Memory Leak - LOH
Posted: Thu Jun 30, 2016 9:40 am
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
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