.Net中各种不同的对象创建方式的速度差异(三)

作者:小菜 更新时间:2025-02-21 点击数:
简介:从前面的文章,我们发现以下两点有趣的东西:1、使用System.Activator的非泛型方法比使用泛型方法快很多(超过200%) 2、使用泛型约束和new关键

【菜科解读】

从前面的文章,我们发现以下两点有趣的东西:

1、使用System.Activator的非泛型方法比使用泛型方法快很多(超过200%) 2、使用泛型约束和new关键字创建的速度几乎和System.Activator的泛型方法的一样 在这篇文章里,我将会这两个问题做一个进一步的探究,我使用的工具就是鼎鼎大名的.Net反编译工具:Reflector,欢迎读者跟我一起探讨造成这个现象的原因。

第一段 从System.Activator.CreateInstance(Type)开始我们先用Reflector打开.net framework 3.5中的mscorlib.dll,看看这里面,微软是怎么实现的。

首先看看System.Activator.CreateInstance(Type),它直接调用了System.Activator.CreateInstance(Type, Boolean),代码如下

1 public static object CreateInstance(Type type)

2 {

3 return CreateInstance(type, false);

4 }

那么这个CreateInstance(Type, Boolean)的实现,是这样的:

01 public static object CreateInstance(Type type, bool nonPublic)

02 {

03 if (type == null)

04 {

05 throw new ArgumentNullException("type");

06 }

07 RuntimeType underlyingSystemType = type.UnderlyingSystemType as RuntimeType;

08 if (underlyingSystemType == null)

09 {

10 throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "type");

11 }

12 return underlyingSystemType.CreateInstanceImpl(!nonPublic);

13 }

将这段代码简化一下,就是:

1 public static object CreateInstance(Type type, bool nonPublic)

2 {

3 RuntimeType underlyingSystemType = type.UnderlyingSystemType as RuntimeType;

4 return underlyingSystemType.CreateInstanceImpl(!nonPublic);

5 }

在RuntimeType的CreateInstanceImpl(bool isPublic)中,直接调用了CreateInstanceImpl(bool isPublic, bool skipVisibilityCheck, bool fillCache),这个函数的实现非常有意思,我先把代码贴出来:

01 internal object CreateInstanceImpl(bool publicOnly, bool skipVisibilityChecks, bool fillCache)

02 {

03 RuntimeTypeHandle typeHandle = this.TypeHandle;

04 ActivatorCache cache = s_ActivatorCache;

05 if (cache != null)

06 {

07 ActivatorCacheEntry entry = cache.GetEntry(this);

08 if (entry != null)

09 {

10 if ((publicOnly && (entry.m_ctor != null)) && ((entry.m_hCtorMethodHandle.GetAttributes() & MethodAttributes.MemberAccessMask) != MethodAttributes.Public))

11 {

12 throw new MissingMethodException(Environment.GetResourceString("Arg_NoDefCTor"));

13 }

14 object obj2 = typeHandle.Allocate();

15 if (entry.m_ctor != null)

16 {

17 if (!skipVisibilityChecks && entry.m_bNeedSecurityCheck)

18 {

19 MethodBase.PerformSecurityCheck(obj2, entry.m_hCtorMethodHandle, this.TypeHandle.Value, 0x10000000);

20 }

21 try

22 {

23 entry.m_ctor(obj2);

24 }

25 catch (Exception exception)

26 {

27 throw new TargetInvocationException(exception);

28 }

29 }

30 return obj2;

31 }

32 }

33 return this.CreateInstanceSlow(publicOnly, fillCache);

34 }

看起来非常复杂,其实他的实现也也就实现了一个缓存机制:

检查缓存中是否存在这个构造器的委托,如果有,就调用自己的typeHandler的Allocate()方法分配内存,然后调用构造器的委托初始化对象 如果没有缓存,就调用CreateInstanceSlow(bool isPublic, bool fillCache)创建对象,并填充缓存 好吧继续再看看这个CreateInstanceSlow里面干了什么事情。

照例先贴代码吧:

01 private object CreateInstanceSlow(bool publicOnly, bool fillCache)

