IDisposable implementation in .NET

74 views
Skip to first unread message

Carl HOSSLER

unread,
Feb 3, 2020, 2:42:09 PM2/3/20
to or-tools-discuss
Hi,

Quick question regarding the implementation of the IDisposable interface in .NET: when calling LinearSolver.Solver.Dispose() method, does the method disposes of all the variables and constraints associated with the solver object or do does it just disposes of the solver object (at which point you will have dispose of the constraints and variables beforehand)?

Thanks a lot,
Carl

christoph...@ksb.com

unread,
Jul 8, 2021, 6:10:44 AM7/8/21
to or-tools-discuss
Hello Carl,

did you ever get an answer to this question?

We're facing a memory leak problem while using Google.OrTools.ConstraintSolver.Solver in c# during performance testing, in which hundreds of thousands of Solvers are created. We've simply been setting the c# references to the Solver to null and relying on the garbage collection to clean up, but that doesn't appear to be enough.

Laurent Perron

unread,
Jul 8, 2021, 7:05:15 AM7/8/21
to or-tools-discuss
For both, deleting the solver will delete all solver objects associated.

Now, we have seen the GC trailing if the rate of model creation/deletion is high.
Laurent Perron | Operations Research | lpe...@google.com | (33) 1 42 68 53 00



--
You received this message because you are subscribed to the Google Groups "or-tools-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to or-tools-discu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/or-tools-discuss/69d9800b-a3ca-400f-bcdc-ef08c874e3c5n%40googlegroups.com.

christoph...@ksb.com

unread,
Jul 8, 2021, 7:19:27 AM7/8/21
to or-tools-discuss
Thank you for the clarification.

christoph...@ksb.com

unread,
Sep 9, 2021, 3:46:33 AM9/9/21
to or-tools-discuss
I've got some test results that may be interesting with regard to this question.

When faced with memory leak problems, our IT consultant recommends focusing on single small actions but repeating them thousands of times. 

I therefore made the following test program (c#) to exercise creation and deletion of  Google.OrTools.ConstraintSolver.Solver  and IntVar objects:

class Program
    {
        const int nloops = 10000;
        const int nvars = 1000;
        const long maxval = 50;
        static void Main(string[] args)
        {
            string name = "solver";
            for (int i = 0; i < nloops; i++)
            {
                Google.OrTools.ConstraintSolver.Solver solver = new Google.OrTools.ConstraintSolver.Solver(name);
                Google.OrTools.ConstraintSolver.IntVar[] vars = new Google.OrTools.ConstraintSolver.IntVar[nvars];
                for (int j = 0; j < nvars; j++)
                {
                    vars[j] = solver.MakeIntVar(0L, maxval);
                }
                for (int j = 0; j < nvars; j++)
                {
                    vars[j].Dispose();
                    vars[j] = null;
                }
                vars = null;
                solver.Dispose();
                solver = null;
            }
        }
    }

The program finishes in 7 seconds on my machine, the memory allocation during the test looks like this:

hamkchr_2021.09.07_006.png


The blue and maroon colors at the bottom of the graph are the "managed" memory, i.e. that which DotNet is managing, the gray area at the top is the "unmanaged" memory, i.e. that which is allocated (among other things) by the OR-Tools c++ methods for the Solver and the objects it creates.

If I change the code to not call the Dispose() method on the IntVar's (but still delete their c# reference by setting to null):

...
                for (int j = 0; j < nvars; j++)
                {
                    //vars[j].Dispose();
                    vars[j] = null;
                }
        ...

Then the program takes over 5 minutes to complete and there is huge pressure on the garbage collection. The garbage collection simply doesn't catch up, both the managed and unmanaged memory continue to grow as long as the test is running and are only freed up at the end after the program exits.

hamkchr_2021.09.07_008.png

So it appears that there is a big difference between explicitly calling Dispose on the IntVar's or letting the Solver.Dispose() take care of it. Or could there be a bug in the Solver.Dispose() that leaves something undisposed?

Test was done with Google.OrTools, Version=9.0.9048.0, Culture=neutral, PublicKeyToken=53dbb1ea090cbef7
Reply all
Reply to author
Forward
0 new messages