Ik heb een tijdje een service draaien geschreven in .Net 4 (C#). Het doel van de service is op basis van wat input een hele berg berekeningen starten, op basis van de resultaten worden er nog meer berkeningen gestart, en zo nog een paar keer verder (een soort sneeuwbaleffect aan berkeningen). Dit draait best aardig, en schaalt redelijk op een quad core cpu, over het algemeen draait de server 80-90% cpu. De service gebruikt ook aardig wat geheugen maar dat is geen probleem, de server beschikt over 12GB. Nu loop ik de laatste tijd tegen wat limieten aan, en begint de garbage collector roet in het eten te gooien. Tijd dus voor wat analyse en optimalisatie! Ik heb perfmon gestart en zag dat de Large Object Heap zich nogal misdraagt:

De rode lijn is cpu usage, de andere de LOH size. Er is goed te zien dat zodra de LOH gegarbage-collect wordt dit hele nadelige gevolgen heeft. Nu heb ik gekeken wat er in de LOH staat:
Nogal veel...
Maar wat ik vooral vreemd is dat "MyNamespace.DataObject" er tussenstaat, deze class ziet er als volgt uit:
Als ik de types optel, kom ik aan 4 + 8 + 8 + 8 + 4 + 8 + 8 + 4 = 52 bytes, lang niet de 85000 bytes om op de LOH heap geplaatst te worden dus. Mijn vraag is (lang verhaal): begrijp ik het nu verkeerd? Iemand ideeen hoe op basis van deze output verder te gaan? Ik zou dit graag oplossen zodat de service weer gewoon lekker de hele dag 90% cpu kan draaien

De rode lijn is cpu usage, de andere de LOH size. Er is goed te zien dat zodra de LOH gegarbage-collect wordt dit hele nadelige gevolgen heeft. Nu heb ik gekeken wat er in de LOH staat:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| 0:069> !dumpheap -stat 0000000012aa0000 0000000228029b30 total 0 objects Statistics: MT Count TotalSize Class Name 000007ff004004f8 1 24 System.Collections.Generic.Dictionary`2+KeyCollection[[System.Threading.WaitHandle, mscorlib],[AtomPro.Foundation.Command.ICommand, AtomPro.Foundation]] 000007feee2dda40 1 24 System.Configuration.ConfigurationPermission ... *snip heleboel regels* ... 000007ff004b4340 2105207 50524968 System.Collections.Generic.SortedDictionary`2+KeyValuePairComparer[[System.DateTime, mscorlib],[MyNamespace.DataObject, MyNamespace]] 000007ff004da838 1025797 57444632 System.Collections.Generic.TreeSet`1[[System.Collections.Generic.KeyValuePair`2[[System.Int32, mscorlib],[MyNamespace.DataObject, MyNamespace]], mscorlib]] 000007ff004b4fc8 315239 60518832 System.Collections.Generic.Dictionary`2+Entry[[System.Int32, mscorlib],[System.Collections.Generic.SortedDictionary`2[[System.DateTime, mscorlib],[MyNamespace.DataObject, MyNamespace]], System]][] 000007ff003d99e8 2105206 84208240 System.Collections.Generic.SortedDictionary`2[[System.DateTime, mscorlib],[MyNamespace.DataObject, MyNamespace]] 000007ff004b45a0 2105207 117891592 System.Collections.Generic.TreeSet`1[[System.Collections.Generic.KeyValuePair`2[[System.DateTime, mscorlib],[MyNamespace.DataObject, MyNamespace]], mscorlib]] 00000000004e52c0 305592 363590976 Free 000007ff004da0b0 8182857 458239992 System.Collections.Generic.SortedSet`1+Node[[System.Collections.Generic.KeyValuePair`2[[System.Int32, mscorlib],[MyNamespace.DataObject, MyNamespace]], mscorlib]] 000007feea42eb90 53638 527013472 System.Double[] 000007ff002ad1d8 31404381 2261115432 MyNamespace.DataObject 000007ff004b4240 54384959 3045557704 System.Collections.Generic.SortedSet`1+Node[[System.Collections.Generic.KeyValuePair`2[[System.DateTime, mscorlib],[MyNamespace.DataObject, MyNamespace]], mscorlib]] |
Nogal veel...

code:
1
2
3
4
5
6
7
8
9
10
11
| class MyNamespace.DataObject { int DateTime DateTime double int double double int } |
Als ik de types optel, kom ik aan 4 + 8 + 8 + 8 + 4 + 8 + 8 + 4 = 52 bytes, lang niet de 85000 bytes om op de LOH heap geplaatst te worden dus. Mijn vraag is (lang verhaal): begrijp ik het nu verkeerd? Iemand ideeen hoe op basis van deze output verder te gaan? Ik zou dit graag oplossen zodat de service weer gewoon lekker de hele dag 90% cpu kan draaien