Page 1 of 1

Memory Leak - LOH

Posted: Thu Jun 30, 2016 9:40 am
by DoubleVerify
Hi,

When calling WURFLManager.GetDeviceForRequest(string) method with an Android useragent, the call stack creates memory inside LOH (Large Object Heap).
I was profiling WURFL and disassembled it and found out that it happens due to allocation of a new List<string> for each call to the method above.

The following is the call stack that make the most garbage into LOH:

UserAgenrProcessorMemoryInspector.Program.Main(String[])
-> UserAgenrProcessorMemoryInspector.Program.Run()
-> DoubleVerify.TP.Service.Data.UserAgentData.ProcessTemp(String)
-> DoubleVerify.TP.Service.Data.UserAgentData.TryGetWurflBrowser(String, InternalUserAgentData, Nullable<Int16>&, String&)
-> WurflWrapperVersion1_7.WurflWrapper1_7.GetCapabilities(String, String[])
-> WurflWrapperVersion1_7.WurflWrapper1_7.GetVirtualCapabilities(String, String[])
-> WURFL.WURFLManager.GetDeviceForRequest(String)
-> WURFL.WurflWorkerService.GetDeviceForRequest(WURFLRequest, MatchMode, Boolean)
-> WURFL.Devices.DeviceRepository.GetMatcherResponseByRequest(WURFLRequest)
-> WURFL.Matchers.Chains.MatcherChain.Match(WURFLRequest)
-> WURFL.Matchers.Chains.MatcherChain.Match(WURFLRequest)
-> WURFL.Matchers.Core.AbstractMatcher.Match(WURFLRequest)
-> WURFL.Matchers.Core.AbstractMatcher.ApplyConclusiveMatch(WURFLRequest)
-> WURFL.Matchers.Browsers.AndroidMatcher.LookForMatchingUserAgent(String)
-> WURFL.Matchers.StringMatcher.LongestCommonPrefixMatcher.Match(ICollection<String>, String, Int32)
-> System.Collections.Generic.List..ctor(IEnumerable<T>)

I was debugging WURFL code and saw that for the given call stack above, the List was instantiated with about 24,000 strings.
24,000 objects times 8 bytes for a reference type is more than 85,000, which means that the List will be allocated on the LOH.
Important to note: I've noticed this memory issue only for Android user agents.
This causes a huge penalty to our system as doing GC on the LOH is much more expensive, and more than that, it causes LOH to be fragmented over time.

Is there a workaround for making your code not to instantiate big objects on the LOH when calling to WURFLManager.GetDeviceForRequest(string) ?

Thanks,

Lior,
DoubleVerify

Re: Memory Leak - LOH

Posted: Wed Jul 20, 2016 3:21 pm
by aaronp
Per our email conversation:

We have made updates to the API (v1.7.1.1) so that only one static instance of List<string> is instantiated (during engine startup), as opposed to an instance per each request. While the List is still in LOH (given the size), the garbage collector will never remove it. In turn, performance is enhanced and there is no memory fragmentation.