[vtkusers] C#/VTK Memory Leak

Theodore Holden theodoreholden at yahoo.com
Fri May 8 16:00:22 EDT 2009


If I can solve one or two more problems here, I'll be looking at replacing an existing system of around 12,000 lines of OpenGL code with a couple of hundred lines of VTK code, and the VTK graphics look better.  It's probably a common situation, the data involved is fairly simple but the existing code for presenting it is byzantine and borderline unmaintainable.  

But there's a big and non-obvious problem with a memory leak in the picture.  The application reads data from a proprietary file, writes that data out to a .vtk file, and then calls a function which uses VTK code to draw the data on a VTK form which is created using the sourceforge wrapper library and component for c# available at http://vtkdotnet.sourceforge.net/.

The problem I'm seeing is definitely in the VTK code and not any part of the code which generates the data.  If I insert a return statement just prior to the call to the vtk code, the memory leak vanishes.

Worse, the Red-Gate ANTS memory profiler offers no help;  it shows the largest objects in the system being a couple of inconsequential byte arrays which are definitely not part of the problem.

The examples provided show functions with names like AddConeSurfaceToWindow and AddFlamingoToWindow.

Trying to use the same techniques produces a function which looks like this:


       // 3d texture
        void AddBagVolumeToWindow4(vtk.vtkRenderWindow renWin)
        {
            // 3d texture map
            vtkStructuredPointsReader reader = new vtkStructuredPointsReader();
            vtkVolume volume = new vtkVolume();
            vtkVolumeProperty volumeProperty = new vtkVolumeProperty();            
            vtkRenderer renderer = new vtkRenderer();
            vtkRenderWindowInteractor interactor = new vtkRenderWindowInteractor();
            vtkVolumeTextureMapper3D volumeMapper = new vtkVolumeTextureMapper3D();
            vtkPiecewiseFunction opacity = new vtkPiecewiseFunction();
            vtkColorTransferFunction color = new vtkColorTransferFunction();

            reader.SetFileName("c:\\zz.vtk");
            reader.Update();
            ifileLoaded = 1;  

            opacity.AddPoint(0, 0);
            opacity.AddPoint(64, .005);
            opacity.AddPoint(127, .01);
            opacity.AddPoint(128, .05);
            opacity.AddPoint(200, .5);

            color.AddRGBPoint(0, 1, 1, 1);
            color.AddRGBPoint(126, .665, .84, .88);
            color.AddRGBPoint(127, 0, 1, 0);
            color.AddRGBPoint(199, 1, 0, 0);

            volumeProperty.SetColor(color);
            volumeProperty.SetScalarOpacity(opacity);
            volumeProperty.SetInterpolationTypeToLinear();
            volumeProperty.ShadeOn();

            volumeMapper.SetInput(reader.GetOutput());

            volume.SetMapper(volumeMapper);
            volume.SetProperty(volumeProperty);

            renderer.SetBackground(1, 1, 1);
            renderer.AddVolume(volume);
            interactor.SetRenderWindow(renWin);           

            renWin.AddRenderer(renderer);

            renWin.Render();
            interactor.Start();

            reader.Dispose();
            volume.Dispose();
            volumeProperty.Dispose();
            renderer.Dispose();
            interactor.Dispose();
            opacity.Dispose();
            color.Dispose();

            vtk.vtkWin32OpenGLRenderWindow win32win =
                vtk.vtkWin32OpenGLRenderWindow.SafeDownCast(renWin);
            win32win.Clean();
        }

Again testing indicates that the memory leak has nothing to do with code outside of this function and a memory profiler reputed to be the best provides no information.  I get the impression that many if not most VTK apps only need to put a particular 3D image on a screen once, while this function is called repeatedly as a succession of images is read in by the user.  Again the read process reads data and throws it out to c:\\zz.vtk, which the vtk code then reads.

It occurred to me that eliminating the repeated VTK constructor calls might help.  That leads to this code in the app constructor:


       public Form1()
        {  
            InitializeComponent();

            // clear out vtk widget screen
            vtkForm1.GetRenderWindow().Frame();
            vtkRenderer vr = new vtkRenderer();
            vr.SetBackground(1, 1, 1);
            vr.SetRenderWindow(vtkForm1.GetRenderWindow());
            vtkForm1.GetRenderWindow().AddRenderer(vr);
            vr.Clear();
            vr.Render();
            vtk.vtkWin32OpenGLRenderWindow win32win =
                vtk.vtkWin32OpenGLRenderWindow.SafeDownCast(vtkForm1.GetRenderWindow());
            win32win.Clean();

            // set viewing objects for 3D texture map model           
            volume4 = new vtkVolume();
            volumeProperty4 = new vtkVolumeProperty();
            renderer4 = new vtkRenderer();
            interactor4 = new vtkRenderWindowInteractor();
            volumeMapper4 = new vtkVolumeTextureMapper3D();    

            opacity = new vtkPiecewiseFunction();
            color   = new vtkColorTransferFunction();
            
            renderer4.AddVolume(volume4);            
            vtkForm1.GetRenderWindow().AddRenderer(renderer4);
            volume4.SetMapper(volumeMapper4);
            volume4.SetProperty(volumeProperty4);   
        }

and then a modified function to display images:


        void AddBagVolumeToWindow4(vtk.vtkRenderWindow renWin)
        {
            
            vtkStructuredPointsReader reader4 = new vtkStructuredPointsReader();
            reader4.SetFileName("c:\\zz.vtk");
            reader4.Update();

            opacity.AddPoint(0, 0);
            opacity.AddPoint(64, .005);
            opacity.AddPoint(128, .01);
            opacity.AddPoint(200, .05);
            opacity.AddPoint(220, .4);

            color.AddRGBPoint(64, .665, .84, .88);
            color.AddRGBPoint(128, 0, .746, .95);
            color.AddRGBPoint(220, 0, 1, 0);
            color.AddRGBPoint(230, 1, 0, 0);

            volumeProperty4.SetColor(color);
            volumeProperty4.SetScalarOpacity(opacity);
            volumeProperty4.SetInterpolationTypeToLinear();
            volumeProperty4.ShadeOn();

            volumeMapper4.SetInput(reader4.GetOutput());
            volumeMapper4.Update();

            renderer4.SetBackground(1, 1, 1);          
            interactor4.SetRenderWindow(renWin);  
           
            renWin.Render();
            interactor4.Start();

            reader4.Dispose();
            GC.Collect();
            
            vtk.vtkWin32OpenGLRenderWindow win32win =
                vtk.vtkWin32OpenGLRenderWindow.SafeDownCast(renWin);
            win32win.Clean();   
            
        }

But even that doesn't help.  The computer loses around 50MB each time a new image is read in and these images are not that large, more like around 10MB on average.  

Again I'm new at this, and any help or information would be appreciated.


Ted


      
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.vtk.org/pipermail/vtkusers/attachments/20090508/06e0d3af/attachment.htm>


More information about the vtkusers mailing list