浩VS其他IoC容器中,容器、VS、IoC

2023-09-03 10:59:28 作者:一切与你无关

在this文章(2009年4月11日),提交人称浩是:

世界上最快的IoC容器......一个静态precompiled IOC容器,以最快的速度执行的申请,无需IOC容器的。

难道今天仍然最快的IOC容器?它是为生产做好准备?是否有任何其他容器可以在编译时做国际奥委会?什么是它的主要优点和缺点比其他IOC容器?

感谢

解决方案

浩号称是最快的容器。这种说法是基于笔者给出的基准(见here对于很多容器之间的一个客观的比较)。不论这个基准是现实的,取决于你的应用程序的大小。基准似乎巧妙地设置一个非常小的一套注册的类型。当添加更多注册的标杆,性能开始下降(见下面这样的一个例子基准)。当密切关注,我们可以看到,浩有 O(n)的的性能特征,而正常的DI框架有O(1)的特点,因此与其他框架的性能保持不变,注册类型的数量。

什么是好的关于浩是生成一个新的装配在飞行中,解决了新型仅由一个单一的接口调用。这是非常快的。在另一方面,最常见的DI框架,将永远有一个调用的GetInstance期间做一个字典查找。 Hiro的getInstance方法基本上是一个大的switch case语句内部,实现为一堆if语句的。如果为基础的开关case语句是非常快,直到一个点。 C#编译器使用的启发(我相信)18 case语句的转折点。下面说一些编译器生成一个一堆if语句的。上面这个数字将创建并存储一个静态字典和做一个字典查找,因为字典查找的超过18查找性能,如果简单地更快。

嗯你猜怎么着;浩不使用优化的C#编译器。这就是为什么性能,因为越来越多的类型被添加到容器中不断下降。线性性能特点 - 或为O(n)进行短期是好于小数据集,但任何写得很好,一般大小,依赖型应用程序有许多类型的注册/映射。在此情况下纮的性能迅速下降。

因此​​,要回答你的问题:

  

仍是它最快的IOC容器   今天?

对于非常小的应用中是最快的。对于任何一个正常大小的应用中从未有过的速度最快的。

  

它是为生产做好准备?

很难说。其当前状态为α型,它忽略了很多功能,其他IOC框架有。只(见下面的评论)的开发者发布了稳定版本。这意味着,根据显影剂它可用于生产

  

什么是它的主要优势   以上等IOC容器的缺点是什么?

就拿一起来看看本文(和跟进)的给国际奥委会框架的一个很好的(功能)的比较。文章的作家有什么,他认为是很重要的一个愿景。你必须作出这样的名单你自己。性能似乎是高的名单上。但是,请注意,还有其他的方法来提高性能。比如通过注册类型为单身到prevent创建多种类型的。

spring中基于IOC容器对bean进行管理

下面是一个与其他容器相比不大。请注意,我没有写浩,所以我可能会错过的事情,尤其是因为似乎没有文档可言,但在这里有云:

您需要4个组件的运行,而不是1或2对大多数国际奥委会框架。 在它抛出时,递归依赖性解决一个堆栈溢出(大多数框架做BTW)。因此,有没有循环依赖检测。 似乎不支持任何暂时性的其他生活方式(笔者不说will,但我现在看到这个不支持)。这实际上是坏的表现,因为大多数服务通常会被注册为单身。据笔者,支持多种生活方式。 在不支持解决开放式泛型类型。 在不支持未注册的类型解析。 在我还没有文档接受XML(智能感知)文档。   

还有没有其他的容器可以做   国际奥委会在编译时?

定义编译时。浩在运行时产生的飞行一个新的装配一次。其他(如 Autofac ,的温莎和简单的注射器)发出IL或在幕后编译代表。这是不是比编译完成装配一气呵成任何慢(但没有叫这比让一个接口调用一点点慢委托的开销)。

顺便说一句,我改变了基准测试,看看上述的行为出现。随着50多登记注册类型,你会看到,浩已经执行三倍慢作为与最初的基准。这里是code我用:

 公共接口IHandler< T> {}

公共类处理器< T> :IHandler< T> {}

