Learn More





DNN Community Blog

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.

Performance, Performance, Performance

As our current version is coming towards the end of its stabilization phase,  I find myself looking at what comes next.   At this time we haven't finalised a Roadmap (in terms of features) for vNext, but we have decided that Performance improvements will be a key component.

I have therefore spent quite a bit of time in the last couple of weeks, profiling our current version (4.3.5).  I have been using a combination of tools,  Red-Gate ANTS Profiler, SQL Server 2005 Profiler, and CacheManager (by Steve Smith on ASPAlliance).

My next few blogs will focus on some of the important bottlenecks I have found, both in memory and speed, and how Module Developers can review their own code to ensure that their modules are not contributing to poor performance.

My first topic is a discussion of the CBO class, and when it should be used, and more importantly when it shouldn't be used.

Let me first describe what the CBO class does.  The CBO (or Custom Business Object) class provides a number of static methods that take a DataReader and converts it into a Business Object.  This is often referred to as "hydration" - the business object is hydrated (or filled). 

As the CBO methods do not know at compile time what kind of object they are "hydrating" they use Reflection.   Reflection is by nature an espensive operation.  It is orders of magnitude slower to create an object using Activator.CreateInstance than to use New.  Equally, PropertyInfo.SetValue is also an extremely expensive operation compared with a simple Property setter in a class.

The TabController, ModuleController and MembershipProvider do not use the CBO class to build their business objects.  They instead have custom "hydrators", such as FillTabInfo, FillModuleInfo etc.  The initial reason for using "custom" hydrators for these classes, rather than the CBO class is that these objects have a deep object structure - CBO only works for simple data types.

Not surprisingly, given the previous discussion, one of the first discoveries I made when profiling the application is that CBO.CreateObject() was one of the top 10 slowest methods, contributing to performance on every request. 

The CBO class is a convenience class, it allows us to use a "generic" methodolgy to hydrate any object, so when we write a Controller class's Get methods we just need to make calls to CBO.FillObject or CBO.FillCollection.  However, this convenience comes at a price, and we need to be aware of this. 

Is the price in performance worth the time it takes to develop a custom hydrator?  In my opinion, I don't think it is worth it.  I spent a few hrs last week writing custom dedicated hydrators for the more common classes, PortalInfo, TabPermissionInfo, ModulePermissionInfo and RoleInfo, and the increase in performance was noticable - CBO.CreateObject is no longer a significant contributor to each request.

As a Module Developer I would recommend that you review your Controller code and for the most common classes build your own custom dedicated hydrators - only rely on CBO for rarely used classes.


Comment Form

Only registered users may post comments.


2sic Daniel Mettler (124)
Aderson Oliveira (15)
Alec Whittington (11)
Alex Shirley (10)
Andrew Nurse (30)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (22)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (203)
Chris Paterra (55)
Clinton Patterson (28)
Cuong Dang (21)
Daniel Bartholomew (2)
Dave Buckner (2)
David Poindexter (3)
David Rodriguez (2)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (74)
Geoff Barlow (6)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (270)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matthias Schlomann (15)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Mike Horton (19)
Mitchel Sellers (28)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Peter Donker (52)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott S (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Timo Breumelhof (24)
Tony Henrich (3)
Torsten Weggen (2)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (37)
Will Strohl (163)
William Severance (5)
Try Evoq
For Free
Start Free Trial
a Demo
See Evoq Live
Need More Information?