应用办公生活信息教育商业
投稿投诉
商业财经
汽车智能
教育国际
房产环球
信息数码
热点科技
生活手机
晨报新闻
办公软件
科学动态
应用生物
体育时事

为什么要把类设置成密封?

  前几天笔者提交了关于FasterKvCache的性能优化代码,其中有一个点就是我把一些后续不需要继承的类设置为了sealed密封类,然后就有小伙伴在问,为啥这个地方需要设置成sealed?
  提交的代码如下所示:
  一般业务开发的同学可能接触密封类比较少,密封类除了框架设计约束(不能被继承)以外,还有一个微小的性能提升,不过虽然它是一个微小的优化点,多框架开发的作者都会做这样的优化,如果方法调用的频次很高,那也会带来很大的收益。
  笔者最开始是从。NETruntime中的代码学习到这一个优化技巧,后面有看到meziantou大佬的文章performancebenefitsofsealedclass〔1〕完整的学习了一下。
  然后本来是想翻译一下这篇文章,找了下发现Weihan大佬今年年初翻译了meziantou大佬的文章,质量非常高的中文版,大家可以戳链接看看,既然如此在本文中带大家回顾一下文章中例子,另外从JITASM的层面分析为什么性能会有提升。性能优势虚方法调用
  在上面提到的文章例子中,有一个虚方法的调用,大家其实要明白一点,现在面向对象的封装、继承、多态中的多态实现主要就是靠虚方法。
  一个类型可能会有子类,子类可能会重写类型的方法从而达到不同的行为(多态),而这些重写的方法都在虚方法表里,调用的话就需要查表。
  回到文中的代码,大佬构建了一个这样的测试用例:
  publicclassSealedBenchmark
  {
  readonlyNonSealedTypenonSealedTypenew();
  readonlySealedTypesealedTypenew();
  〔Benchmark(Baselinetrue)〕
  publicvoidNonSealed()
  {
  JIT不能知道nonSealedType的实际类型。
  它可能已经被另一个方法设置为派生类。
  所以,为了安全起见,它必须使用一个虚拟调用。
  nonSealedType。Method();
  }
  〔Benchmark〕
  publicvoidSealed()
  {
  JIT确信sealedType是一个SealedType。由于该类是密封的。
  它不可能是一个派生类型的实例。
  所以它可以使用直接调用,这样会更快。
  sealedType。Method();
  }
  }
  基类
  internalclassBaseType
  {
  publicvirtualvoidMethod(){}
  }
  非密封的派生类
  internalclassNonSealedType:BaseType
  {
  publicoverridevoidMethod(){}
  }
  密封的派生类
  internalsealedclassSealedType:BaseType
  {
  publicoverridevoidMethod(){}
  }
  取得的结果就是密封类要比非密封的快98。
  那么为什么会这样呢?首先我们来比较一下两个方法的IL代码,发现是一模一样的,对于方法调用都是用了callvirt(它就是用来调用虚方法的,想了解更多详情可以看这里〔2〕),因为instance是从字段中加载的,编译器无法知道具体的类型,只能使用callvirt。
  那区别在哪里呢?我们可以看到JIT生成后的汇编代码,可以很清楚的看到密封类少了两条指令,因为JIT可以从密封类中知道它不可能被继承,也不可能被重写,所以是直接跳转到密封类目标方法执行,而非密封类还有一个查表的过程。而现在很多大佬聊天说JIT的去虚拟化其实主要就是在JIT编译时去除了callvirt调用。
  另外文中也提到了一段代码,如果JIT能确定类型,也是直接调用的:
  voidNonSealed()
  {
  varinstancenewNonSealedType();
  instance。Method();JIT知道instance是NonSealedType,因为它是在方法中被创建的,
  从未被修改过,所以它使用直接调用
  }
  voidSealed()
  {
  varinstancenewSealedType();
  instance。Method();JIT知道类型是SealedType,所以直接调用
  }
  此时两者的汇编代码没有任何区别,都是直接jmp到目标方法。
  发现一个有趣的东西,如果我们切到。NETFramework的JIT,可以发现。NETFramework的JIT没有。NET生成的这么高效,没有直接jmp到目标方法,而是多了一层call和ret。所以,朋友们还等什么呢?快升级。NET版本吧。对象类型转换(isas)
  同样有下面这样一段代码,测试密封类和非密封类的对象类型转换性能:
  publicclassSealedBenchmark
  {
  readonlyBaseTypebaseTypenew();
  〔Benchmark(Baselinetrue)〕
  publicboolIsSealed()baseTypeisSealedType;
  〔Benchmark〕
  publicboolIsNonSealed()baseTypeisNonSealedType;
  }
  internalclassBaseType{}
  internalclassNonSealedType:BaseType{}
  internalsealedclassSealedType:BaseType{}
  毫无疑问,密封类快91。
  IL层面,两个方法都是一模一样:
  可以看到密封类的代码相当高效,直接比较一下就转换类型返回了,而非密封类还需要call方法走查表流程:数组
  。NET的数组是协变的,协变兼容的话就意味着在添加进入数组时需要检查它的类型,而如果是密封类那就可以删除检查,同样有下面一段代码:
  publicclassSealedBenchmark
  {
  SealedType〔〕sealedTypeArraynewSealedType〔100〕;
  NonSealedType〔〕nonSealedTypeArraynewNonSealedType〔100〕;
  〔Benchmark(Baselinetrue)〕
  publicvoidNonSealed()
  {
  nonSealedTypeArray〔0〕newNonSealedType();
  }
  〔Benchmark〕
  publicvoidSealed()
  {
  sealedTypeArray〔0〕newSealedType();
  }
  }
  internalclassBaseType{}
  internalclassNonSealedType:BaseType{}
  internalsealedclassSealedType:BaseType{}
  密封类的性能要高14左右。
  打开IL代码,两者编译出的方法都是一样的,但是跳转到汇编代码可以发现差别,同样的是Stelem。Ref给数组赋值,密封类只是检查了一下数组长度,然后直接赋值,而非密封类还需要调用System。Runtime。CompilerServices。CastHelpers。StelemRef进行检查才能完成赋值。将数组转换为Span
  和数组一样,将数组转换为Span时也需要插入类型检查,有如下测试代码:
  publicclassSealedBenchmark
  {
  SealedType〔〕sealedTypeArraynewSealedType〔100〕;
  NonSealedType〔〕nonSealedTypeArraynewNonSealedType〔100〕;
  〔Benchmark(Baselinetrue)〕
  publicSpanNonSealed()nonSealedTypeArray;
  〔Benchmark〕
  publicSpanSealed()sealedTypeArray;
  }
  publicclassBaseType{}
  publicclassNonSealedType:BaseType{}
  publicsealedclassSealedType:BaseType{}
  密封类的性能要高50:
  同样,这也是IL一模一样的,在JIT阶段做的优化,可以明显的看到,JIT为非密封类单独做了类型检查:总结
  笔者在FasterKvCache代码中将一些类设置为sealed的原因显而易见:为了让类的职责更加清晰,在设计中没有计划让它有派生类为了性能的提升,JIT优化可以让其方法调用更快
  还有更多有趣的东西(比如IDE智能提示将类设置为密封,如何使用dotnetformat集成这些分析),大家可以翻阅原文或者Weihan大佬翻译的文章。https:www。meziantou。netperformancebenefitsofsealedclass。htmhttps:mp。weixin。qq。comsdZlEjOB8jx0ku8eN8AhpzQ。NET性能优化交流群
  相信大家在开发中经常会遇到一些性能问题,苦于没有有效的工具去发现性能瓶颈,或者是发现瓶颈以后不知道该如何优化。于是很高兴的在这里宣布,我创建了一个专门交流。NET性能优化经验的群组,主题包括但不限于:如何找到。NET性能瓶颈,如使用APM、dotnettools等工具。NET框架底层原理的实现,如垃圾回收器、JIT等等如何编写高性能的。NET代码,哪些地方存在性能陷阱
  希望能有更多志同道合朋友加入,分享一些工作中遇到的。NET性能问题和宝贵的性能分析优化经验。由于已经达到200人,可以加我微信,我拉你进群:ls1075
  参考资料
  〔1〕
  performancebenefitsofsealedclass:https:www。meziantou。netperformancebenefitsofsealedclass。htm
  〔2〕
  这里:https:learn。microsoft。comzhcndotnetapisystem。reflection。emit。opcodes。callvirt?viewnet7。0

