[NHibernate-development] Speed improvement using compile time generated proxies

28 views
Skip to first unread message

Johan Kirsten

unread,
Sep 3, 2008, 5:54:08 PM9/3/08
to nhibernate-...@lists.sourceforge.net
Greetings
 
There was a request for benchmark numbers regarding the performance increase. I have performed my tests using the following configuration:
 
Pentium 4 2.4 GHz
1 GB RAM
Win XP Pro SP 3
VS 2005
NET 2.0
MS SQL Server 2000
Ran in debug mode
The nhibernate proxy generator by WC Pierce (http://code.google.com/p/nhibernateproxygenerator/)
NHibernate 2.0 (the nhibernate proxy generator requires NH 2.0 because it needs to set the proxyfactoryfactory)
 
I ran my tests by loading 5 different types from the db. For each type I loaded the top 100 in the table.
I documented the times in milliseconds. The most important difference between each type is the number of contained objects (and therefore foreign keys). I have also documented this.

Using run time proxies
Type FK Run 1 Run 2 Run 3 Average
1 0 203 203 187 198
2 1 328 328 422 359
3 2 406 407 562 458
4 3 500 703 422 542
5 3 547 484 578 536
Compile time proxies
Type FK Run 1 Run 2 Run 3 Average
1 0 188 218 172 193
2 1 78 47 63 63
3 2 62 78 78 73
4 3 78 63 78 73
5 3 78 94 125 99
Difference
Type FK % reduction Calculation
1 0 -3% = (193 - 198)/198
2 1 -83% = (63 - 359)/359
3 2 -84% = (73 - 458)/458
4 3 -87% = (73 - 542)/542
5 3 -82% = (99 - 536)/536

For classes with contained objects (fk's) a reduction in process time of approx 80%
e.g. a load time of 5 seconds can be reduced to 1 second for a list of complex objects
No significant improvement in classes without contained objects (fk's)
 
It is also important to realise that these are speed improvements on NH 2.0. I suspect that the new Dynamic Proxy used by NH 2.0 also has its own optimization. Therefore if you are coming from NH 1.2.1 I suspect you will get an even greater improvement, but this is not confirmed
 
Johan Kirsten

Fabio Maulo

unread,
Sep 3, 2008, 6:33:11 PM9/3/08
to the NHibernate development list
Do you can send me the solution with all your sources and required external lib ?
Thanks.

2008/9/3 Johan Kirsten <jo...@goo.co.za>
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Nhibernate-development mailing list
Nhibernate-...@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nhibernate-development




--
Fabio Maulo

Fabio Maulo

unread,
Sep 3, 2008, 7:20:15 PM9/3/08
to the NHibernate development list
And Johan please do it a soon as possible because soon we will release NH2.0.0SP1 (or NH2.0.1 I'm not sure about it but this will be a matter of another thread).

2008/9/3 Fabio Maulo <fabio...@gmail.com>



--
Fabio Maulo

Jesse Napier

unread,
Sep 4, 2008, 1:01:06 AM9/4/08
to the NHibernate development list

As far as I know the performance of NHibernate got drastically slower in version 2.0.  I remember there was some testing done a while back but I’m not  sure if there issues were resolved. I don’t think the slow down was due to dynamic proxy.

 


Fabio Maulo

unread,
Sep 4, 2008, 2:27:16 AM9/4/08
to the NHibernate development list
We don't have so many response about it after 6000 download of NH2.0.0GA and 14000 downloads of Alpha1.
BTW we are open to make NH more faster but without change all codebase.

2008/9/4 Jesse Napier <jna...@gamefly.com>
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Nhibernate-development mailing list
Nhibernate-...@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/nhibernate-development




--
Fabio Maulo

Johan Kirsten

unread,
Sep 4, 2008, 3:25:22 AM9/4/08
to nhibernate-...@lists.sourceforge.net
Greetings

Unfortunately I am not able to supply source code, as I am under contract. I
will however be able to tell you what I did and how it works. It will not be
difficult for you to do it. I think it took me an afternoon. My code is
based on WC Pierce's code available from
http://code.google.com/p/nhibernateproxygenerator/. It has al the necessary
code and lib to get you started.

The content of the source code zip file you will be interested in is:
1) lib - contains all the libraries (just update NHibernate library with the
latest version)
2) source/NHibernate.Proxy.Generator project - the source code of a console
application that compiles the proxies. The console application obtains the
name of an input library that contains *.hbm.xml mapping files. It compiles
the runtime proxies and saves these runtime proxies into the specified
output library. It also adds a StaticProxyGenerator class to the output
library that will be called by NHibernate to instantiate the compile time
proxies.

The downloaded NHibernate.Proxy.Generator has the following files:
1) ActiveRecordConfigurationSource.cs - class that handles configuration of
nhibernate
2) ApplicationOptions.cs - defines the commandline arguments.
3) CommandLineArguments.cs - used by the console application to parse
commandline arguments into ApplicationOptions class
4) GeneratorProxyFactory.cs - performs the compilation of a proxy factory
5) GeneratorProxyFactoryFactory.cs - calls the GeneratorProxyFactory
6) Program.cs - main console application
7) StaticProxyFactory.boo - boo source that is compiled into the
StaticProxyFactory that will be placed in output library

