各大主流.Net的IOC框架性能測試比較
我簡單介紹過Autofac的使用,有人希望能有個(gè)性能上的測試,考慮到有那么多的IOC框架,而主流的有:Castle Windsor、微軟企業(yè)庫中的Unity、Spring.NET、StructureMap、Ninject等等。本篇文章主要針對這些IOC框架編寫測試程序。
Autofac下載地址:http://code.google.com/p/autofac/
Castle Windsor下載地址:http://sourceforge.net/projects/castleproject/files/Windsor/2.5/Castle.Windsor.2.5.3.zip/download
Unity下載地址:http://entlib.codeplex.com/
Spring.NET下載地址:http://www.springframework.net/
StructureMap下載地址:http://sourceforge.net/projects/structuremap/files/
Ninject下載地址:http://ninject.org/download
其中,測試程序均采用***的類庫。
基礎(chǔ)工作
1、程序還是引用上一篇的示例作為測試背景。
2、編寫一個(gè)性能計(jì)數(shù)器,這里我采用老趙寫的一個(gè)CodeTimer的類,具體介紹見:http://www.cnblogs.com/JeffreyZhao/archive/2009/03/10/codetimer.html
使用方式類似于:
- int iteration = 100 * 1000;string s = "";
 - CodeTimer.Time("String Concat", iteration, () => { s += "a"; });
 - StringBuilder sb = new StringBuilder();
 - CodeTimer.Time("StringBuilder", iteration, () => { sb.Append("a"); });
 
3、編寫一個(gè)IRunner運(yùn)行接口:
- public interface IRunner
 - {
 - void Start(RunType runType);
 - }
 
以及RunnerBase抽象基礎(chǔ)運(yùn)行類:
- public abstract class RunnerBase
 - {
 - private int _iteration = Convert.ToInt32(System.Configuration.ConfigurationSettings.AppSettings["Iteration"] ?? "10000");
 - internal int Iteration
 - {
 - get { return _iteration; }
 - }
 - internal void Time(Action action)
 - {
 - CodeTimer.Time(Name, Iteration, action);
 - }
 - protected abstract string Name { get; }
 - }
 
這里_iteration表示測試運(yùn)行次數(shù),通過配置文件來設(shè)置值。Time方法通過計(jì)數(shù)器對action方法進(jìn)行Iteration次迭代。
編寫一個(gè)RunManager的運(yùn)行管理器:
- public class RunManager
 - {
 - public static void Start(IRunner runner)
 - {
 - Start(runner, RunType.Transient);
 - }
 - public static void Start(IRunner runner, RunType runType)
 - {
 - runner.Start(runType);
 - }
 - }
 
在測試中,我采用兩種方式的性能比較,一個(gè)是單例狀態(tài),一個(gè)是非單例狀態(tài):
- /// <summary>
 - /// 運(yùn)行狀態(tài)
 - /// </summary>
 - public enum RunType
 - {
 - /// <summary>
 - /// 單例
 - /// </summary>
 - Singleton,
 - /// <summary>
 - /// 瞬時(shí)
 - /// </summary>
 - Transient
 - }
 
好了,現(xiàn)在我的程序只要繼承RunnerBase以及IRunnre接口,就可以實(shí)現(xiàn)各個(gè)IOC框架的初始化裝配的工作了?;A(chǔ)工作已經(jīng)做好。
#p#
各個(gè)IOC框架測試程序
1、Autofac:
- public class AutofacRunner : RunnerBase, IRunner
 - {
 - protected override string Name
 - {
 - get { return "Autofac"; }
 - }
 - public void Start(RunType runType)
 - {
 - var builder = new ContainerBuilder();
 - //if (runType == RunType.Singleton)
 - // builder.RegisterType<DatabaseManager>().SingleInstance();
 - //else
 - // builder.RegisterType<DatabaseManager>();
 - //builder.RegisterType<SqlDatabase>().As<IDatabase>();
 - ////builder.RegisterModule(new ConfigurationSettingsReader("autofac"));
 - builder.RegisterType<SqlDatabase>().As<IDatabase>();
 - if (runType == RunType.Singleton)
 - builder.Register(c => new DatabaseManager(c.Resolve<IDatabase>())).SingleInstance();
 - else
 - builder.Register(c => new DatabaseManager(c.Resolve<IDatabase>()));
 - var container = builder.Build();
 - Time(() =>
 - {
 - var manager = container.Resolve<DatabaseManager>();
 - manager.Search("SELECT * FROM USER");
 - });
 - container.Dispose();
 - }
 - }
 
2、Castle Windsor:
- public class WindsorRunner : RunnerBase, IRunner
 - {
 - protected override string Name
 - {
 - get { return "Castle Windsor"; }
 - }
 - public void Start(RunType runType)
 - {
 - var container = new WindsorContainer();
 - if(runType == RunType.Singleton)
 - container.Register(Component.For(typeof(DatabaseManager)).LifeStyle.Singleton);
 - else
 - container.Register(Component.For(typeof(DatabaseManager)).LifeStyle.Transient);
 - container.Register(Component.For(typeof(IDatabase)).ImplementedBy(typeof(SqlDatabase)));
 - Time(() =>
 - {
 - var manager = container.Resolve<DatabaseManager>();
 - manager.Search("SELECT * FROM USER");
 - });
 - }
 - }
 
