Great. Thanks.

On Thu, Sep 17, 2009 at 9:13 PM, Ayende Rahien <[email protected]> wrote:

> Good idea, done.
>
>
> On Fri, Sep 18, 2009 at 2:52 AM, Germán Schuager <[email protected]>wrote:
>
>> I think that it would be great if Kernel.Register(....) takes care of this
>> automatically.
>>
>> On Thu, Sep 17, 2009 at 8:43 PM, Ayende Rahien <[email protected]> wrote:
>>
>>> No, it doesn't.
>>> It is easier with code.
>>> Test code is interesting, it shows a pathological case of adding only
>>> invalid components.
>>> And the problem only show up when we have a large number of invalid
>>> components.
>>>
>>> var kernel = new DefaultKernel();
>>> for (int i = 0; i < 500; i++)
>>> {
>>>     kernel.AddComponent("key" + i, typeof(string), typeof(string));
>>> }
>>>
>>> Before optimization, this runs in 9.2 seconds
>>>
>>> After optimization, this runs in 0.5 seconds.
>>>
>>> Raising the number of components to 5,000 leads to about: 44.5 seconds
>>> (no idea how much before optimization, don't have the patience.
>>>
>>> Using this approach, however:
>>>
>>> var kernel = new DefaultKernel();
>>> using(kernel.OptimizeDependencyResolution())
>>> {
>>>     for (int i = 0; i < 300; i++)
>>>     {
>>>         kernel.AddComponent("key" + i, typeof(string), typeof(string));
>>>     }
>>> }
>>>
>>> Resolve everything in 1.9 seconds.
>>> The OptimizeDependencyResolution defer dependency resolution to the
>>> Dispose part, and allow us to both gain significant optimization in
>>> registering component while at the same time work nicely with all the usual
>>> tools and facilities.
>>>
>>> I also optimized GetHandlers(Type) and GetAssignableHandlers(Type)
>>>
>>> I think that this is good enough for now :-)
>>>
>>>
>>> On Fri, Sep 18, 2009 at 1:44 AM, Tyler Burd <[email protected]> wrote:
>>>
>>>>  I fully accept that.  Does this mean that the startable facility will
>>>> not be usable with this feature?
>>>>
>>>>
>>>>
>>>> *From:* [email protected] [mailto:
>>>> [email protected]] *On Behalf Of *Ayende Rahien
>>>> *Sent:* Thursday, September 17, 2009 3:53 PM
>>>>
>>>> *To:* [email protected]
>>>> *Subject:* Re: long startup time
>>>>
>>>>
>>>>
>>>> Hm, that is a bit complex, though.
>>>> In particular, it effect the way the startable facility behaves.
>>>> I think that I will make this an opt in feature.
>>>>
>>>> On Thu, Sep 17, 2009 at 10:55 PM, Ayende Rahien <[email protected]>
>>>> wrote:
>>>>
>>>> Tyler,
>>>> No, it isn't.
>>>> Basically, I think we need to restructure the way we do this so we will
>>>> defer that as late as possible (to the first resolve call, I think.).
>>>>
>>>>
>>>>
>>>>  On Thu, Sep 17, 2009 at 8:09 PM, Tyler Burd <[email protected]> wrote:
>>>>
>>>> Attached is the profiling screenshot for a VERY simple console app (code
>>>> below).  It took so long to profile that I didn't have the patience to wait
>>>> until all 1000 services were registered, but this clearly shows where the
>>>> problem lies.
>>>>
>>>> Total calls to AddComponent: 409
>>>> Total calls to AbstractHandler.DependencySatisfied: 83,773
>>>>
>>>>
>>>> If I try to profile my original app, it times out and causes a profiler
>>>> error even when left overnight to finish starting up.  When I stopped the
>>>> profiler after 30 minutes of running I saw over 600,000 calls to
>>>> DependencySatisfied.
>>>>
>>>> Am I wrong in thinking that 1000 services is not THAT many in a well
>>>> designed app?  I have a large financial app that has many complicated
>>>> processes, so I split out every process into isolated services.  I also use
>>>> a service to encapsulate ever query with a dedicated service interface.  
>>>> The
>>>> number of services registered adds up fast, but it sure seems like the
>>>> right, maintainable, and testable way to do things.
>>>>
>>>>
>>>> Profiled code:
>>>>
>>>> var container = new WindsorContainer();
>>>> var kernel = container.Kernel;
>>>>
>>>> for (int i = 0; i < 1000; i++)
>>>> {
>>>>        kernel.AddComponent("key" + i, typeof(string), typeof(string));
>>>> }
>>>>
>>>> Console.ReadLine();
>>>>
>>>>
>>>>
>>>>
>>>> -----Original Message-----
>>>> From: [email protected] [mailto:
>>>> [email protected]] On Behalf Of Mauricio Scheffer
>>>> Sent: Wednesday, September 16, 2009 8:28 PM
>>>> To: Castle Project Users
>>>> Subject: Re: long startup time
>>>>
>>>>
>>>> It's definitely the HandlerRegistered event, or more likely
>>>> AbstractEventHandler.DependencySatisfied()... here's a little test:
>>>>
>>>> import System
>>>> import System.Diagnostics
>>>> import Castle.Windsor from Castle.Windsor
>>>> import Castle.MicroKernel from Castle.MicroKernel
>>>> import Castle.MicroKernel.Handlers from Castle.MicroKernel
>>>> import Castle.MicroKernel.SubSystems.Naming from Castle.MicroKernel
>>>> import Castle.MicroKernel.ModelBuilder from Castle.MicroKernel
>>>>
>>>> def KernelAddComponent(k as IKernel):
>>>>        for i in range(1000):
>>>>                w = Stopwatch()
>>>>                w.Start()
>>>>                k.AddComponent("key${i}", typeof(string), typeof(string))
>>>>                w.Stop()
>>>>                print "${i} took ${w.ElapsedMilliseconds}"
>>>>
>>>> class CustomKernel(DefaultKernel):
>>>>        override def RaiseHandlerRegistered(h as IHandler):
>>>>                pass
>>>>
>>>> KernelAddComponent(DefaultKernel())
>>>>
>>>> Change the DefaultKernel() to CustomKernel() and the perf hit goes
>>>> away.
>>>>
>>>>
>>>> On Sep 16, 2:00 pm, Tuna Toksoz <[email protected]> wrote:
>>>> > N! times? How?
>>>> >
>>>> > Tuna Toksöz
>>>> > Eternal sunshine of the open source mind.
>>>> >
>>>> >
>>>> http://devlicio.us/blogs/tuna_toksozhttp://tunatoksoz.comhttp://twitter.com/tehlike<http://devlicio.us/blogs/tuna_toksozhttp:/tunatoksoz.comhttp:/twitter.com/tehlike>
>>>> >
>>>> >
>>>> >
>>>> > On Wed, Sep 16, 2009 at 12:59 PM, Ayende Rahien <[email protected]>
>>>> wrote:
>>>> > > IIRC, the culprit is the ComponentRegistered event, that is being
>>>> raised N!
>>>> > > times
>>>> > > We had to do that when we use the AddComponent model, but with
>>>> Register, we
>>>> > > can probably optimize this.
>>>> >
>>>> > > On Wed, Sep 16, 2009 at 7:54 PM, Tyler Burd <[email protected]> wrote:
>>>> >
>>>> > >> I'm not sure how feasible that idea could be.  SO much of an
>>>> application
>>>> > >> depends on having everything registered and ready to go before any
>>>> actual
>>>> > >> services are invoked.  For instance, my project uses Rhino Service
>>>> Bus,
>>>> > >> which depends heavily on the GetAssignableHandlers and similar
>>>> methods on
>>>> > >> the kernel.  If a critical message came in and we weren't finished
>>>> > >> registering services (AKA Message Consumers), that message could be
>>>> lost
>>>> > >> forever since GetAssignableHandlers would not return all of the
>>>> expected
>>>> > >> handlers.
>>>> >
>>>> > >> I'd much rather have some form of lazy initialization of handlers
>>>> and
>>>> > >> dependencies to amortize whatever this startup cost is, but I'm not
>>>> sure
>>>> > >> right now how that might look.
>>>> >
>>>> > >> -----Original Message-----
>>>> > >> From: [email protected] [mailto:
>>>> > >> [email protected]] On Behalf Of James Curran
>>>> > >> Sent: Wednesday, September 16, 2009 10:31 AM
>>>> > >> To: [email protected]
>>>> > >> Subject: Re: long startup time
>>>> >
>>>> > >> This leads to interesting question.  Since, one presumes you won't
>>>> > >> need all 1000 service immediately, could building the container be
>>>> > >> spun off as a background task?  This of course would lead to some
>>>> > >> interesting race conditions, but if most of those services are for
>>>> > >> corner cases (ie, say 90% of your functionality could be handled by
>>>> > >> 10% of the services), then it just become a case of filling it in
>>>> th
>>>> > >> eproper order, and releasing semaphores as you go.
>>>> >
>>>> > >> On Wed, Sep 16, 2009 at 12:05 PM, Tyler Burd <[email protected]>
>>>> wrote:
>>>> > >> > I have another similar project that has around 300 services, and
>>>> the
>>>> > >> average
>>>> > >> > AddComponent time there is 20ms, so that would make sense.  I'll
>>>> try to
>>>> > >> get
>>>> > >> > profile results today (have to buy dotTrace first).
>>>> >
>>>> > >> > From: [email protected]
>>>> > >> > [mailto:[email protected]] On Behalf Of
>>>> Ayende
>>>> > >> Rahien
>>>> > >> > Sent: Wednesday, September 16, 2009 3:00 AM
>>>> > >> > To: [email protected]
>>>> > >> > Subject: Re: long startup time
>>>> >
>>>> > >> > IIRC,
>>>> >
>>>> > >> > We saw something like that previously, I think that there is an
>>>> O(N)
>>>> > >> > operation in Windsor somewhere.
>>>> >
>>>> > >> > On Wed, Sep 16, 2009 at 7:19 AM, Tyler Burd <[email protected]>
>>>> wrote:
>>>> >
>>>> > >> > Hi all,
>>>> >
>>>> > >> > I've got a large application that takes about 1 minute to start
>>>> up.  I
>>>> > >> > investigated today what could be the cause of this very long
>>>> delay, and
>>>> > >> > narrowed it down to the WindsorContainer.AddComponent method.  I
>>>> have
>>>> > >> about
>>>> > >> > 1000 service classes, each with an interface (the service type).
>>>>  The
>>>> > >> > average time to call WindsorContainer.AddComponent is 52ms on my
>>>> system.
>>>> > >> > 52ms * 1000 is 52 seconds, which is the vast majority of the
>>>> app's
>>>> > >> startup
>>>> > >> > time.
>>>> >
>>>> > >> > My system is a Quad Core, 2.66GHz Core2 running Windows XP.  The
>>>> same
>>>> > >> > approximate startup time can be verified on multiple machines,
>>>> servers,
>>>> > >> and
>>>> > >> > OS's.
>>>> >
>>>> > >> > Is this normal?  Do I have to just bite the bullet on a long
>>>> startup
>>>> > >> time,
>>>> > >> > or is there something I can do to help this?
>>>> >
>>>> > >> > Here is the block of code in a small executable I used to
>>>> calculate the
>>>> > >> > times.  I can provide a profile report if necessary.  I normally
>>>> use
>>>> > >> > AllTypes along with the fluent registration, but I wanted to get
>>>> as
>>>> > >> > low-level as possible.  This code outputs:
>>>> >
>>>> > >> "Called AddComponent 957 times.  Average AddComponent time:
>>>> 52.0267175572519ms"
>>>> >
>>>> > >> > var container = new WindsorContainer();
>>>> >
>>>> > >> > //calculates the time for each AddComponent call
>>>> >
>>>> > >> > var watch = new Stopwatch();
>>>> >
>>>> > >> > var totalAddComponentCalls = 0;
>>>> >
>>>> > >> > //keeps track of the average ms to call AddComponent
>>>> >
>>>> > >> > var allAddComponentTimes = new List<long>(1000);
>>>> >
>>>> > >> > foreach (var classType in
>>>> > >> >
>>>> typeof(TheBigApplicationThingyWithAllTheServices).Assembly.GetTypes())
>>>> >
>>>> > >> > {
>>>> >
>>>> > >> >                 if (classType.IsInterface)
>>>> >
>>>> > >> >                                 continue;
>>>> >
>>>> > >> >                 if (classType.Namespace == null)
>>>> >
>>>> > >> >                                 continue;
>>>> >
>>>> > >> >                 if (!classType.Namespace.Contains("Services"))
>>>> >
>>>> > >> >                                 continue;
>>>> >
>>>> > >> >                 var interfaces = classType.GetInterfaces();
>>>> >
>>>> > >> >                 if (interfaces.Length == 0)
>>>> >
>>>> > >> >                                 continue;
>>>> >
>>>> > >> >                 var firstInterface = interfaces[0];
>>>> >
>>>> > >> >                 var serviceName =
>>>> totalAddComponentCalls.ToString();
>>>> > >> > //simple way to get unique name
>>>> >
>>>> > >> >                 watch.Start();
>>>> >
>>>> > >> >                 container.AddComponent(serviceName,
>>>> firstInterface,
>>>> > >> > classType);
>>>> >
>>>> > >> >                 watch.Stop();
>>>> >
>>>> > >> >
>>>> allAddComponentTimes.Add(watch.ElapsedMilliseconds);
>>>> >
>>>> > >> >                 watch.Reset();
>>>> >
>>>> > >> >                 ++totalAddComponentCalls;
>>>> >
>>>> > >> > }
>>>> >
>>>> > >> > var avgAddCompTime = (from ms in allAddComponentTimes select
>>>> > >> ms).Average();
>>>> >
>>>> > >> > Console.Out.WriteLine(string.Format("Called AddComponent {0}
>>>> times.
>>>> > >> Average
>>>> > >> > AddComponent time: {1}ms", totalAddComponentCalls,
>>>> avgAddCompTime));
>>>> >
>>>> > >> --
>>>> > >> Truth,
>>>> > >>    James
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>>
>>
>>
>>
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Castle Project Users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/castle-project-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to