各大主流.Net的IOC框架性能测试比较

开发 后端
我简单介绍过Autofac的使用,有人希望能有个性能上的测试,考虑到有那么多的IOC框架,而主流的有:Castle Windsor、微软企业库中的Unity、Spring.NET、StructureMap、Ninject等等。本篇文章主要针对这些IOC框架编写测试程序。

我简单介绍过Autofac的使用,有人希望能有个性能上的测试,考虑到有那么多的IOC框架,而主流的有:Castle Windsor、微软企业库中的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

其中,测试程序均采用***的类库。

基础工作

1、程序还是引用上一篇的示例作为测试背景。

2、编写一个性能计数器,这里我采用老赵写的一个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"); }); 
  • 1.
  • 2.
  • 3.
  • 4.

3、编写一个IRunner运行接口:

public interface IRunner   
{   
    void Start(RunType runType);   

  • 1.
  • 2.
  • 3.
  • 4.

以及RunnerBase抽象基础运行类:

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; }   
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

这里_iteration表示测试运行次数,通过配置文件来设置值。Time方法通过计数器对action方法进行Iteration次迭代。

编写一个RunManager的运行管理器:

public class RunManager   
{   
    public static void Start(IRunner runner)   
    {   
        Start(runner, RunType.Transient);   
    }  
 
    public static void Start(IRunner runner, RunType runType)   
    {   
        runner.Start(runType);   
    }   

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

在测试中,我采用两种方式的性能比较,一个是单例状态,一个是非单例状态:

/// <summary>   
/// 运行状态   
/// </summary>   
public enum RunType   
{   
    /// <summary>   
    /// 单例   
    /// </summary>   
    Singleton,  
 
    /// <summary>   
    /// 瞬时   
    /// </summary>   
    Transient   
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

好了,现在我的程序只要继承RunnerBase以及IRunnre接口,就可以实现各个IOC框架的初始化装配的工作了。基础工作已经做好。

#p#

各个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();   
    }   
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

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");   
        });   
    }   
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

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");   
            });   
    }   
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

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");   
        });   
    }   
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

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");   
            });   
    }   
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

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");   
        });   
    }   
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

客户端测试程序

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();   
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

通过修改App.config的Iteration配置值,来设置迭代次数。

<appSettings>   
  <add key="Iteration" value="100000" />   
</appSettings>  
  • 1.
  • 2.
  • 3.

 

运行结果

1、Iteration=1000:

 

image

 

分析:在千数量级时,Autofac,CastleWindsor、StructureMap基本差不多,效率上比其他的要高。

2、Iteration=10000:

 

image

 

分析:在万数量级时,Autofac,CastleWindsor,StructureMap基本效率还是差不多,其中StructureMap效率稍稍有些下降;Spring.NET以及Ninject的性能比较低。

3、Iteration=100000:

 

image

 

分析:在十万数量级时,CastleWindsor的效率开始下降,而在Transient方面,StructureMap和Autofac基本差不多。

4、Iteration=1000000:

 

image

 

分析:在百万数量级时,Autofac和StructureMap两者还是保持比较高的效率,并且在Transient方面,StructureMap已经超过了Autofac。

总结:从测试中,可以看出Autofac和StructureMap在性能上面还是体现出比较大的优势,Ninject可以说性能上较低。而Spring.NET不仅仅专注于IOC方面,它还专注于其他方方面面的功能,所以在IOC方面的性能不是太高。另外,微软的Unity中规中矩,性能较为稳定,也是一个不错的选择。另外,可能测试程序会有所偏差,希望大家也能够指出问题!

测试程序源代码:IOCPerformanceTest.rar

原文:http://www.cnblogs.com/liping13599168/archive/2011/07/17/2108734.html

【编辑推荐】

  1. 浅议对.NET第三方控件的一些认识
  2. 五理由 .NET开发者应该关注HTML 5
  3. 微软的沉默 .NET开发者伤不起
  4. 漫谈C#开发中的ASP.NET页生命周期
  5. 纪念VB.NET君
责任编辑:陈贻新 来源: Leepy的博客
相关推荐

2020-12-23 15:42:42

大数据大数据技术大数据框架

2016-12-07 10:42:57

排序算法实例

2013-02-19 13:23:03

MySQL部署Linux平台

2011-04-15 10:26:38

JavaMVC

2021-11-28 08:04:27

.Net性能测试

2009-11-25 09:54:20

无线路由传输

2012-03-28 16:24:12

开源协议比较

2024-01-04 08:43:50

Autofac容器.NET

2009-01-07 18:27:52

2023-08-30 13:22:00

测试框架工具

2025-01-06 06:10:00

开源.NEThttps://mp

2013-07-11 11:13:51

编辑器

2021-08-11 05:06:23

NETJSON框架

2010-02-01 17:09:16

千兆接入交换机

2024-12-27 10:20:54

2024-05-11 11:18:21

Kafka监控框架

2012-12-18 13:32:45

IBMdW

2009-04-14 10:11:29

.NETWeb测试工具

2023-03-14 08:03:37

Web框架JavaScript

2012-07-31 09:02:49

Apworks
点赞
收藏

51CTO技术栈公众号