NHibernate Forge
The official new home for the NHibernate for .NET community

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 mar 13 2009, 09:18 p.m. by Tuna Toksoz
Filed under: ,

Comments

Jonathon Rossi wrote re: An improvement on SessionFactory Initialization
on 03-14-2009 4:40

I updated NHibernate on the Castle trunk to r4123 a few days ago. I can't see any since then you would need.

Tuna Toksoz wrote re: An improvement on SessionFactory Initialization
on 03-14-2009 6:45

I should have missed this, Jonathon. Thanks for the information!

Tuna Toksoz wrote re: An improvement on SessionFactory Initialization
on 03-14-2009 18:31

I have committed the changes. Thank you Jonathon!

antoschka wrote re: An improvement on SessionFactory Initialization
on 06-13-2009 8:57

you didn't explain much about the way how accelerated the startup, in a scenario not using castle. What do you mean by "serialization of configuration". Could you explain a little more on that.

I face a lot of problems during startup of an application. I still use hbms for mapping (seperate ones for each entity). What do you recommand to speed up the starting process?

Thanks for your reply

antoschka

Tuna Toksoz wrote re: An improvement on SessionFactory Initialization
on 06-13-2009 9:02

Hi @antoschka

This is not specific to castle. All you need is to have a configuration that has mappings loaded, then you'll need to serialize it into a file. This is for the first time. Later all you need to do is deserialize the configuration and you'll be good to go.

Lucis Ferre wrote Speed up nHibernate startup with object serialization
on 09-19-2009 2:31

Speed up nHibernate startup with object serialization

Lucis Ferre wrote Speed up nHibernate startup with object serialization
on 09-19-2009 16:49

Speed up nHibernate startup with object serialization

Lucis Ferre wrote Speed up nHibernate startup with object serialization
on 10-05-2009 13:33

Speed up nHibernate startup with object serialization

Development With A Dot wrote Speeding Up NHibernate Startup Time
on 04-01-2010 6:36

One technique I use and posted on the NHUsers mailing list consists in serializing a previously-configured

lucisferre wrote Speed up nHibernate startup with object serialization
on 05-11-2010 20:51

Speed up nHibernate startup with object serialization

hace wrote re: An improvement on SessionFactory Initialization
on 04-11-2011 8:43

Small issue in the code above:

FileInfo dependency = new FileInfo(dependencies);

should be:

FileInfo dependency = new FileInfo(dependenciesIdea);

Powered by Community Server (Commercial Edition), by Telligent Systems