TES战胜XYG,湘军发文称拳头就是大,XYG一波虐泉让上野王者荣耀挑战者杯正赛已经正式开战,第一场比赛就非常精彩,XYG和TES打到了巅峰对决,最终TES更胜一筹,成功挺进四强。比赛获胜之后,打野湘军也非常激动,直接发文表示拳头就是大……龙途天下宝石系统宝石系统有哪些作用龙途天下宝石系统攻略大家好,今天小编想跟大家分享一下龙途天下宝石系统有哪些作用宝石系统说明。感兴趣的小伙伴那就接着往下看吧。本文转自怀旧传奇手游盒子。宝石系统说明宝石镶嵌在全身各个部位,与装……从3499元跌至跌至1087元,骁龙8555000mAh大电我们查看了当前市面上在9001100元价位段的手机,很多品牌厂商都推出了这个价位段的手机,包括vivoiQOOU3x、RedmiNote94G、荣耀Play5T、RedmiNo……高糖饮食01hr一看到高糖饮食这四个字,很多看众一定会觉得奇怪!现在糖尿病人那么多,不是提倡低糖饮食吗?高糖食物两会事。况且糖尿病的发生不是因为糖多,而是因为身体的组织细胞……空调开多少度制冷最省电空调开多少度制冷最省电?关于这个问题赵宇今天和大家分享一下,那么开多少度制冷最省电。我们正常在制冷的时候,我们的设定温度和省电和费电有直接关系。那么怎么设定最省电呢。遥控……九岭山深处奏响青春之歌来源:人民网人民日报江西九岭山国家级自然保护区。本报记者朱磊摄彭勇(中)和同事巡山时发现一株细茎石斛。周亮摄(人民视觉)核心阅读近年来,江西九岭山国家级……双休中国股市不开盘,刚刚得知1则重磅消息,明天行情怎么走?周末A股不开盘,但是消息面却很不平静,美联储重磅讲话,竟让美股大崩盘,究竟发生了什么?对于A股有什么影响?本期文章给大家一个观点鲜明的解读,听完认可的朋友关注点赞评论走一波,下……中国女排35岁的北长城至今单身,郎平最期待的球员婚礼就是她在张常宁结婚之后,目前最热议的话题就是朱婷,朱婷什么时候结婚让非常多球迷都非常期待,像朱婷这种比较优秀的球员是一名世界级别的主攻手,不仅是中国的球迷会非常期待,包括国外的一些朱……女子以为儿子偷钱请人吃喝,拿起奶茶淋在女生头上,后续来了优秀的孩子源自优秀的教育,而教育又分为学校教育跟家庭教育两个方面,虽然学校教育比较重要,但家庭教育也是不能缺少。家长是孩子的第一任人生导师,应该有以身作则,把给孩子往好的……第二届消博会今天起所有展馆正式对外开放原标题:第二届中国国际消费品博览会今天起所有展馆正式对外开放第二届中国国际消费品博览会昨天在海南海口开幕。今天起至28日为本届消博会的专业观众日,29日、30日为社会公众……目前拍照出色的4款性价比手机,兼顾性能与影像,关键价格还不贵现在大家对手机的拍照要求越来越高,如果你最近有换机需求,但预算并不高,还想兼顾性能和拍照的话,那么分享以下4款拍照出色的性价比手机,影像性能都出众,关键价格还不贵,流畅三五年不……全面战争战锤3混沌冠军勇士DLC试玩报告体会《全面战争战锤3》的全部内容并不是一个轻松的活儿,雄伟且容量惊人的布景设定和历代著作所堆集下来的经验设计,让这部著作的每一个细节都需求你投入满足的时间去了解学习,毫无疑问的……
明星作假的秘密藏不住了,假头假发假屁股,半个娱乐圈都纷纷中招老话说得好金无足赤,人无完人。,这句话放在娱乐圈里也同样适用。镜头前的明星个个脸蛋精致、仪态万千,身材前凸后翘,在耀眼的聚光灯下,仿佛他们的毛孔都在发着光。但事实真……可以称之为录音转写王者科大讯飞智能录音笔SR502使用体验说起录音笔,大家肯定都不会陌生,即使现在各种电子产品的录音质量都有较大的提升,但是录音笔作为更专业的录音设备是手机和其他录音产品无法替代的,而说到国内的录音笔品牌,科大讯飞在第……被何炅提拔,被节目组力捧,湖南卫视台柱苗子终于显露出来了01一群人的坚持,一群人的青春啥也别说了,《你好,星期六》节目组给何炅磕一个吧!从这档节目开始,何炅就一带多强撑着。没话找话,没梗找梗,没笑点就硬笑,新人嘉宾……李东生的TCL,站在资本与产业的交叉路口文三生出品节点财经2022年,TCL创始人、董事长李东生年满65岁。与他同时代的老对手,如长虹的倪润峰、创维的黄宏生、海尔的张瑞敏等均已先后隐退江湖,而他仍活跃在商……星巴克换帅面临多重挑战袁勇星巴克近日宣布,英国家庭用品巨头利洁时CEO纳拉辛汉将从今年10月1日起担任星巴克候任CEO,并将于2023年4月1日正式就任星巴克CEO。纳拉辛汉曾就职于麦肯锡和百……36氪首发映驰科技获近亿元B1轮融资,大陆商汤联合领投,地平文李安琪编辑苏建勋36氪获悉,近日智能驾驶高性能计算软件平台企业映驰科技获得近亿元B1轮融资,本轮融资由大陆集团和商汤国香资本联合领投,老股东地平线持续追加投资。……8月发售的热门游戏蜘蛛侠忍者神龟羔羊崇拜等准备好了吗?8月就要到了,如果您正在寻找一些可以在Xbox、PlayStation、Switch和PC上玩的新游戏,那么这几款将让你爱不释手。两点校园(8月9日)欢迎来到……高色域,分区背光,MiniLED和OLED,同尺寸各类电视差最近总有朋友问,她想买一台电视,但技术太多了,让她摸不清头脑,具体要买哪种,谁的技术好,她也是一团浆糊。具体来说,她提到了高色域,分区背光,MiniLED和OLED这些名……鼻塞嗅觉异常怎么办?试试这几个妙招鼻塞、嗅觉异常怎么办?试试这几个妙招按摩三个穴位缓解症状01迎香穴在鼻翼外缘中点旁,当鼻唇沟中。鼻子的下缘和鼻唇沟的交点位置,有一个凹陷,用指腹压时有酸胀感,……桃源仙境古致游古致自然村,隐于灶山之西面深山老林之中,属赤土乡溪东村,是漳浦余存不多的高海拔村社。从县道524湖西往赤土方向到岭顶有三叉岔路口,左转离开县道,蜿蜒而上约二公里见一古寨,……TA来了,让怒江的激情触动世界的心跳来源:云境数字文创云境数字研究院我是云南的,云南怒江的怒江泸水市是谁?哼着年度魔性歌曲向我们走来了?峡谷里的划水英雄?野水中的搏浪勇士!怒江……无论你当下正在经历什么,心态,才是归属于你自己的风水!陈丹青在一次采访中说:活在今天,你必须足够无耻才能有机会撑下去,机会都留给了机会主义者,必须足够无耻这六个字,刻板、刺眼、尖锐、实用。12月25日了,该阳过的已经阳过、大……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网