| From | Sent On | Attachments |
|---|---|---|
| Rasmus Kromann-Larsen | Dec 11, 2008 4:11 am | |
| Ayende Rahien | Dec 11, 2008 1:15 pm | |
| Ayende Rahien | Dec 11, 2008 1:18 pm | |
| Rasmus Kromann-Larsen | Dec 11, 2008 1:28 pm | |
| Ayende Rahien | Dec 11, 2008 1:37 pm | |
| Ben Lovell | Dec 11, 2008 1:47 pm | |
| Rasmus Kromann-Larsen | Dec 11, 2008 1:59 pm | |
| Rasmus Kromann-Larsen | Dec 11, 2008 2:08 pm | |
| Fabio Maulo | Dec 11, 2008 2:40 pm | |
| Davy Brion | Dec 14, 2008 10:17 am |
| Subject: | [nhusers] Possible NHibernate SessionFactory (LRUMap) Memory Leak? | |
|---|---|---|
| From: | Rasmus Kromann-Larsen (rasm...@gmail.com) | |
| Date: | Dec 11, 2008 4:11:08 am | |
| List: | com.googlegroups.nhusers | |
Hi,
I have been trying to pin down a memory leak in my wep app these past few weeks - and digging into my application with WinDbg revealed something fishy with the NHibernate SessionFactory in memory.
Context: It's a standard ASP.NET application using NHibernate 2.0.0.4000. I only use 1 SessionFactory since that seems to be the defacto standard - and my Sessions are disposed using something along the lines of Ayende's unit of work.
I have been analyzing a memory dump of a ~800mb .NET heap to figure out why it kept growing. One thing I found was around 1.9 million NHibernate.SqlCommand.SqlStrings and ~90000 HQLQueryPlans
MT Count TotalSize Class Name 0f7fb3e4 92382 3695280 NHibernate.Engine.Query.HQLQueryPlan 0eafd714 1939496 31031936 NHibernate.SqlCommand.SqlString
Digging down into the roots of one of these SqlStrings revealed that it was being stored in the query plan cache in the SessionFactoryImpl:
067016bc(NHibernate.Impl.SessionFactoryImpl)-> 06702470(NHibernate.Engine.Query.QueryPlanCache)-> 06703050(NHibernate.Util.SoftLimitMRUCache)-> 067030a0(NHibernate.Util.LRUMap)-> 067030d4(System.Collections.Hashtable)-> 0c8af170(System.Collections.Hashtable+bucket[])-> 02e30ccc(NHibernate.Util.SequencedHashMap+Entry)-> 02e2efdc(NHibernate.Engine.Query.HQLQueryPlan)-> 02e2f1dc(System.Object[])-> 02e2f1f0(NHibernate.Hql.Classic.QueryTranslator)-> 02e2f4c4(System.Collections.Generic.List`1 [[NHibernate.SqlCommand.SqlString, NHibernate]])
I checked and there was exactly 1 instance of the SessionFactoryImpl in the dump - checking it's size took a few hours, which is not surprising:
sizeof(067016bc) = 716798348 bytes (NHibernate.Impl.SessionFactoryImpl)
That is one big SessionFactory :-) Still tracking the SqlString I explored the query plan cache and ended up at the LRUMap, which according to the code is supposed to keep the last (128 in this case) most recently used queries in cache. The LRUMap looked like this:
Name: NHibernate.Util.LRUMap Fields: MT Field Offset Type VT Attr Value Name 0f76a554 4000e40 c ...ncedHashMap+Entry 0 instance 067030bc _sentinel 79101fe4 4000e41 10 ...ections.Hashtable 0 instance 067030d4 _entries 790ffcc8 4000e42 4 System.Int64 1 instance 104874 _modCount 79102290 4000e51 14 System.Int32 1 instance 128 maximumSize
That is, 128 max size. Examining the hashtable called Entries in the LRUMap revealed this though (some lines removed):
Name: System.Collections.Hashtable Size: 56(0x38) bytes Fields: MT Field Offset Type VT Attr Value Name 7912d9bc 400092b 4 ...ashtable+bucket[] 0 instance 0c8af170 buckets 79102290 400092c 1c System.Int32 1 instance 92382 count 79102290 400092d 20 System.Int32 1 instance 35331 occupancy 79102290 400092e 24 System.Int32 1 instance 112634 loadsize 79102290 4000930 2c System.Int32 1 instance 92391 version
Supposedly it contains ~90000 objects (count field) and a big (reachable) object size: sizeof(067030d4) = 716798264 bytes (System.Collections.Hashtable)
I have examined the LRUMap source and can't find any glaring mistakes, I looked at the LRUMapFixture, which didn't seem to contain any tests that verify that it actually is limited to it's max size. However, I made a unit test in my own test project:
[Test] public void LRUTest() { LRUMap map = new LRUMap(10);
for (int i = 0; i < 20000; i++) map.Add("str" + i, i);
Assert.AreEqual(10, map.Count); }
and this passed just fine.
Now this is where I am stumped, somehow my application manages to squeeze all these objects into the cache, but I haven't been able to reproduce it with simple tests.
Does anyone have an idea what could be the culprit?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To post to this group, send email to nhus...@googlegroups.com
To unsubscribe from this group, send email to
nhusers+unsu...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nhusers?hl=en
-~----------~----~----~----~------~----~------~--~---