3、Unity:
- public class UnityRunner : RunnerBase, IRunner
 - {
 - protected override string Name
 - {
 - get { return "Unity"; }
 - }
 - public void Start(RunType runType)
 - {
 - var container = new UnityContainer();
 - if(runType == RunType.Singleton)
 - container.RegisterType<DatabaseManager>(new ContainerControlledLifetimeManager());
 - else
 - container.RegisterType<DatabaseManager>(new TransientLifetimeManager());
 - container.RegisterType<IDatabase, SqlDatabase>();
 - Time(() =>
 - {
 - var manager = container.Resolve<DatabaseManager>();
 - manager.Search("SELECT * FROM USER");
 - });
 - }
 - }
 
4、Spring.NET:
- public class SpringRunner : RunnerBase, IRunner
 - {
 - protected override string Name
 - {
 - get { return "Spring.NET"; }
 - }
 - public void Start(RunType runType)
 - {
 - string databaseManagerName;
 - if (runType == RunType.Singleton)
 - databaseManagerName = "DatabaseManager_Singleton";
 - else
 - databaseManagerName = "DatabaseManager_Transient";
 - Time(() =>
 - {
 - IApplicationContext context = ContextRegistry.GetContext();
 - var manager = (DatabaseManager)context.GetObject(databaseManagerName);
 - manager.Search("SELECT * FROM USER");
 - });
 - }
 - }
 
5、StructureMap:
- public class StructureMapRunner : RunnerBase, IRunner
 - {
 - protected override string Name
 - {
 - get { return "StructureMap"; }
 - }
 - public void Start(RunType runType)
 - {
 - ObjectFactory.Initialize(container =>
 - {
 - if (runType == RunType.Singleton)
 - container.ForRequestedType<DatabaseManager>().Singleton();
 - else
 - container.ForRequestedType<DatabaseManager>();
 - container.ForRequestedType<IDatabase>().TheDefaultIsConcreteType<SqlDatabase>();
 - });
 - Time(() =>
 - {
 - var manager = ObjectFactory.GetInstance<DatabaseManager>();
 - manager.Search("SELECT * FROM USER");
 - });
 - }
 - }
 
6、Ninject:
- public class NinjectRunner : RunnerBase, IRunner
 - {
 - protected override string Name
 - {
 - get { return "Ninject"; }
 - }
 - public void Start(RunType runType)
 - {
 - IKernel kernel = new StandardKernel(new MyNinjectModule(runType));
 - Time(() =>
 - {
 - var manager = kernel.Get<DatabaseManager>();
 - manager.Search("SELECT * FROM USER");
 - });
 - }
 - }
 
客戶端測試程序
- static void Main(string[] args)
 - {
 - CodeTimer.Initialize();
 - Console.WriteLine("IOC - Singleton");
 - // Autofac Singleton
 - RunManager.Start(new AutofacRunner(), RunType.Singleton);
 - // Castle Windsor
 - RunManager.Start(new WindsorRunner(), RunType.Singleton);
 - // Unity
 - RunManager.Start(new UnityRunner(), RunType.Singleton);
 - // Spring.NET
 - RunManager.Start(new SpringRunner(), RunType.Singleton);
 - // StructureMap
 - RunManager.Start(new StructureMapRunner(), RunType.Singleton);
 - // Ninject
 - RunManager.Start(new NinjectRunner(), RunType.Singleton);
 - Console.WriteLine("===================================");
 - Console.WriteLine("IOC - Transient");
 - // Autofac Singleton
 - RunManager.Start(new AutofacRunner(), RunType.Transient);
 - // Castle Windsor
 - RunManager.Start(new WindsorRunner(), RunType.Transient);
 - // Unity
 - RunManager.Start(new UnityRunner(), RunType.Transient);
 - // Spring.NET
 - RunManager.Start(new SpringRunner(), RunType.Transient);
 - // StructureMap
 - RunManager.Start(new StructureMapRunner(), RunType.Transient);
 - // Ninject
 - RunManager.Start(new NinjectRunner(), RunType.Transient);
 - Console.ReadKey();
 - }
 
通過修改App.config的Iteration配置值,來設(shè)置迭代次數(shù)。
- <appSettings>
 - <add key="Iteration" value="100000" />
 - </appSettings>
 
運(yùn)行結(jié)果
1、Iteration=1000:

分析:在千數(shù)量級時(shí),Autofac,CastleWindsor、StructureMap基本差不多,效率上比其他的要高。
2、Iteration=10000:

分析:在萬數(shù)量級時(shí),Autofac,CastleWindsor,StructureMap基本效率還是差不多,其中StructureMap效率稍稍有些下降;Spring.NET以及Ninject的性能比較低。
3、Iteration=100000:

分析:在十萬數(shù)量級時(shí),CastleWindsor的效率開始下降,而在Transient方面,StructureMap和Autofac基本差不多。
4、Iteration=1000000:

分析:在百萬數(shù)量級時(shí),Autofac和StructureMap兩者還是保持比較高的效率,并且在Transient方面,StructureMap已經(jīng)超過了Autofac。
總結(jié):從測試中,可以看出Autofac和StructureMap在性能上面還是體現(xiàn)出比較大的優(yōu)勢,Ninject可以說性能上較低。而Spring.NET不僅僅專注于IOC方面,它還專注于其他方方面面的功能,所以在IOC方面的性能不是太高。另外,微軟的Unity中規(guī)中矩,性能較為穩(wěn)定,也是一個(gè)不錯的選擇。另外,可能測試程序會有所偏差,希望大家也能夠指出問題!
測試程序源代碼:IOCPerformanceTest.rar
原文:http://www.cnblogs.com/liping13599168/archive/2011/07/17/2108734.html
【編輯推薦】















 
 
 








 
 
 
 