ValeraT1982 / ObjectsComparer

C# Framework provides mechanism to compare complex objects, allows to override comparison rules for specific properties and types.
MIT License
352 stars 86 forks source link

Memory leak issue #51

Open SergNikitinSharpDev opened 1 year ago

SergNikitinSharpDev commented 1 year ago

We've used a simple method that resulted in a memory leak in our application:

private bool CompareEntities<T>(T object1, T object2)
{
    var comparer = new ObjectsComparer.Comparer<T>();

    return comparer.Compare(object1, object2, out IEnumerable<Difference> _);
}

image

The method was used in a background job.

ValeraT1982 commented 1 year ago

Can you please provide more information? Does it help if you change

return comparer.Compare(object1, object2, out IEnumerable<Difference> _); to return comparer.Compare(object1, object2);

wholroyd commented 1 year ago

I recently started using the library and ran into the same issue. It only occurs with return comparer.Compare(object1, object2, out IEnumerable<Difference> _);. The root cause is from an unexpected infinite recursion.

Here is a screen shot of two objects that this occurred on (here is the JSON format of them): image

I got this far before it hung, so it was able to detect the most obvious differences between them:

Difference: DifferenceType=ValueMismatch, MemberPath='LastModified', Value1='04-26-2021 06:33:56 AM', Value2='05-24-2023 07:03:47 PM'. Difference: DifferenceType=ValueMismatch, MemberPath='Revision', Value1='2d757694-224a-46a2-93a1-d353e38f1518', Value2='2023-05-24T19:03:47.613Z'.

I was able to resolve my issue by changing the class type for the Filters property in the objects from Newtonsoft's JObject to dynamic. The JObject class has parent <-> child references on the object tree, so it's most likely getting stuck here recursively going down the children, coming back up on the parent reference, and isn't aware the object was already evaluated, continuously evalating the object tree until terminated.

Here is the class definition for the Result list entry:

public class Result
{
    public string Id { get; set; }
    public string Title { get; set; }
    public string LastModified { get; set; }
    public string Revision { get; set; }
    public string ShortTitle { get; set; }
    public string Description { get; set; }
    public string FeatureImage { get; set; }
    public string Action { get; set; }
    public string ActionType { get; set; }
    public string ActionLink { get; set; }
    public string BrandName { get; set; }
    public string BrandImage { get; set; }
    public string Priority { get; set; }
    public string Page { get; set; }
    public string Template { get; set; }
    public string Position { get; set; }
    public string Initiative { get; set; }
    public string OverlayTheme { get; set; }
    public List<Parameter> Parameters { get; set; }
    public dynamic Filters { get; set; } // it hangs if the type here if Newtonsoft's JObject class is used
    public string DisplayStartDate { get; set; }
    public string ExpirationDate { get; set; }
}

Hope this helps!

Bortxop commented 4 months ago

Im running into the same problem but in my case the memory leak appears when trying to access the properties of IEnumerable. Thanks to @wholroyd issue I have assumed correctly that the following property was the problem: public CultureInfo DefaultCultureInfo { get { return CultureInfo.GetCultureInfo(DefaultCulture); } }

I won't try your approach since I don't like dynamic variables but thanks!

ValeraT1982 commented 4 months ago

@Bortxop can you please provide more information about your case?