公共类HiroUseCase:用例
{
    IMicroContainer容器;

    私有静态无效RegisterHandler< T>(DependencyMap图)
    {
        map.AddService(typeof运算(IHandler< T>)的typeof(处理器< T>));
    }

    公共HiroUseCase()
    {
        VAR地图=新DependencyMap();

        // ***我的新增注册
        RegisterHandler<字节>(图)
        RegisterHandler<字节>(图)
        RegisterHandler<短>(图)
        RegisterHandler<短>(图)
        RegisterHandler< USHORT>(图)
        RegisterHandler< USHORT>(图)
        RegisterHandler< INT>(图)
        RegisterHandler<诠释>(图)
        RegisterHandler< UINT>(图)
        RegisterHandler< UINT>(图)

        RegisterHandler<长>(图)
        RegisterHandler<长>(图)
        RegisterHandler< ULONG>(图)
        RegisterHandler< ULONG>?(图)
        RegisterHandler<浮动>(图)
        RegisterHandler<浮动>(图)
        RegisterHandler<双>(图)
        RegisterHandler<双倍>(图)
        RegisterHandler<十进制>(图)
        RegisterHandler<十进制>(图)

        RegisterHandler< D​​ateTime的>(图)
        RegisterHandler< D​​ateTime的>?(图)
        RegisterHandler<焦炭>(图)
        RegisterHandler<烧焦>(图)
        RegisterHandler<对象>(图)
        RegisterHandler<字符串>(图)
        RegisterHandler<布尔>(图)
        RegisterHandler< bool的>(图)
        RegisterHandler<枚举>(图)
        RegisterHandler< D​​ateTimeKind>(图)

        RegisterHandler< D​​ateTimeKind>?(图)
        RegisterHandler<的DateTimeOffset>(图)
        RegisterHandler<的DateTimeOffset>?(图)
        RegisterHandler< D​​AYOFWEEK>(图)
        RegisterHandler< D​​AYOFWEEK>?(图)
        RegisterHandler<为DBNull>(图)
        RegisterHandler<委托>(图)
        RegisterHandler< D​​ivideByZeroException>(图)
        RegisterHandler< D​​llNotFoundException>(图)
        RegisterHandler<异常>(图)

        RegisterHandler< KeyNotFoundException>(图)
        RegisterHandler<出现InvalidOperationException>(图)
        RegisterHandler< InvalidCastException的>(图)
        RegisterHandler< InvalidProgramException>(图)
        RegisterHandler< InvalidTimeZoneException>(图)
        RegisterHandler< IDisposable的>(图)
        RegisterHandler< IComparable的>(图)
        RegisterHandler< IEquatable< INT>>(图)
        RegisterHandler< IEnumerable的>(图)
        RegisterHandler<的IEqualityComparer>(图)

        // ***原基准设置
        map.AddService(typeof运算(IWebApp)的typeof(Web应用程序));
        map.AddService(typeof运算(IAuthenticator)的typeof(验证));
        map.AddService(typeof运算(IStockQuote)的typeof(股票报价));
        map.AddService(typeof运算(了IDatabase)的typeof(数据库));
        map.AddService(typeof运算(IErrorHandler)的typeof(的ErrorHandler));
        map.AddService(typeof运算(ILogger)的typeof(记录器));

        IContainerCompiler编译器=新ContainerCompiler();
        VAR组装= compiler.Compile(图);;

        变种loadedAssembly = assembly.ToAssembly();
        变种containerType = loadedAssembly.GetTypes()[0];
        容器=(IMicroContainer)激活
            .CreateInstance(containerType);
    }

    公众覆盖无效的run()
    {
        VAR Web应用程序=
            (IWebApp)container.GetInstance(typeof运算(IWebApp),NULL);
        webApp.Run();
    }
}
 

In this article (11 Apr 2009), the author claims Hiro is:

"the World's Fastest IOC Container... a statically precompiled IOC container that performs as fast as an application without an IOC container".

Is it still the fastest IOC container today? Is it ready for production? Are there any other containers can do IOC at compile time? What are its major advantages and disadvantages over other IOC containers?

Thanks

解决方案

Hiro claims to be the fastest container. This statement is based on the benchmark given by the author (see here for an objective comparison between many containers). Whether or not this benchmark is realistic depends upon the size of your application. The benchmark seems to be cleverly setup with a very small set of registered types. When adding more registrations to the benchmark, the performance starts dropping (see below for an example benchmark of this). When looking closely we can see that Hiro has a performance characteristic of O(n), while normal DI frameworks have a characteristic of O(1), thus with other frameworks the performance stays constant with the number of registered types.

What’s nice about Hiro is that it generates a new assembly on the fly and resolving a new type consists of just a single interface call. This is very fast. Most common DI frameworks on the other hand, will always have to do a dictionary lookup during a call to GetInstance. Hiro’s GetInstance method is basically a big switch case statement internally, implemented as a bunch of if-statements. If-based switch case statements are extremely fast up until a point. The C# compiler uses an heuristic of (I believe) 18 case statements as turning point. Below that number the compiler generates a bunch of if-statements. Above that number it creates and stores a static dictionary and does a dictionary lookup, because above 18 lookups performance of a dictionary lookup if simply faster.

Well guess what; Hiro doesn’t use the optimization as the C# compiler does. That's why the performance keeps dropping as more and more types are added to the container. A linear performance characteristic –or O(n) for short- is okay for small sets of data, but any well written and commonly sized, dependency-friendly application has many type registrations / mappings. And in that case the performance of Hiro drops quickly.

So, to answer your questions:

Is it still the fastest IOC container today?

For very small applications it is the fastest. For any normal sized applications it has never been the fastest.

Is it ready for production?

Hard to say. Its current status is alpha and it misses a lot of features that other IOC framework have. The developer just (see comments below) published a stable release. This means that according to the developer it is ready for production.

What are its major advantages and disadvantages over other IOC containers?

