Results 1 to 7 of 7

Thread: Poor performance of XmlApplicationContext.Dispose()

Hybrid View

  1. #1
    Join Date
    Jun 2007
    Posts
    17

    Default Poor performance of XmlApplicationContext.Dispose()

    Of all my application objects (all 1400+ of them) that are registered/created through Spring, only a small percentage of them define cleanup code. In other words, only about 2% of my application objects either define IDisposable or a "destroy-method" method. And for those that do the cleanup code is very lightweight. Yet when Dispose() is invoked on the XmlApplicationContext it takes upwards of 60 seconds to destroy all 1400+ objects. This comes out to about 45ms per object and makes for a very slow application shutdown. Looking at the logs, there isn't any one single object responsible for the delay -- all objects take an equal amount of time to be destroyed.

    Is there something obvious I am missing -- a simple configuration change perhaps? I can't think of anything that would cause this kind of performance issue. I am currently on version 1.3.1 and running in a .NET 4.0 environment.

  2. #2
    Join Date
    Jun 2007
    Posts
    17

    Default Spring is not scalable

    The problem appears to be the scalability of Spring. The more objects you define in Spring the worse the performance gets when disposing a Spring context. In my application the main object factory in Spring has 2956 object definition names. During disposal the factory destroys dependent objects, recursively looping through the object hierarchy and disposing/destroying each applicable object. The problem is that this recursion takes an eternity and makes disposing the context impractical.

    The change I tinkered with that improved the performance of disposal is to destroy dependent objects only if the current object is itself disposable/destroyable. This resulted in a 75% improvement in performance. The only thing stopping me from getting a larger improvement are AbstractFactoryObject objects. The call to destroy dependent objects is likely wasted on these objects because even though they implement IDisposable, the inner singleton they forward the call onto may not implement IDisposable. If I could fix this problem I could reduce the time to call Dispose to almost nothing.

  3. #3
    Join Date
    Jul 2010
    Posts
    245

    Default

    This is an interesting approach to increasing the disposal performance; would you be willing to submit a github pull request that we could examine? This (general) issue is probably related to https://jira.springsource.org/browse/SPRNET-1318 and we are aware that the present dispose algorithm is a possible performance bottleneck and would be interested in seeing your approach to solving it if you're willing to share it.

  4. #4
    Join Date
    Jun 2007
    Posts
    17

    Default Potential fix

    The notes in the defect you referenced talk about a more appropriate fix -- using separate factories to track destroy-able objects. Unfortunately, the fix I came up with (below) partially relies on hard coding a factory type -- a hack if you will -- that isn't worthy of submission. Here's what I experimented with (instrumentation removed for clarity):

    protected override void DestroyObject(string name, object target)
    {
    if (target is IDisposable)
    {
    ObjectFactoryCreatingFactoryObject factory = target as ObjectFactoryCreatingFactoryObject;
    // destroy factory only if it requires it
    if (factory != null && factory.IsSingleton && !(factory.GetObject() is IDisposable))
    return;

    DestroyDependantObjects(name);

    ((IDisposable)target).Dispose();
    }
    else
    {
    RootObjectDefinition rootDefinition = GetMergedObjectDefinition(name, false);
    if (rootDefinition != null && StringUtils.HasText(rootDefinition.DestroyMethodNa me))
    {
    DestroyDependantObjects(name);
    InvokeCustomDestroyMethod(name, target, rootDefinition.DestroyMethodName);
    }
    }
    }

  5. #5
    Join Date
    Jul 2010
    Posts
    245

    Default

    Understood -- thanks for the sample code all the same. Bottom line: we know about this bottleneck and are targeting to address it in the next release. Thanks again!

  6. #6
    Join Date
    Mar 2012
    Posts
    2

    Default

    We just ran into the same issue when creating more than a few hundred objects. I ran a test on some simple objects with spring creating (10K) and "disposing" of them took over 10 minutes on a really nice machine.

    I am not trying to "rub salt" on the wound since you guys already know about the issue.

    I just was checking on the status of this. I saw the target for the release had passed.

    Maybe some other alternatives that would be okay to use and faster to code would be:

    1. Like the previous post - disable Idisp checks from a flag in the xml file... no need to do the check if you know you are not using any class the imps Idisposable.

    2. Having a marker interface for parent classes that you want to dispose of - that might hold or "own" Idisposable objects.

    3. Separate thread?

    Thanks,
    Brad

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •