Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
An improvement on SessionFactory Initialization

UPDATE: I have just committed the PersistentConfigurationBuilder for Castle NHibernate Facility. Thank you Jonathon Rossi for informing me!

We have received several complaints about slowness of SessionFactory initialization when there’s hundreds of entities, and Ayende has replied one of them here. It even gets worse if you’re using it in a web environment. You may think that it is not a problem since SessionFactory is initialized once in a web environment, but the major impact is not on production but development. Think how many times you start your application a day.

The problem is not really with NHibernate but with xml validation against the schema. Here are some profiler results for SessionFactory initialization with one thousand entities:

 image

As you see, the adding XML resources takes the most time and the reason behind this is the schema validation. There is also an I/O cost involved (1040 resources should be read by NHibernate). There are several ways to get rid of it, one being the serialization of configuration. I spend 3 days (statics prevented me from spotting some bugs in the code) on this and I believe it pretty much works for every configuration. Another way of doing this is the merging of HBM files, which I believe faster than Serialization as Deserialization also takes some amount.

Now the results for the one using the Deserialized Configuration.

 image

A nice feature of dotTrace allows us to compare the performance improvements over the old way.

 image

We got 10 seconds rescued! Yay!

Now I am going to show how I used this feature in Castle NHibernate Facility. We have IConfigurationBuilder that is used to integrate various Configuration sources (such as FluentNHibernate).

First of all I must ensure that if any of the files that are used to create the Configuration change, we shouldn’t use the serialized configuration, instead the Configuration should be re-created.

public override Configuration GetConfiguration(IConfiguration config)
{
    log.Debug("Building the Configuration");

    string fileName = config.Attributes["fileName"];

    IConfiguration dependsOn = config.Children["dependsOn"];
    IList<string> list = new List<string>();

    foreach (var on in dependsOn.Children)
        list.Add(on.Value);

    Configuration cfg;
    if (IsNewConfigurationRequired(fileName, list))
    {
        log.Debug("Configuration is either old or some of the dependencies have changed");
        using(var fileStream = new FileStream(fileName, FileMode.OpenOrCreate))
        {
            cfg = base.GetConfiguration(config);
            this.WriteConfigurationToStream(fileStream, cfg);
        }
    }
    else
    {
        using (var fileStream = new FileStream(fileName, FileMode.OpenOrCreate))
        {
            cfg = this.GetConfigurationFromStream(fileStream);
        }
    }
    return cfg;
}



protected virtual bool IsNewConfigurationRequired(string fileName,IList<string> dependencies)
{
    if (!File.Exists(fileName))
        return true;
    FileInfo fi = new FileInfo(fileName);
    DateTime lastModified = fi.LastWriteTime;
    bool requiresNew=false;
    for (int i = 0; i < dependencies.Count && !requiresNew; i++)
    {
        FileInfo dependency = new FileInfo(dependencies);
        DateTime dependencyLastModified = dependency.LastWriteTime;
        requiresNew |= dependencyLastModified > lastModified;
    }
    return requiresNew;
}

Code doesn’t look really good, I guess, so I am open to any suggestions on improvement. The code is not yet in Castle Codebase, as our NH dependency on trunk is not the latest (and i am too lazy to update it). When I find time, I may update the dependency if others agree.

There is one thing that you have to be careful about. You must be aware that if you’re using IUserType, IInterceptor, ISqlFunction etc, all of those should be Serializable too!


Posted 03-14-2009 1:40 AM by Tuna Toksoz
Filed under:

[Advertisement]

Comments

DotNetKicks.com wrote An Improvement on SessionFactory initialization
on 03-13-2009 6:54 PM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

DotNetShoutout wrote An improvement on SessionFactory Initialization - Tuna Toksoz
on 03-14-2009 12:04 AM

Thank you for submitting this cool story - Trackback from DotNetShoutout

labilbe wrote re: An improvement on SessionFactory Initialization
on 03-14-2009 2:19 AM

Nice try!

How much dependencies a real case scenario can handle?

Tuna Toksoz wrote re: An improvement on SessionFactory Initialization
on 03-14-2009 5:21 AM

@labilbe I guess as many as neccessary(even if it is linear), because in general you put your mappings in assemblies not more than 10 lets say, and if you specify dependencies on them, it would still be advantageous.

Parag Mehta wrote re: An improvement on SessionFactory Initialization
on 03-15-2009 5:07 AM

File Serialization is bound to have problems in the web environment. I would suggest you do a thread safety check and see how much you are gaining out of this.

Tuna Toksoz wrote re: An improvement on SessionFactory Initialization
on 03-15-2009 5:11 AM

My guess is that Castle handles thread safety for me.

Reflective Perspective - Chris Alcock » The Morning Brew #307 wrote Reflective Perspective - Chris Alcock &raquo; The Morning Brew #307
on 03-16-2009 4:16 AM

Pingback from  Reflective Perspective - Chris Alcock  &raquo; The Morning Brew #307

Ben Scheirman wrote re: An improvement on SessionFactory Initialization
on 03-16-2009 12:05 PM

Whoa, deja vu!  We talked about this in the first ALT.NET Conference in Austin a couple years ago.

Two things came out of that:

 *  possibly serializing & storing configuration to speed up the startup cost

 *  creating a model for mappings that is already compiled.

Sadly the first item never really was investigated (to my knowledge) and the 2nd... well I tried but lost interest.  Luckily the Fluent Nhibernate project came along and did a much better job!  I'd like to see the FNH model make it's way directly into the NH mapping, rather than still using XML.  It would sidestep this problem completely.

Good stuff, Tuna!

Tuna Toksoz wrote re: An improvement on SessionFactory Initialization
on 03-16-2009 12:47 PM

Hi Ben,

I tried making FNH work with NH mapping(metadata) but due to lack of time I suspended it for a while. Hope to going it back soon.

Ashish wrote re: An improvement on SessionFactory Initialization
on 04-30-2009 2:41 AM

By merging hbm.xml do you mean having one hbm.xml and merging all mapping under one

<Hibernate>

<class 1>

</class 1>

<class 2>

</class 2>

</hibernate>

Is this what you mean?

Tuna Toksoz wrote re: An improvement on SessionFactory Initialization
on 04-30-2009 3:06 AM

Exactly.

Tecnocrata wrote Como acelerar la construccion del NHibernate SessionFactory
on 07-22-2011 11:45 PM

Hola, voy a cubrirme un poco antes de que entren a leer completamente el articulo, lo que se logra con

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)