迭戈

博客园 首页 新随笔 联系 管理
  11 Posts :: 1 Stories :: 109 Comments :: 0 Trackbacks
  之所以要测试这个方法,是因为项目中要使用该方法动态创建需要对象。  

  上次说了方法Activator.CreateInstance()创建对象和直接用表达式创建对象的性能比较。被老赵等大牛批评测试方法不对,我决定再测试一下,测试环境和第一次一样。
  测试代码如下(其中Form1就是新建的一个WinForm,什么代码都没有写):
代码
 1 Stopwatch watch1 = new Stopwatch();
 2 watch1.Start();
 3 for (int i = 0; i < 10000; i++)
 4 {
 5      Form1 form1 = Activator.CreateInstance(typeof(Form1)) as Form1;
 6 }
 7 
 8 watch1.Stop();
 9 Console.WriteLine("Activator.CreateInstance");
10 Console.WriteLine(watch1.Elapsed.ToString());
11 
12 watch1.Reset();
13 watch1.Start();
14 for (int i = 0; i < 10000; i++)
15 {
16      Form form1 = GetCache.InstanceCacheEx.InstanceCache(typeof(Form1)) as Form1;
17 }
18 watch1.Stop();
19 Console.WriteLine("Expression.CreateInstanceEx");
20 Console.WriteLine(watch1.Elapsed.ToString());

 

而创建Expression Tree的代码如下:
创建Expression Tree,并缓存
 1     public class InstanceCachesEx
 2     {
 3         private Dictionary<Type, Func<object>> dicEx = new Dictionary<Type, Func<object>>();
 4         public object InstanceCache(Type key)
 5         {
 6 
 7             object value = null;
 8 
 9             if (dicEx.TryGetValue(key, out value))
10             {
11                 return value();
12             }
13             else
14             {
15                 value = CreateInstance(key);
16                 dicEx[key] = value;
17                 return value();
18             }
19         }
20 
21         static Func<object> CreateInstance(Type type)
22         {
23             NewExpression newExp = Expression.New(type);
24             Expression<Func<object>> lambdaExp = Expression.Lambda<Func<object>>(newExp, null);
25             Func<object> func = lambdaExp.Compile();
26             return func;
27         }
28     }
29 
30     public static class GetCache
31     {
32         static GetCache()
33         {
34             InstanceCacheEx = new InstanceCachesEx();
35         }
36 
37         public static InstanceCachesEx InstanceCacheEx { getset; }
38     }

测试结果如下:

Activator.CreateInstance:
00:00:00.0140537
Expression.CreateInstanceEx:
00:00:00.7389382

 

 

吆呼,差了这么多......
我们换一个类来试试,来一个简单的类:

public class Class1 { }

再来看看测试结果:

Activator.CreateInstance
00:00:00.0020066
Expression.CreateInstance
00:00:00.0078841

 

 

嗯?结果方法Activator.CreateInstance()比表达式树要快了。
待续......

标签: c#
posted on 2009-12-07 22:11 Will Meng 阅读(1874) 评论(12) 编辑 收藏

Feedback

#1楼 2009-12-07 22:28 Jeffrey Zhao      
谁说Expression Tree不是调用构造器实现的啊?
 回复 引用 查看   

#2楼 2009-12-07 22:36 深山老林      
哈哈,又被批了。兄弟,顶住,咱越挫越勇。
 回复 引用 查看   

#3楼 2009-12-07 22:49 Gray Zhang      
你怎么能把创建好的对象实例缓存了返回给人家呢,除非这个对象是完全无状态的
 回复 引用 查看   

#4楼 2009-12-07 22:50 Gray Zhang      
顶多你缓存表达式就成了……
 回复 引用 查看   

#5楼[楼主] 2009-12-08 08:51 Will Meng      
@Jeffrey Zhao
可能是我表达的产生歧义了,我的意思是用表达式树值需要调用一次对象的构造器来构造对象的实例。对于相同的对象,只要从缓存中取值就可以了。

 回复 引用 查看   

#6楼[楼主] 2009-12-08 08:52 Will Meng      
@Gray Zhang
说的是,等晚上我再重新测试一下。。。
多谢!

 回复 引用 查看   

#7楼 2009-12-08 09:03 Jeffrey Zhao      
@Will Meng
有兄弟已经说了,你缓存错东西了。

 回复 引用 查看   

#8楼[楼主] 2009-12-08 10:17 Will Meng      
@Jeffrey Zhao
错误已经改了。
趁着课间休息的间隙,赶紧把新的测试和想法写了上来。

 回复 引用 查看   

#9楼 2009-12-08 11:48 Ivony...      
刚去Reflector看了一下Activator的实现,的确是有优化的存在。。。

但是绕了半天,我只看到了值类型的优化,引用类型的优化没看着。。。。

 回复 引用 查看   

#10楼 2009-12-08 11:48 古巴[未注册用户]
第11行还是错的吧,应该也是return value();才对吧

 回复 引用   

#11楼 2009-12-08 11:50 Ivony...      
终于找全了引用类型的创建过程。
 回复 引用 查看   

#12楼 2009-12-08 11:52 Ivony...      
话说这就是修改后的程序?

那个Dictionary明明存的是Func<object>咋就能as Form1

 回复 引用 查看