I was started choosing orm systems since few weeks ago and little bit struggle in use NH or EF. I know there was a big argument around which one's better, which i'm not quite interested to discuss here, but I did test some basic performance of both.
I have to say I really like the flexibility NH provided, but I still bit concern about the performance, especially materialization of NH is much slower than EF.
Although I temporary chose EF as the Orm of my currently project, but I hope that can switch back to NH once the performance has been improved.
But, anyway, after reviewing and profile NH code for few hours, I tried to make some small change to improve the performance,
here's what I found.
When NH materialize Linq query, it uses dynamicinvoke to construct object, which is obviously slow. After change the constructor call delegate (both in Linq\ResultTransformer and Linq\ExpressionToHqlTranslationResults) from Delegate type to Func<object[],object> type ( for item transformer only as testing, but list transformer should be same), the time costed reduced to less than 50%.
Here's some test result, retrieve 200001 rows, simple entity.
Entity (single table in db):
public class Person
{
[Key]
public virtual int PersonId { get; protected set; }
[StringLength(100)]
public virtual string FirstName { get; set; }
[StringLength(100)]
public virtual string LastName { get; set; }
}
Query(Session is status less):
int agr = 0;
foreach (var pp in session.Query<Person>().Where(p => p.PersonId > 0)
.Select(p => new { p.PersonId, p.FirstName, p.LastName }))
//.Take(100))
{
agr++;
}
return agr;
Before changing this query took 1.2 seconds (while EF took 0.2 second) on my machine ( SQL express, i5 3.1Ghz 4GB win7).
After changing this query took 0.5 to 0.6 seconds.
This is the quick change I can discover so far.
Some other place I've looked is NH 's retrieve row/column data and converting types designed little bit too heavy, but changing this requires changing the code structur, which I dont have to do yet. Something I can think about to be small change is it uses lots of Converto.Toxxx() method which I believe to be a performance impact, and also, after it do a conversion (in most case is unnecessary) it do a boxing again, so there's some extra steps can be removed.
Hope it helps.
Regards,
Steven