02 {

03 RuntimeMethodHandle emptyHandle = RuntimeMethodHandle.EmptyHandle;

04 bool bNeedSecurityCheck = true;

05 bool canBeCached = false;

06 bool noCheck = false;

07 this.CreateInstanceCheckThis();

08 if (!fillCache)

09 {

10 noCheck = true;

11 }

12 object obj2 = RuntimeTypeHandle.CreateInstance(this, publicOnly, noCheck, ref canBeCached, ref emptyHandle, ref bNeedSecurityCheck);

13 if (canBeCached && fillCache)

14 {

15 ActivatorCache cache = s_ActivatorCache;

16 if (cache == null)

17 {

18 cache = new ActivatorCache();

19 Thread.MemoryBarrier();

20 s_ActivatorCache = cache;

21 }

22 ActivatorCacheEntry ace = new ActivatorCacheEntry(this, emptyHandle, bNeedSecurityCheck);

23 Thread.MemoryBarrier();

24 cache.SetEntry(ace);

25 }

26 return obj2;

27 }

这个函数写的很复杂,其实实现的东西很简单,其一是调用RuntimeTypeHandler.CreateInstance方法创建对象,然后再填充缓存,以加快下次创建对象的速度。

好了,我们现在已经非常接近事实的真相了。

让我们从另外一个角度出发,看看CreateInstance()干了什么事情。

第二段 从System.Activator.CreateInstance()开始这里,我们先看看他的实现:

1 public static T CreateInstance()

2 {

3 bool bNeedSecurityCheck = true;

4 bool canBeCached = false;

5 RuntimeMethodHandle emptyHandle = RuntimeMethodHandle.EmptyHandle;

6 return (T) RuntimeTypeHandle.CreateInstance(typeof(T) as RuntimeType, true, true, ref canBeCached, ref emptyHandle, ref bNeedSecurityCheck);

7 }

我们忽然就看到了我们熟悉的身影:RuntimeTypeHandler.CreateInstance方法,终于殊途同归啊。

也就是说,System.Activator.CreateInstance()相当于调用了CreateInstanceSlow方法(但是没有缓存机制),这应该就是CreateInstance比CreateInstance(Type)慢的主要原因,我们回顾一下这两个方法的时间消耗:System.Activator.CreateInstance(Type):

缓存机制时间消耗 RuntimeTypeHandler.Allocate()内存分配的时间消耗 调用构造器委托初始化数据的时间消耗 这里不考虑缓存失败,调用CreateInstanceSlow的情况,因为这个只会发生一次。

System.Activator.CreateInstance(Type):

调用RuntimeTypeHandler.CreateInstance的时间消耗 在下一篇文章中,我会对这两个函数的性能差异做进一步的分析

.Net,中,各种,不同,的,对象,创建,方式,速度,

在俄国的沙皇当中为什么还有一个德国人?这个德国人什么来历

话说,如果我们提起俄国的沙皇,学过历史的人,估计就知道,至少也有几十个。

然而,在这几十个沙皇当中能够获得大帝荣誉称号的却仅仅只有两人。

但就在这两人当中,还曾经有过一个德国人。

那么,这究竟是怎么回事呢?下面我们就一起前往查看一番。

事实上,要想这件事情说清楚,就不能不提。

想当初,当彼得大帝打败了瑞典,夺取了波罗的海沿岸广大地区之后,他的野心就更加膨胀了,甚至,他还企图获得整个海域的控制权。

然而,由于当时波罗的海沿岸最大的国家却是德国,而俄国一时间又战胜不了德国,于是乎,彼得大帝就想到了“和亲”,把自己的大女儿嫁给了一位德国的亲王。

而在彼得大帝死后,就由他小女儿做了俄国的沙皇。

然而,令彼得大帝死都没有想到的是,他的小女儿一生竟然没有生孩子。

于是乎,没有办法,他的小女儿,也就是俄国的女沙皇,就去德国将自己的亲外甥领养了过来,并取名彼得三世。

而彼得三世从德国过来做皇太子的时候,也把他的未婚妻索菲亚给从德国带了过来,另取了一个俄国名字叫叶卡特琳娜。

当然,作为德国人,叶卡特琳娜刚到俄国的时候,俄语都不会说,几乎与人无法沟通。

但是,既聪明又机智的叶卡特琳娜却苦学俄语,并研究俄国历史,甚至,他的婆婆越是讽刺她,她就越是孝敬她婆婆。

因此,没过几年,就在宫里扎下了根。

