1

I'm developing a Windows Service with C# and .NET Framework 4.6.2 and Entity Framework 6.1.3.

I have a Web API interface on that service and in one Controller's method I create a Dictionary with more than one million strings:

Dictionary<string, List<string>> codes;

This Dictionary is created inside another method:

codes = GetCodesAsDictionary(connectionString, productionId);

I pass this variable to a static method from a static class.

One Visual Studio 2015's memory profiler I see how memory grows to 1,1Gb when I call this method, but when the method ends, the memory keep as 1,1Gb.

If I call the method again, memory grows again to 2Gb, and after method finishes, memory goes to 1,1Gb again.

I have tried to pass the codes variable as reference, but I get the same memory allocation. I have to stop the service and re-run it again to release that 1,1Gb. By the way, I pass it by reference because I don't want that the static method makes a copy of it.

Do you know why it doesn't release such amount of memory after method ends?

UPDATE:

I have changed the static class with an instance class (copying the method from static class) and I get the same result (1,1Gb memory allocated).

SECOND UPDATE:

I have also changed how the dictionary is created:

Dictionary<string, List<string>> codes = null;
GetCodesAsDictionary(connectionString, productionId, out codes);

And I get the same result: 1,1Gb memory allocated.

THIRD UPDATE:
I have changed the Dictionary with a KeyValuePair<byte, string[]>[] and I get the same result, 1,1Gb allocated. Now, instead of using a string as key, I'm using byte.

VansFannel
  • 45,055
  • 107
  • 359
  • 626

2 Answers2

0

Do you know why it doesn't release such amount of memory after method ends?

If there aren't any references hanging around any more, it could just be that the garbage collector doesn't feel the urge to free that memory, even though it isn't in use any more.

You can try to force garbage collection and see if the memory is freed. If not, there is probably an issue with your code.

(Side note: if you have a high amount of repetition in the strings, you might benefit from interning them. It will minimize the memory pressure a lot. This will however keep those strings allocated at all time.)

Community
  • 1
  • 1
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
0

are you sure the dictionary is created and used only in that method?

If nothing else helps, you could try to use GC.Collect(), but this should be only used as a last resort.

https://msdn.microsoft.com/en-us/library/system.gc.collect(v=vs.110).aspx

EDIT: You can try to use GC.AddMemoryPressure method instead of what I recommended earlier. You need to pass the amount of the Memory to make the GC aware of the fact that there is some memory that could be collected.

https://msdn.microsoft.com/en-us/library/system.gc.addmemorypressure(v=vs.110).aspx

Try if the following works for you:

Dictionary<string, List<string>> codes = new Dictionary<string, List<string>>();
long bytesBefore = GC.GetTotalMemory(true);

// Code that adds items to your dictionary comes here

long bytesAfter = GC.GetTotalMemory(true);

// After your method ends:
GC.AddMemoryPressure((long) (bytesAfter - bytesBefore));
Thomas Flinkow
  • 4,845
  • 5
  • 29
  • 65