PDA

View Full Version : Quick question and praise :)


cdigs
02-08-2007, 03:41 PM
First of all, I have to say this: I love it (http://www.charliedigital.com/PermaLink,guid,dd758f83-d39c-40db-b94b-743b1c97b988.aspx).

The data access block, at first glance, is a thing of beauty and simplifies data access while still giving a great deal of control over the "rendering" of the data; it's the perfect compromise between a full blown ORM like NHibernate and raw ADO access.

I've been doing this with a lot of the AJAX code that I've been writing, using the same methodology (delegate based) to render UI components based on returned data sets, but the thought had never even occurred to me to do the same with datasets; it greatly simplifies the code by removing the tedium of raw ADO and even working with Enterprise Library.

I do have some questions and concerns that popped up as I was going through the examples and the documentation:

1) I noticed that in the examples, all of the methods on the DAO were marked as virtual. Is this a requirement?

2) What are the performance ramifications of adding the extra wiring for the delegate as opposed to simply using a while(){} loop? Has this been tested with large data sets?

3) Explain the Common.Logging library. I noticed the full file name in the lib/logging/#.#/release. Is this a custom adapatation of log4net? What is the thinking behind this? What if I'm already using log4net? What did you guys add/remove from log4net? I'm looking for some guidance on the best strategy to use for logging now that the Spring team has introduced another logging library.

Bruno Baia
02-08-2007, 05:36 PM
Hi,

nice blog post :)

1)
I'm not sure why, but a good reason is to allow use of Spring.Aop when your DAO does not implement an interface.
To be proxied, a method needs to belong to an interface or to be virtual.

3)
Common.Logging is an abstract library
See this post : http://forum.springframework.net/showthread.php?t=851
I just never liked that a framework like Spring where dependend/hard wired upon other 3rd party projects. Seemed a bit silly, loose coupling and all :-)
Take a look to the Spring.Calculator exemple, specially the Web project inside for an example of 3rd party library usage (log4net in this case)

2)
I let Mark answer this one :)


Bruno

Mark Pollack
02-08-2007, 06:54 PM
Hi Charlie,

I very much liked your blog entry - very balanced. Today seems to be a good day for positive feedback! Thanks for your kind words. I'll post a link to your blog entry on our web page soon.

As for your second question, can you explain more what you mean? If you take a look at the code pathway for QueryWithRowCallbackDelegate it creates a RowCallbackResultSetExtractor (once) and inside its ExtractData method is exactly the 'tight' while loop you mention. I have not done performance tests per-se, but I haved 'extracted' ~40,000 rows without really feeling that something odd was going on. Maybe you mean having repeated calls to QueryWithRowCallbackDelegate and the cost of creating a RowCallbackResultSetExtractor? I doubt that extra object creation is a big issue in a situation like this - where the big cost is the getting data from the DB.


Cheers,
Mark

cdigs
02-08-2007, 07:24 PM
I am looking for simple performance data (if they exist) comparing the same database call and domain object list building using the different methods exposed by the data access library.

As I understand it, there are performance penalties (http://blogs.msdn.com/vancem/archive/2006/03/13/550529.aspx) making calls through interfaces in .Net (although admittedly, I'm not intimately familiar with the nature and numbers).


From another blog post (http://blogs.msdn.com/oldnewthing/archive/2006/08/02/686456.aspx), I gathered:The hard case is where things get interesting. The body of an anonymous method is permitted to access the local variables of its lexically-enclosing method, in which case the compiler needs to keep those variables alive so that the body of your anonymous method can access them. Here's a sample anonymous method that accesses local variables from its lexically-enclosing method: -- code-snippet --When faced with this "hard" type of anonymous method, wherein variables are shared with the lexically-enclosing method, the compiler generates a helper class:-- code-snippet --Wow, there was a lot of rewriting this time. A helper class was created to contain the local variables that were shared between the MemberFunc function and the anonymous method (in this case, just the variable i), as well as the hidden this parameter (which I have called this$). In the MemberFunc function, access to that shared variable is done through this anonymous class, and the anonymous method that you wrote is an anonymous method on the anonymous class.Granted: it seems like the performance would stabilizes over any sort of non-trivial data set even with heavy usage of interface dispatches (according to Morrison) and anonymous delegates (for which helper classes are generated at compile time, but add to the memory footprint (and thus overall performance profile)), but again, I myself am not that intimately familiar with the low level implementation, optimization, and performance details of the compiler in supporting various language features.

There is another discussion (http://www.dotnet247.com/247reference/msgs/32/162980.aspx) which I just came across today regarding the performance of multi-cast delegates that's worth taking a look at as well.

I know, I know, I could always write the tests myself :rolleyes: but I was hoping that there would be some numbers on this already.

I will probably never have to deal with any data sets greater than say 100-200 rows in my application (paged data, strategic caching), but it's still good to have some assurance when other engineers bring up the issue of performance versus using typical while/Read() loop to perform object building.

Aleks Seovic
02-08-2007, 10:47 PM
Hi Charlie,

First of all, thanks for the very positive blog post.

I haven't done any performance tests for the data access layer, but based on the tests I've done while working on AOP and some other things I'm pretty confident that you will not see any performance differences between while loop and delegate or interface callback.

Pretty much all the tests I've run show that there are significant differences in performance between different ways to invoke a method, but with one very important caveat -- differences exist only as long as the method does nothing or almost nothing (property get or set could be considered "almost nothing").

Once you place some logic into your method, the overhead of the actual invocation becomes so small that it is pretty much irrelevant how you invoked it. Granted, creating a domain object and setting a few properties is not very much work, but it should be more than enough to make invocation cost a non-issue.

Now, if you do decide to run some tests, please share the results with us ;)

Later,

Aleks