My changes
1) I dropped the ActiveRecordConfigurationSource as I use my nhibernate
configuration files as input
2) I altered ApplicationOptions to store
a) the input the path to an nhibernate configuration file and
b) the path to my source directory containing the input libraries
3) I left GeneratorProxyFactory and GeneratorProxyFactoryFactory as they are
4) I altered the StaticProxyFactory.boo so that its static _proxies
dictionary will compile to a generic dictionary that maps System.Int64 to
System.Type

I altered the Program file to have it work with normal nhibernate
configuration files, but is similar to the existing progrma file. Also, I do
not think one should assume ActiveRecord is used. To create a compile time
proxy library the main program must
1) load command line arguments
2) load the nhibernate configuration file
3) for each session factory defined in the configuration file it must:
a) Obtain the name to use for the output library file from the property
"proxyfactory.factory_class" in the nhibernate configuration instance
b) Replace the property "proxyfactory.factory_class" in the nhibernate
configuration instance with the type name of GeneratorProxyFactoryFactory
c) Call BuildSessionFactory on configuration instance. (This will use
GeneratorProxyFactoryFactory to call GeneratorProxyFactory to compile
proxies using ProxyGenerator created by Program class and place the Type
objects into the Proxies library defined in Program class)
d) Call Program.ProxyGenerator.ProxyBuilder.ModuleScope.SaveAssembly() to
save compile time proxies to CastleDynProxy2.dll
e) Use Boo compiler to compile StaticProxyFactory.dll (look at original
Program class to see how to do this - remember to add all assemblies used by
NHibernate configuration)
f) Use ILMerge to merge compile time proxies in CastleDynProxy2.dll with
StaticProxyFactory class in StaticProxyFactory.dll (remember to name output
library to the library specified in original loaded nhibernate
configuration)

Note there is a spelling mistake in original Program class. Replace the
occurance of StatixProxyFactory with StaticProxyFactory. (The x should be a
c)

In summary I made three important changes:
1) I dropped the ActiveRecord support as I do not use it and do not think it
should be assumed
2) Only used nhibernate configuration instance (I created configuration
instance from my normal config file, but others might use a different
method)
3) I altered the StaticProxyFactory.boo so that its static _proxies
dictionary will compile to a generic dictionary that maps System.Int64 to
System.Type. this is important as it is a bug

I hope this helps. If you have any questions, please feel free to email and
ask. I hope you can understand that I am not allowed to supply code, but I
do want to help.

Johan Kirsten

> ----------------------------------------------------------------------
>
> Message: 1
> Date: Wed, 3 Sep 2008 19:33:11 -0300
> From: "Fabio Maulo" <fabio...@gmail.com>
> Subject: Re: [NHibernate-development] Speed improvement using compile
> time generated proxies
> To: "the NHibernate development list"
> <nhibernate-...@lists.sourceforge.net>
> Message-ID:
> <bc77d5880809031533q27e...@mail.gmail.com>
> Content-Type: text/plain; charset="iso-8859-1"


>
> Do you can send me the solution with all your sources and required
> external
> lib ?Thanks.
>

-------------------------------------------------------------------------

Andrew Mayorov

unread,
Sep 4, 2008, 3:39:24 AM9/4/08
to the NHibernate development list

Hi!

 

Guys, can anyone explain why precompiled proxy could be faster than runtime generated in real application? Proxy generation should be one time operation for each type, and as soon as we’ve made a proxy for particular type there should be no difference in method of its creation. Yes, first query with precompiled proxy would execute faster, but all subsequent should have the same speed.

 

Best,

Andrew

Fabio Maulo

unread,
Sep 4, 2008, 8:53:27 AM9/4/08
to the NHibernate development list
2008/9/4 Johan Kirsten <jo...@goo.co.za>

Greetings

Unfortunately I am not able to supply source code, as I am under contract.

Absolutely all your code is "under contract" ? Really you can't share a piece of base code (no business code)?
Are you sure ?
If so, you have a really good employer!
He are using the effort of dozen programmers without spent a cent and he don't want share something to improve a product he is using ?
Really good place where work.

--
Fabio Maulo

Ayende Rahien

unread,
Sep 4, 2008, 8:56:51 AM9/4/08
to the NHibernate development list
In other words, please go to the employer and tell him the scenario and that this is test code with no relation to the actual business.
That tend to get you a release.

Fabio Maulo

unread,
Sep 4, 2008, 9:02:11 AM9/4/08
to the NHibernate development list
2008/9/4 Ayende Rahien <aye...@ayende.com>

In other words, please go to the employer and tell him the scenario and that this is test code with no relation to the actual business.
That tend to get you a release.

jajajajaja
even if I'm Italian the diplomazia is not my best

--
Fabio Maulo

Ayende Rahien

unread,
Sep 4, 2008, 9:14:41 AM9/4/08
to the NHibernate development list
Oh my god! I never thought that the day would come where _I_ would be the one who is considered polite.

Tuna Toksöz

unread,
Sep 4, 2008, 9:17:38 AM9/4/08
to the NHibernate development list
And make sure your employer signs the paper about this issue, just to be on the safe side.
--
Tuna Toksöz

Typos included to enhance the readers attention!
Reply all
Reply to author
Forward
0 new messages