What is the best way to improve performance of NHibernate? [closed]
The first and most dramatic performance problem that you can run into with NHibernate is if you are creating a new session factory for every session you create. Only one session factory instance should be created for each application execution and all sessions should be created by that factory.
Along those lines, you should continue using the same session as long as it makes sense. This will vary by application, but for most web applications, a single session per request is recommended. If you throw away your session frequently, you aren't gaining the benefits of its cache. Intelligently using the session cache can change a routine with a linear (or worse) number of queries to a constant number without much work.
Equally important is that you want to make sure that you are lazy loading your object references. If you are not, entire object graphs could be loaded for even the most simple queries. There are only certain reasons not to do this, but it is always better to start with lazy loading and switch back as needed.
That brings us to eager fetching, the opposite of lazy loading. While traversing object hierarchies or looping through collections, it can be easy to lose track of how many queries you are making and you end up with an exponential number of queries. Eager fetching can be done on a per query basis with a FETCH JOIN. In rare circumstances, such as if there is a particular pair of tables you always fetch join, consider turning off lazy loading for that relationship.
As always, SQL Profiler is a great way to find queries that are running slow or being made repeatedly. At my last job we had a development feature that counted queries per page request as well. A high number of queries for a routine is the most obvious indicator that your routine is not working well with NHibernate. If the number of queries per routine or request looks good, you are probably down to database tuning; making sure you have enough memory to store execution plans and data in the cache, correctly indexing your data, etc.
One tricky little problem we ran into was with SetParameterList(). The function allows you to easily pass a list of parameters to a query. NHibernate implemented this by creating one parameter for each item passed in. This results in a different query plan for every number of parameters. Our execution plans were almost always getting released from the cache. Also, numerous parameters can significantly slow down a query. We did a custom hack of NHibernate to send the items as a delimited list in a single parameter. The list was separated in SQL Server by a table value function that our hack automatically inserted into the IN clause of the query. There could be other land mines like this depending on your application. SQL Profiler is the best way to find them.
NHibernate's SessionFactory is an expensive operation so a good strategy is to creates a Singleton which ensures that there is only ONE instance of SessionFactory in memory:
public class NHibernateSessionManager
{
private readonly ISessionFactory _sessionFactory;
public static readonly NHibernateSessionManager Instance = new NHibernateSessionManager();
private NHibernateSessionManager()
{
if (_sessionFactory == null)
{
System.Diagnostics.Debug.WriteLine("Factory was null - creating one");
_sessionFactory = (new Configuration().Configure().BuildSessionFactory());
}
}
public ISession GetSession()
{
return _sessionFactory.OpenSession();
}
public void Initialize()
{
ISession disposeMe = Instance.GetSession();
}
}
Then in your Global.Asax Application_Startup, you can initialize it:
protected void Application_Start()
{
NHibernateSessionManager.Instance.Initialize();
}
Avoid and/or minimize the Select N + 1 problem by recognizing when to switch from lazy loading to eager fetching for slow performing queries.
No a recommendation but a tool to help you : NH Prof ( http://nhprof.com/ ) seems to be promising, it can evaluate your use of the ORM framework. It can be a good starting point for your tunning of NHibernate.