不仅如此,大家都知道,宫里的女人一般都是“母凭子贵”,也许是该着叶卡特琳娜发达,她的肚子非常争气,很快就给皇太子生了一个儿子。

而女沙皇一见自己有了,也是,马上就奖励了她10万卢布。

但是,令谁都没有想到的是,叶卡特琳娜在收到这一笔钱之后,竟然没有用来自己花销,而是收买了朝廷内外的许多贵族和军官,从此,她的势力是越来越大。

此后,当时光走到了1761年底的时候,她的婆婆——女沙皇去世了。

他的丈夫就成为了新的沙皇。

而她也随之成为了皇后。

但是,对于皇后这个职位,叶卡特琳娜却始终并不知足。

于是,她就开始秘密策划,想着要把自己的老公搞掉,由自己继承沙皇。

显然,无怪乎古人说:“最毒不过妇人心”,此话不假。

不过,这可是掉脑袋的事情,必须小心从事。

叶卡特琳娜也不敢大意。

于是,她就先是对内串通了两名近卫军的高级军官,对外买通了一名英国大使,随后,就发动了一起宫廷政变,将自己的丈夫给杀死了。

然后,自己堂而皇之登上了俄国沙皇的宝座。

当然,不过话又说回来了,这个女人确实有能力,比她老公强100倍。

在她统治俄国的34年当中,不但先后打败了土耳其、波兰等国,还攫取了黑海沿岸的大片土地,从而使俄国的领土一下子就扩大了63万平方公里,对于俄国后来的版图作出了重大贡献。

因此,她和一样,被俄国人尊称为“大帝”。

随机文章阿帕奇战斗机杀伤力惊人,海湾战争中摧毁500辆坦克莫比乌斯环象征着什么,无限循环(象征永恒无限的爱情)北极为什么有蚊子,北极蚊子凶猛无比(一口气吸光麋鹿的血)地震为什么预测不到,动物异象预测真的靠谱吗/准确率极低古代骂读书人的时候,为什么要骂穷秀才?

中国古时候最强冷兵器陌刀,人马挡之俱碎

在冷兵器时代,兵器的先进水平决定了军队在作战过程中的杀伤力,有较好装备配置的部队,取得胜利的可能性会大大提高。

在我国古代,冷兵器的制作工艺达到了巅峰水准,杀伤力巨大的冷兵器以各种各样的形式出现,所谓,各有优劣。

不过说到单兵作战最强的一种兵器,那就是这种出自于唐朝的重型长刀了,也叫做陌刀,这种武器又长又重,是专门针对骑兵的一种重型武器。

著名唐朝将领李陌藩手下就有一只陌刀队,史书上记载,在陌刀阵之前,人马挡之俱碎,可谓是杀力巨大。

众所周知,日本受唐朝文化的影响极大,就连世界著名的武士刀也是仿制唐刀而来,那么陌刀这种杀力巨大的兵器,日本当然也十分想要武装到部队手中,只不过因为陌刀制作成本太高,而且日本也很少有面对大量骑兵的机会,所以并没有成功仿制出陌刀这种武器。

当然,由于陌刀在唐朝是不允许私人收藏和陪葬的,所以现在也已经失传了,目前只能从书上了解到这种兵器,虽然现代有很多武器爱好者在仿造陌刀,但历史上真正的陌刀终究是不可能被百分百还原的。

在古代,兵器的重要性,但并不是能够决定战场胜负的关键,真正的胜负手,主要还是看双方国力,而在局部战役中,那就要看领军主帅的军事谋略了。

在古代战争中,这样的战役比比皆是,以弱胜强全靠主帅卓越的领军能力和军事谋略,所以兵器的先进仅是决定胜负的一个方面而已。

随机文章戊戌变法的意义中国ufo视频震惊世界造谣,画面看起来连三岁小孩都骗不了!探山东双乳峰诅咒,挖山者接连死亡/外形似少女的双乳黑天鹅事件是什么意思,出乎人们意料之外的事(重庆啤酒破产)蒙娜丽莎的背后骷髅头,纪念丽莎·盖拉尔迪尼逝去的儿子

加入收藏
               

.Net中各种不同的对象创建方式的速度差异(三)

点击下载文档

格式为doc格式

  • 账号登录
社交账号登录