Page 1 of 3 123 LastLast
Results 1 to 10 of 28

Thread: Very poor performance using Spring Web Framework

  1. #1
    Join Date
    Jun 2005
    Posts
    33

    Default Very poor performance using Spring Web Framework

    In an earlier projects using the Spring Web Framework, we experienced extremely poor performance due to Spring trying to inject every single control used on our web pages.

    Tracing the code using DotTrace showed the culprits:
    - InjectDependenciesRecursive was called 1400+ times for some pages.
    - InjectDependenciesRecursiveInternal was called 11000+ times.

    That particular page had a large GridView containing many nested controls, all of which Spring attempted to inject. Needless to say, rendering of that page in particular was very slow.

    Erich Eichinger came to our rescue and explained how it all works:
    "By default Spring replaces the page's ControlCollection with it's own DI-aware collection - and this process is cascaded as additional controls are loaded and added to the collection."

    Erich then recommended us to implement the ISupportsWebDependencyInjection interface to control whether dependency injection (DI) is performed on page controls (thus increasing performance).

    Our solution was to let all pages inherit from an AbstractBasePage, which implemented the interface like this:

    Code:
    public abstract class AbstractBasePage : Page, ISupportsWebDependencyInjection
    This tells Spring that the page will handle DI of controls itself, thus overriding Spring's default mechanism for recursive DI of controls. Since our AbstractBasePage does not attempt to perform DI on controls, DI is effectively turned off for child controls. (Check out this page for info on how actually do DI yourself: [http://www.springframework.net/docs/...opic12141.html].)

    Question:
    The solution described above works, but ties all our pages to Spring because we have to implement Springs interface. My question is whether better solutions have surfaced in newer versions of Spring? For example:

    - Has DI of controls become faster in Spring RC2, so that this isn't a problem anymore?
    - Can DI of controls be configured from the Spring XML files now (on/off, depth)?
    - Are there other, more elegant solutions we can use?
    Last edited by Erich Eichinger; 12-06-2007 at 07:00 AM. Reason: fixed cross reference link
    Bjørn Wang

  2. #2
    Join Date
    Jan 2006
    Location
    Cambridge, UK
    Posts
    1,340

    Default

    Hi,

    I - Has DI of controls become faster in Spring RC2, so that this isn't a problem anymore?
    There have been a couple of performance-related improvements to web DI. Maybe you want to give Spring.Web another chance and let me know your results. As you might remember I'm more than willing to help.

    If you are really looking for performance I recommend not using GridView at all, since - from performance viewpoint - this is the worst control of all. Replacing GridViews with e.g. DataLists will make your application much more resource-friendly.

    - Can DI of controls be configured from the Spring XML files now (on/off, depth)?
    Control DI can be configured as described in the reference docs. Atm there is no way to control DI depth or turn it off aside from implementing ISupportsWebDependencyInjection yourself.

    Of course I'm all ears for suggestions on how to configure/control DI for particular cases and would be glad to hear your opinion. I simply didn't have much time to think about a solution yet.

    - Are there other, more elegant solutions we can use?
    E.g. separate your pages by configuring 2 <httpHandler>s:

    Code:
    <httpHandlers>
      <add verb="*" path="*_di.aspx" type="Spring.Web.Support.PageHandlerFactory, Spring.Web"/>
      <add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory"/>
    </httpHandlers>
    this will cause only pages with the "_di" postfix to take part in dependency injection.

    It is too late to fix this for the upcoming 1.1 release. I recorded it to JIRA as SPRNET-794.

    hope this helps,
    Erich
    Last edited by Erich Eichinger; 12-05-2007 at 07:55 PM. Reason: added to jira

  3. #3
    Join Date
    Jan 2006
    Location
    Cambridge, UK
    Posts
    1,340

    Default

    Hi Bjorn,

    I just had another idea on how to better control DI on controls. See my post over here and checkout solution variant 2 for more.

    hope this helps,
    Erich

  4. #4
    Join Date
    Jan 2008
    Posts
    1

    Default

    Hi guys sorry for this newbie question but Bjorn quoted Erich as saying "By default Spring replaces the page's ControlCollection with it's own DI-aware collection".

    By looking at the config files, I initially thought Spring only injected objects I specify. So for other asp controls like GridView, Labels etc don't they just get processed as per normal?

  5. #5
    Join Date
    Jan 2006
    Location
    Cambridge, UK
    Posts
    1,340

    Default

    Hi,

    to enable DI for ASP.NET controls, we faced an important problem: Instantiation of controls happens outside the container. To cope with this, DI is done in 2 steps:

    1) The ControlCollection of any control, that is added to the hierarchy, is dynamically replaced with a DI-aware ControlCollection

    2) This ControlCollection instance checks each added control, if there is a corresponding object definition in the container. If one is found, the control will be configured. Otherwise just do step 1)


    Normally this works without noticable delay but in the case of a GridView, that potentially creates hundreds of child controls, this may cause a remarkable performance degradation.

    Finding an alternative, but still non-intrusive solution is on my plate and will definitely be part of an upcoming Spring.NET release. I'll ping back on this thread as soon as I commit something.

    hope this helps,
    Erich

  6. #6
    Join Date
    Nov 2007
    Posts
    75

    Question

    So if I wanted to turn off DI on a whole page could I just have my page implement ISupportsWebDependencyInjection and then comment out the calls to WebUtils.InjectDependenciesRecursive in Add, AddAt,
    AddedControl from the implementation examples in http://www.springframework.net/docs/...pic12141.html? Then for pages where I do want it I'd just not use the base page that implements it? This seems neater to me than using a naming convention for the page. I think the documentation could use some more examples on custom injection strategies or disabling rather than just showing the default implementation.

    Could I also do something like this to specifically ignore GridViews as they have lots of nested controls? Is this sort of type checking slow?
    if (!child is GridView)
    WebUtils.InjectDependenciesRecursive...

    Just to confirm, if I do manual object lookups in a Spring.NET app context I won't need to use the httphandler and won't have any performance hit on heavy nested control pages at all, correct?

    Thanks.

  7. #7
    Join Date
    Jan 2006
    Location
    Cambridge, UK
    Posts
    1,340

    Default

    Hi all,

    I added a new <spring:Panel> server control, which has an attribute "suppressDependencyInjection". By wrapping the performance sensitive parts of your page within this panel, you can easily turn off DI:

    Code:
    <spring:Panel runat="server"
       suppressDependencyInjection="true"  
       renderContainerTag="false">
    
       .. put your heavy controls here - they won't be touched by DI
    
    </spring:Panel>
    Note: In contrast to <asp:Panel>, by default <spring:Panel> won't render a container tag (<div>, <span> etc.). You can modifiy this behaviour by setting the attribute "RenderContainerTag" accordingly.

    I will update the documentation regarding this asap.

    Is this sort of type checking slow?
    if (!child is GridView)
    WebUtils.InjectDependenciesRecursive...
    Compared to what else is happening during a request, I don't think that such checks cause measurable performance degradation.

    hope this helps,
    Erich

  8. #8
    Join Date
    Nov 2007
    Posts
    75

    Default

    Thanks Erich. That looks very handy for pages where I want DI to work in general, but have areas of heavily nested controls.

    I'm still trying to generate a base class that turns off DI for anyone implementing it just to make it easy to have it off by default without relying on page naming conventions (almost our entire app implements a Page derived base class so this would be a good point to turn DI off by default) and haven't been successful. My properties are still injected. Here's what I've created:

    Code:
    public class SpringNoDIPage : Page, ISupportsWebDependencyInjection
    {
        public SpringNoDIPage()
        {
        }
    
        #region ISupportsWebDependencyInjection Members
    
        private IApplicationContext _defaultApplicationContext;
        public IApplicationContext DefaultApplicationContext
        {
            get { return _defaultApplicationContext; }
            set { _defaultApplicationContext = value; }
        }                                                      
        #endregion
    
        protected override void AddedControl(Control control, int index)
        {
    //Note that this is WebDependencyInjectionUtils and not WebUtils.  The docs are out of date.        //WebDependencyInjectionUtils.InjectDependenciesRecursive(_defaultApplicationContext, control);
            base.AddedControl(control, index);
        }
    }
    Code:
    public partial class Test_Spring_SpringNoDI : SpringNoDIPage
    {
        private string _TestMessage;
    
        public string TestMessage
        {
            get { return _TestMessage; }
            set { _TestMessage = value; }
        }
    
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write(String.Format("TestMessage Local Property: {0}<br>", TestMessage));
        }
    }
    Code:
      <object type="Test/Spring/SpringNoDI.aspx">
        <property name="Title" value="Spring No DI Title"></property>
        <property name="TestMessage" value="Hello From Spring No DI"></property>
      </object>

  9. #9
    Join Date
    Jan 2006
    Location
    Cambridge, UK
    Posts
    1,340

    Default

    Hi,

    as long as you configure Spring's PageHandlerFactory in the <httpHandlers> section, your *page* will be populated with configured values.

    But your implementation will successfully prevent any *control* on this page to get injected.

    cheers,
    Erich

  10. #10
    Join Date
    Nov 2007
    Posts
    75

    Default

    Excellent. I put a giant gridview on my page and confirmed my NoDI page is working as expected and disabling injection. My DI version of the page with a giant gridview has a 25 second extra delay. Thanks.

Posting Permissions

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