0

Within my application, I'm having memory usage issues where the Loh is filling up with dead objects, 1.5GB worth (seen below). The objects are being stored in a Byte array.

enter image description here

I've tried to clean it up by running the following code to reduce memory usage but it doesn't seem to be functioning.

private static void OnScavengeProfileCache(object data)
{
 // loop until the runtime is shutting down
while(HostingEnvironment.ShutdownReason == ApplicationShutdownReason.None)
{
    // NOTE: Right now we only do the scavenge when traffic is temporarily low,
    // to try to amortize the overhead of scavenging the cache into a low utilization period.
    // We also only scavenge if the process memory usage is very high.
    if (s_timerNoRequests.ElapsedMilliseconds >= 10000)
    {
        // We dont want to scavenge under lock to avoid slowing down requests,
        // so we get the list of keys under lock and then incrementally scan them
        IEnumerable<string> profileKeys = null;
        lock (s_profileCache)
        {
             profileKeys = s_profileCache.Keys.ToList();
        }


        ScavengeProfileCacheIncremental(profileKeys.GetEnumerator());
    }

    // wait for a bit
    Thread.Sleep(60 * 1000);
}
}

private static void ScavengeProfileCacheIncremental(IEnumerator<string> profileKeys)
{
if (s_thisProcess.PrivateMemorySize64 >= (200 * 1024 * 1024) ) // 3Gb at least
{
    int numProcessed = 0;
    while(profileKeys.MoveNext())
    {
        var key = profileKeys.Current;
        Profile profile = null;
        if (s_profileCache.TryGetValue(key, out profile))
        {
            // safely check/remove under lock, its fast but makes sure we dont blow away someone currently being addded
            lock (s_profileCache)
            {
                if (DateTime.UtcNow.Subtract(profile.CreateTime).TotalMinutes > 5)
                {
                    // can clear it out
                    s_profileCache.Remove(key);
                }
            }
        }

        if (++numProcessed >= 10)
        {
            // stop this scan and check memory again
            GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
            GC.Collect(); 
            break;
        }
    }
}
}

Any tips on how I should go about cleaning up memory usage here?

  • 1
    Possible duplicate of [Large Arrays, and LOH Fragmentation. What is the accepted convention?](https://stackoverflow.com/a/29520108/34092) – mjwills Sep 20 '18 at 13:15
  • Should you count even the profiles that you don't remove here? – 500 - Internal Server Error Sep 20 '18 at 13:18
  • `MemoryCache` is likely the right solution since the data will automatically expire - you don't need to do it manually like you are here. – mjwills Sep 20 '18 at 21:17
  • Memory caching is a foreign topic to me, any advice on how I could go about implementing it? @mjwills –  Sep 21 '18 at 00:04
  • I'd suggest reading the docs for `MemoryCache` and having a play with it, and then creating a new question with any specific questions you have. – mjwills Sep 21 '18 at 00:15

1 Answers1

-1

try System.GC.Collect() forces garbage collector to run. This should clean out dead objects

China Syndrome
  • 953
  • 12
  • 24