Take a look for instance at this article (and the follow up) which gives a good (feature) comparison of IOC frameworks. The writer of the article has a vision of what he thinks is important. You have to make such a list for yourself. Performance seems to be high on your list. However, please note that there are other ways to improve performance. For instance by registering types as singletons to prevent the creation of many types.

Here is a little comparison with other containers. Note that I didn't write Hiro, so I could be missing things, especially since there seems to be no documentation at all, but here goes:

You need 4 assemblies to run, instead of 1 or 2 for most IOC frameworks. It throws a stack overflow when a recursive dependency is resolved (most frameworks do this btw). So there is no cyclic dependency detection. Doesn't seem to support any lifestyle other than transient (the writer does say it will, but I currently see no support for this). This actually is bad for performance, because most services would normally be registered as singletons. According to the author, it supports multiple lifestyles. Doesn't support resolving open generic types. Doesn't support unregistered type resolution. I has no documentation accept XML (intellisense) documentation.

Are there any other containers can do IOC at compile time?

Define 'compile time'. Hiro generates a new assembly on the fly once during runtime. Others (like Autofac, Windsor and Simple Injector) emit IL or compile delegates under the covers. This isn't any slower than compiling the complete assembly in one go (however, there is the overhead of calling the delegate which is a tiny bit slower than making an interface call).

BTW, I changed the benchmark to see the behavior described above appear. With 50 extra types registered you will see that Hiro performs already three times as slow as with the initial benchmark. Here is the code I used:

public interface IHandler<T> { }

public class Handler<T> : IHandler<T> { }

public class HiroUseCase : UseCase
{
    IMicroContainer container;

    private static void RegisterHandler<T>(DependencyMap map)
    {
        map.AddService(typeof(IHandler<T>), typeof(Handler<T>));
    }       

    public HiroUseCase()
    {
        var map = new DependencyMap();

        // *** My added registrations
        RegisterHandler<byte>(map);
        RegisterHandler<byte?>(map);
        RegisterHandler<short>(map);
        RegisterHandler<short?>(map);
        RegisterHandler<ushort>(map);
        RegisterHandler<ushort?>(map);
        RegisterHandler<int>(map);
        RegisterHandler<int?>(map);
        RegisterHandler<uint>(map);
        RegisterHandler<uint?>(map);

        RegisterHandler<long>(map);
        RegisterHandler<long?>(map);
        RegisterHandler<ulong>(map);
        RegisterHandler<ulong?>(map);
        RegisterHandler<float>(map);
        RegisterHandler<float?>(map);
        RegisterHandler<double>(map);
        RegisterHandler<double?>(map);
        RegisterHandler<decimal>(map);
        RegisterHandler<decimal?>(map);

        RegisterHandler<DateTime>(map);
        RegisterHandler<DateTime?>(map);
        RegisterHandler<char>(map);
        RegisterHandler<char?>(map);
        RegisterHandler<object>(map);
        RegisterHandler<string>(map);
        RegisterHandler<bool>(map);
        RegisterHandler<bool?>(map);
        RegisterHandler<Enum>(map);
        RegisterHandler<DateTimeKind>(map);

        RegisterHandler<DateTimeKind?>(map);
        RegisterHandler<DateTimeOffset>(map);
        RegisterHandler<DateTimeOffset?>(map);
        RegisterHandler<DayOfWeek>(map);
        RegisterHandler<DayOfWeek?>(map);
        RegisterHandler<DBNull>(map);
        RegisterHandler<Delegate>(map);
        RegisterHandler<DivideByZeroException>(map);
        RegisterHandler<DllNotFoundException>(map);
        RegisterHandler<Exception>(map);

        RegisterHandler<KeyNotFoundException>(map);
        RegisterHandler<InvalidOperationException>(map);
        RegisterHandler<InvalidCastException>(map);
        RegisterHandler<InvalidProgramException>(map);
        RegisterHandler<InvalidTimeZoneException>(map);
        RegisterHandler<IDisposable>(map);
        RegisterHandler<IComparable>(map);
        RegisterHandler<IEquatable<int>>(map);
        RegisterHandler<IEnumerable>(map);
        RegisterHandler<IEqualityComparer>(map);

        // *** Original benchmark setup
        map.AddService(typeof(IWebApp), typeof(WebApp));
        map.AddService(typeof(IAuthenticator), typeof(Authenticator));
        map.AddService(typeof(IStockQuote), typeof(StockQuote));
        map.AddService(typeof(IDatabase), typeof(Database));
        map.AddService(typeof(IErrorHandler), typeof(ErrorHandler));
        map.AddService(typeof(ILogger), typeof(Logger));

        IContainerCompiler compiler = new ContainerCompiler();
        var assembly = compiler.Compile(map);;

        var loadedAssembly = assembly.ToAssembly();
        var containerType = loadedAssembly.GetTypes()[0];
        container = (IMicroContainer)Activator
            .CreateInstance(containerType);
    }

    public override void Run()
    {
        var webApp = 
            (IWebApp)container.GetInstance(typeof(IWebApp), null);
        webApp.Run();
    }
}