Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

10k+ leaked objects from simple test #1343

Open
alliepiper opened this issue May 22, 2015 · 67 comments
Open

10k+ leaked objects from simple test #1343

alliepiper opened this issue May 22, 2015 · 67 comments
Assignees
Labels

Comments

@alliepiper
Copy link
Contributor

Running the test_meshfill_draw_mesh.py test leaks about 10,900 objects. This is very significant, as it means that rendering multiple large datasets, even properly scoped so no vcs objects are reachable, will quickly exhaust the available system memory. This is also causing issues interfacing with other modules that need objects to be freed before the interpreter shuts down.

This is easy to test for manually:

  1. Take any existing test, and put the entire file, imports and all, into a def runTest(): block.
  2. Change any sys.exit(x) calls into return x.
  3. Add the following to the bottom of the script:
import gc
gc.enable()
gc.set_debug(gc.DEBUG_LEAK)

result = runTest()

gc.collect()

for i,g in enumerate(gc.garbage):
    print "Leak %d: %s @0x%x:\n   %s"%(i, type(g), id(g), str(g)[:70])

import sys
sys.exit(result)

The results of test_meshfill_draw_mesh.py are here: https://gist.github.com/dlonie/2d72d0cfa4a52271bb7a

@alliepiper alliepiper added the VCS label May 22, 2015
@doutriaux1
Copy link
Contributor

Admittedly I just quickly glanced at it. But there seems to be a lot of DV3D ref in there. Why are they even here? Meshfill shouldn't be using it.

@alliepiper
Copy link
Contributor Author

Not sure, but my guess is that it's related to bloat in the vcs/__init__.py file.

@ThomasMaxwell
Copy link
Contributor

It would be useful to distinguish between leaked objects that are allocated on a per-plot basis and those that are allocated once at app initialization. The leaked objects that are allocated once at app startup are probably relatively small and ignorable .

From: David Lonie <[email protected]mailto:[email protected]>
Reply-To: UV-CDAT/uvcdat <[email protected]mailto:[email protected]>
Date: Tuesday, May 26, 2015 at 12:16 PM
To: UV-CDAT/uvcdat <[email protected]mailto:[email protected]>
Subject: Re: [uvcdat] 10k+ leaked objects from simple test (#1343)

Not sure, but my guess is that it's related to bloat in the vcs/init.py file.


Reply to this email directly or view it on GitHubhttps://github.com//issues/1343#issuecomment-105584135.

@alliepiper
Copy link
Contributor Author

Ignoring leaks is a bad practice, as is initializing objects that aren't needed. It would be good to clean up both of these, as they have performance implications.

Leaks are especially dangerous when mixing python with other languages, as the issue we're now seeing is that leaks in vcs are causing segfaults in external modules that are trying to clean up the leaked memory after the python session finishes, but need to release their allocations while the interpreter is active.

@doutriaux1 doutriaux1 added this to the 2.3 milestone May 26, 2015
@aashish24
Copy link
Contributor

@ThomasMaxwell I don't know how do we do that but yes, I agree that having that information might be helpful. However, like @dlonie said, we should fix both of these leaks with priority for per-plot basis.

@jbeezley
Copy link
Contributor

FYIW, running this script

import gc
gc.enable()
gc.set_debug(gc.DEBUG_LEAK)

def scoped_import():
    import vcs

scoped_import()
del scoped_import

gc.collect()
print len(gc.garbage)

Results in 10632 leaked objects.

The aggregated types are as follows:

 2261: <type 'dict'>
 1962: <type 'list'>
 1645: <type 'set'>
 1389: <type 'tuple'>
 1072: <type 'weakref'>
  896: <type 'function'>
  792: <type 'instance'>
  486: <type 'getset_descriptor'>
  448: <class '_weakrefset.WeakSet'>
  448: <class 'DV3D.ConfigurationFunctions.SIGNAL'>
  242: <type 'type'>
  240: <type 'instancemethod'>
  192: <type 'vtkobject'>
    8: <class 'collections.OrderedDict'>
    3: <type 'StgDict'>
    2: <type '_ctypes.PyCSimpleType'>
    1: <type '_ctypes.PyCArrayType'>

@aashish24
Copy link
Contributor

Just trying to understand. When can we have dict or similar python data types getting leaked? (what scenarios etc)

@alliepiper
Copy link
Contributor Author

Circular dependencies are one case, e.g.

x = []
x.append(x)
del x

will leak. This is sort of rare, though, and indicative of a bad design. More likely, some other object is getting leaked that references a member dict/list.

@doutriaux1
Copy link
Contributor

just for convenience updated script leak_detector.py

import gc
gc.enable()
gc.set_debug(gc.DEBUG_LEAK)

import sys

def runTest():
  print "Testing leaks on:",sys.argv[1]
  execfile(sys.argv[1])

result = runTest()

gc.collect()

for i,g in enumerate(gc.garbage):
      print "Leak %d: %s @0x%x:\n   %s"%(i, type(g), id(g), str(g)[:70])

sys.exit(result)

usage:

leak_detector.py my_test_file.py

@doutriaux1
Copy link
Contributor

commenting out all the

impor dv3d

I get this while running the "import vcs" test

Testing leaks on: ../../basic.py
Leak 0: <type 'tuple'> @0x10930ca50:
   (<type '_ctypes.Array'>,)
Leak 1: <type 'StgDict'> @0x1093d41f8:
   {'__module__': 'numpy.ctypeslib', '__dict__': <attribute '__dict__' of
Leak 2: <type '_ctypes.PyCArrayType'> @0x7fb8704558d0:
   <class 'numpy.ctypeslib.c_int_Array_1'>
Leak 3: <type 'getset_descriptor'> @0x1093097a0:
   <attribute '__dict__' of 'c_int_Array_1' objects>
Leak 4: <type 'getset_descriptor'> @0x1093e0320:
   <attribute '__weakref__' of 'c_int_Array_1' objects>
Leak 5: <type 'tuple'> @0x1093c2208:
   (<class 'numpy.ctypeslib.c_int_Array_1'>, <type '_ctypes.Array'>, <typ
Leak 6: <type 'tuple'> @0x10b7051d0:
   (<class 'numpy.ctypeslib._ndptr'>,)
Leak 7: <type '_ctypes.PyCSimpleType'> @0x7fb8706bf8a0:
   <class 'numpy.ctypeslib.ndpointer_<i4'>
Leak 8: <type 'tuple'> @0x10b702390:
   (<class 'numpy.ctypeslib.ndpointer_<i4'>, <class 'numpy.ctypeslib._ndp
Leak 9: <type 'StgDict'> @0x10b703898:
   {'__module__': 'numpy.ctypeslib', '_shape_': None, '_ndim_': None, '_d
Leak 10: <type 'tuple'> @0x10b705210:
   (<class 'numpy.ctypeslib._ndptr'>,)
Leak 11: <type '_ctypes.PyCSimpleType'> @0x7fb8706bff50:
   <class 'numpy.ctypeslib.ndpointer_<i4'>
Leak 12: <type 'tuple'> @0x10b7023f8:
   (<class 'numpy.ctypeslib.ndpointer_<i4'>, <class 'numpy.ctypeslib._ndp
Leak 13: <type 'StgDict'> @0x10b703a40:
   {'__module__': 'numpy.ctypeslib', '_shape_': None, '_ndim_': None, '_d

@ThomasMaxwell I think it is yours to clean up sorry...

@doutriaux1
Copy link
Contributor

running:

import readline
import rlcompleter
readline.parse_and_bind("tab: complete")
import sys,os
import vtk
renWin = vtk.vtkRenderWindow()
ren = vtk.vtkRenderer()
renWin.AddRenderer(ren)
a = vtk.vtkActor()
m = vtk.vtkPolyDataMapper()

import cdms2
fnm = sys.prefix+'/sample_data/clt.nc'
f=cdms2.open(fnm)
s=f("clt")
import cdutil
cdutil.times.setTimeBoundsMonthly(s)
import genutil
fnm=sys.prefix+'/sample_data/clt.nc'
fnmirr=sys.prefix+'/sample_data/sampleGenGrid3.nc'
fnmcurv=sys.prefix+'/sample_data/sampleCurveGrid4.nc'
import numpy
import cdtime
import vcs
#from PyQt4 import QtCore, QtGui
x=vcs.init()
iso=x.createisofill()
T=x.createtemplate()

def Classes(obj,firsttime=True):
   if firsttime:
     obj=obj.__class__
   res=set()
   for c in obj.__bases__:
     res.add(c)
     res.update(Classes(c,False))
   return res

f=cdms2.open(fnm)
s=f('clt')
t=s.getTime()
tc=t.asComponentTime()

shows a lot of AutoAPI leaks. I think it was used way back then to generate vistrails xml strings. But I doubt it is still true. Will see if I can take off all that AutoAPI that anyway only makes the whole cdms2/vcs heavier than it should.

@doutriaux1
Copy link
Contributor

#1358

@alliepiper
Copy link
Contributor Author

@doutriaux1 Any ideas about the 14 remaining leaks without the dv3d imports?

Also, take a look at the animation tests. I know of at least one leak from there, resulting from this line:

https://github.com/UV-CDAT/uvcdat/blob/master/Packages/vcs/Lib/VTKAnimate.py#L45

atexit.register(self.close)

What this does is tell the interpreter to call self.close() when the interpreter exits, for every VTKAnimationCreate class created. This means that the bound method will be registered with the atexit handler, creating a reference to the method and the object, which will prevent the class from being cleaned up when it would otherwise be eligible for garbage collection.

The reason this code was added needs to be readdressed and a better solution put in place. Also, the rest of the vcs code should be checked to make sure this pattern isn't used anywhere else (just grep for atexit and make sure we aren't registering any bound methods or closures with strong references to it).

@aashish24
Copy link
Contributor

@doutriaux1 @dlonie this is great information and very helpful.. thanks for looking into it. Let's try to get it cleaned up 😄

@doutriaux1
Copy link
Contributor

@dlonie my guess is that they come from libcf (inside cdms2) that's the only thing that I know of that is using ctype (bad idea i think, since they use ctype to access netcdf and libcf whose sources we have, so we could have done a better job at wrapping it directly)

@doutriaux1
Copy link
Contributor

@dlonie the register at exit was the only way I could find at the time to force the function to be ran when the object is deleted. This function needs to be ran in order to clean the temporary pngs from ${HOME}/.uvcdat

@alliepiper
Copy link
Contributor Author

It'd be good to check if the leaks are coming from their library, or if we're holding on to references to them that vcs should be cleaning up.

The easiest way to check this would be to put some code that uses their library (and not vcs) in the leak-test program and see if there's any garbage left over. If not, then there's an issue with vcs leaking references.

@doutriaux1
Copy link
Contributor

@dlonie yes will do that. VCS has no ctype so it has to come from somewhere else, but the AutoAPI brings some leaks so I will clean that first, then try to see why cdms2 leaks (I don't think we are using any libcf file anyway)

@alliepiper
Copy link
Contributor Author

Trouble is, it doesn't really clean up the pngs when the object is deleted, it causes the object to never get deleted until the process exits.

What happens if a user creates many animations in a batch script? All of the temporary files from each animation would persist until the process exits, along with the memory being held by the animation classes that are bound to atexit.

This would usually be fixed by having something explicitly manage the png lifetimes and free them when they're no longer needed, rather than deferring the cleanup to the process's lifetime. One of the animation classes could do this, and then it's a matter of ensuring that the animation class is properly gc'd when it goes out of scope.

Sounds like a good plan for the ctype / AutoAPI leaks.

@doutriaux1
Copy link
Contributor

no I think if you call the "close" manually which you should, it will clear the objects.

@alliepiper
Copy link
Contributor Author

That works too, as long as users will do it ;) That's a fine solution, though, since if people start running into resource issues you can tell them to make sure they're calling close when they're finished 👍

@ThomasMaxwell
Copy link
Contributor

FYI: I have put together some slideshttps://www.dropbox.com/s/lg3k1ap1605rpsl/CDAS-Overview-1.pptx?dl=0 describing the work I have been doing lately developing climate data analysis services in support of NASA CDS and ESFG CWT. This work involves cdms/cdutil parallelization and the development of an analysis server implementation for the ESGF compute working team’s WPS API.

Aashish and I have been putting together a mailing list ([email protected]) to discuss climate data analysis services for large datasets. Please let Aashish know if you would like to be added to the list.

— Tom

@alliepiper
Copy link
Contributor Author

Did you mean to send that to the UVCDAT mailing list? This is a github issue discussing memory leaks.

@doutriaux1
Copy link
Contributor

interstingly enough removing the AutoAPI bit, triggered a lot of niceties (slots being respected for gms and Canvas for example).
Also I now get this:

ERROR: UVCDAT setup was previously sourced at: /lgm/uvcdat/2015-06-01
ERROR: There is no need to run setup_runtime manually anymore.
ERROR: Open a new shell in order to use a different install location.
/lgm/uvcdat/2015-06-01/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/vcs/VTKPlots.py:936: UserWarning: no RenderWindow ready, skipping setantialiasing call, please reissue at a later time
  warnings.warn("no RenderWindow ready, skipping setantialiasing call, please reissue at a later time")
/lgm/uvcdat/2015-06-01/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/vcs/Canvas.py:3540: UserWarning: Unrecognized vcs plot keyword: window_size, assuming backend (vtk) keyword
  warnings.warn('Unrecognized vcs plot keyword: %s, assuming backend (%s) keyword'%(keyarg,self.backend.type))
Baseline dir:  /Users/doutriaux1/build/uvcdat-testdata/baselines/dv3d
Processing vars ['uwnd'] from file /lgm/uvcdat/2015-06-01/Library/Frameworks/Python.framework/Versions/2.7/sample_data/geos5-sample.nc
initCamera: Camera => ((-59.5, 28.0, 161.26666666666665), (-59.5, 28.0, 0.0), (0.0, 1.0, 0.0)) 
Traceback (most recent call last):
  File "/git/uvcdat/testing/dv3d/dv3d_execute_test.py", line 7, in <module>
    testManager.runTest( test_name, interactive, baseline_dir )
  File "/git/uvcdat/testing/dv3d/TestManager.py", line 62, in runTest
    test.test( ast.literal_eval(interactive) )
  File "/git/uvcdat/testing/dv3d/TestManager.py", line 131, in test
    self.build()
  File "/git/uvcdat/testing/dv3d/TestManager.py", line 114, in build
    self.canvas.plot( *plot_args, **plot_kwargs )
  File "/lgm/uvcdat/2015-06-01/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/vcs/Canvas.py", line 2635, in plot
    a = self.__plot( arglist, keyargs )
  File "/lgm/uvcdat/2015-06-01/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/vcs/Canvas.py", line 3711, in __plot
    returned_kargs = self.backend.plot(*arglist,**keyargs)
  File "/lgm/uvcdat/2015-06-01/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/vcs/VTKPlots.py", line 467, in plot
    returned.update(self.plot3D(data1,data2,tpl,gm,ren,**kargs))
  File "/lgm/uvcdat/2015-06-01/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/vcs/VTKPlots.py", line 528, in plot3D
    g.gminit( data1, data2, roi=roi, axes=gm.axes, n_overview_points=n_overview_points, n_cores=gm.NumCores, renwin=ren.GetRenderWindow(), plot_attributes=gm.getPlotAttributes(), gmname=gm.g_name, cm=gm.cfgManager, **kargs  ) #, plot_type = PlotType.List  )
  File "/lgm/uvcdat/2015-06-01/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/DV3D/Application.py", line 66, in gminit
    self.plot.ParameterValueChanged.connect(self.canvas.processParameterChange)
  File "/lgm/uvcdat/2015-06-01/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/DV3D/ConfigurationFunctions.py", line 194, in connect
    self._methods[slot.__self__] = set()
  File "/lgm/uvcdat/2015-06-01/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/weakref.py", line 321, in __setitem__
    self.data[ref(key, self._remove)] = value
TypeError: cannot create weak reference to 'Canvas' object

Does that help @ThomasMaxwell

@jbeezley
Copy link
Contributor

jbeezley commented Jun 4, 2015

http://docs.python.org/2/reference/datamodel.html#slots

Without a __weakref__ variable for each instance, classes defining __slots__ do not support weak references to its instances. If weak reference support is needed, then add '__weakref__' to the sequence of strings in the __slots__ declaration.

That is very obscure.

@doutriaux1
Copy link
Contributor

@dlonie @aashish24 I tracked the leaks I got to
vcs.mklabels and then down to numpy.ma.masked_equal

import numpy
import numpy.ma
a = numpy.ma.array([1,2,34,5,7.])
b = numpy.ma.masked_equal(a,0.)

Leads to:

Testing leaks on: test_ma.py
gc: collectable <tuple 0x7f604589f910>
gc: collectable <StgDict 0x7f6045abdbe8>
gc: collectable <_ctypes.PyCArrayType 0x2115520>
gc: collectable <getset_descriptor 0x7f60458a8fc8>
gc: collectable <getset_descriptor 0x7f60455b1fc8>
gc: collectable <tuple 0x7f604589af18>
gc: collectable <cell 0x7f604bf89670>
gc: collectable <tuple 0x7f604bf8a1d0>
gc: collectable <function 0x7f6045125230>
Leak 0: <type 'tuple'> @0x7f604589f910:
   (<type '_ctypes.Array'>,)
Leak 1: <type 'StgDict'> @0x7f6045abdbe8:
   {'__module__': 'numpy.ctypeslib', '__dict__': <attribute '__dict__' of
Leak 2: <type '_ctypes.PyCArrayType'> @0x2115520:
   <class 'numpy.ctypeslib.c_int_Array_1'>
Leak 3: <type 'getset_descriptor'> @0x7f60458a8fc8:
   <attribute '__dict__' of 'c_int_Array_1' objects>
Leak 4: <type 'getset_descriptor'> @0x7f60455b1fc8:
   <attribute '__weakref__' of 'c_int_Array_1' objects>
Leak 5: <type 'tuple'> @0x7f604589af18:
   (<class 'numpy.ctypeslib.c_int_Array_1'>, <type '_ctypes.Array'>, <typ
Leak 6: <type 'cell'> @0x7f604bf89670:
   <cell at 0x7f604bf89670: function object at 0x7f6045125230>
Leak 7: <type 'tuple'> @0x7f604bf8a1d0:
   (<cell at 0x7f604bf89670: function object at 0x7f6045125230>,)
Leak 8: <type 'function'> @0x7f6045125230:
   <function _recursive_mask_or at 0x7f6045125230>

While disconcerting I don't see any way to avoid this leak. Maybe the upgrade to a newer python will help.
Now I fail to see how this affects @dlonie in his VTK.

@dlonie can you try to bring this branch (with drawColorbar commented out) in your branch and see if it helps?
Thanks.

@doutriaux1
Copy link
Contributor

oops branch is: issue_1343_leaks

@doutriaux1
Copy link
Contributor

numpy leak reported at: numpy/numpy#6010

@alliepiper
Copy link
Contributor Author

Good catch on the numpy arrays! That would explain a lot of the leaks (although I'm curious why so many of these arrays would be created/leaked from just importing vcs).

I tested the new changes and it still segfault on my branch when I run vcs_test_animate_meshfill. See the issue_1343_test branch, which has the leak changes and the meshfill pipeline changes, rebased and merged.

@aashish24
Copy link
Contributor

@dlonie would it be because vcs imports numpy at the top?

@aashish24
Copy link
Contributor

I am wondering if we use numpy + pure VTK combo, then we should see similar issues (seg fault). @dlonie can you create an example as such?

@alliepiper
Copy link
Contributor Author

@aashish24 VTK uses numpy internally without issue, so that's not it. Numpy and VTK have been used together countless times in numerous projects -- it's safe to say that most projects using VTK's python bindings also use numpy.

@alliepiper
Copy link
Contributor Author

@aashish24 import numpy results in 6 leaks, not 10k. It's contributing, but not the only problem.

@aashish24
Copy link
Contributor

I see. When VTK segfaults, is there a way to know what objects its trying to release?

@alliepiper
Copy link
Contributor Author

Yep, gdb. It's segfaulting in vtkPythonAlgorithm's destructor when it calls Py_XDECREF after the interpreter has shut down.

@jbeezley
Copy link
Contributor

I think you should focus on the VTK objects that are leaked. Those are almost certainly the cause of the seg fault. As mentioned in the issue you posted, leaking a small number of static objects at the module level is going to be pretty common. It is highly unlikely these are preventing the VTK objects from being freed because as @dlonie mentioned VTK uses numpy underneath already.

My advice is that you should look for is anywhere a vtk object is allocated and stored statically, either inside a module or a static class attribute. Another possibility is that it exists in the closure of a function being passed to a global event handler such as atexit. A quick google search reveals a number of python packages and blog posts that can help find the source of these kinds of memory leaks. I.e.

https://mg.pov.lt/blog/hunting-python-memleaks.html
http://teethgrinder.co.uk/perm.php?a=Python-memory-leak-detector
http://engineering.hearsaysocial.com/2013/06/16/circular-references-in-python/

I don't have any personal experience with this, so I can't really offer any further advice.

@alliepiper
Copy link
Contributor Author

To add to @jbeezley's input, I've mentioned a couple of times that the likely culprit is the dictionary returned from VTKPlots.plot(...). That's the most obvious place I've seen where these objects can leak, and I've already patched one leak related to this dictionary here: 8b778e5

After that patch (Which I wouldn't submit for inclusion in master, btw -- it's a hack. The atexit pattern is a bad idea, though I've tried to minimize the ill-effects), the only time I'm seeing segfaults is in the animation test, vcs_test_animate_meshfill (note that there may still be other undiscovered issues, but I stopped the refactor after adapting meshfill when I saw the crashes).

@doutriaux1
Copy link
Contributor

@dlonie the 10k are done to 105 when you take out DV3D so the VTKPlot objects are not the culprit for this, the 105 leaks left after a vcs.plot are all the ones from the numpy leak. In the branch I sent you DV3D is gone. Also it was my understanding that the vtk_object thing was just a "hack" until we reimplement the pieline object and return these instead. So we should really work hard on taking these out. Also you try to not return them they are only used by the "update" function when animating, so for now try to not return them and see if it fixes the issue. Again these have been (poorly we knew it back then and agreed to go with it until this re-implementation is done) implemented for the sake of animation only.

@aashish24
Copy link
Contributor

I agree with @doutriaux1. We should remove those hacks! Let me know if I can be of any help.

@alliepiper
Copy link
Contributor Author

@doutriaux1 Have you tried running a more complex example (e.g. the meshfill animation test)? The original 10k leaks were just from importing the module, it would be good to ensure there aren't more leaks generated by a less-trivial example.

If all of the leaks have been tracked down to numpy or DV3D then I'll take another pass at the refactor sometime soon, but make sure that more realistic usecases have been tested and checked for vcs leaks, because something was leaking that filter when the animation was run.

@doutriaux1
Copy link
Contributor

@dlonie isn't the def of a leak is that something that should be released isn't released? If soI fail to see how it affects you. You seem to be releasing memory that has already been released and used for something else. No?

@alliepiper
Copy link
Contributor Author

The memory has not been released and used for something else. The issue is:

  1. We create a VTK filter in VCS and make a plot.
  2. Reference leaks cause the objects to persist after the python interpreter shuts down.
  3. After the interpreter is gone, but before the process exits, the leaked objects are destroyed at the C++ level.
  4. The leaked objects use the Python/C API to clean up, and since the interpreter is gone, this causes a crash while attempting to access the thread state of the dead interpreter.

@alliepiper
Copy link
Contributor Author

BTW, I suggested using objgraph to investigate the leaks a few times. Did you have a look at it?

There are lot of very noticable problems regarding circular references and atexit bound methods:

objgraph-0

objgraph-1

It also looks like objects are getting stuck in the vcs.elements arrays.

Generated with

import gc
gc.enable()

def runTest():
    import vcs
    import cdms2
    import os
    import sys
    import time
    pth = os.path.join(os.path.dirname(__file__),"..")
    sys.path.append(pth)
    import checkimage

    f=cdms2.open(os.path.join(vcs.sample_data,"clt.nc"))
    s=f("clt",slice(0,1)) # read only 12 times steps to speed up things

    x=vcs.init()
    x.drawlogooff()
    x.setbgoutputdimensions(1200,1091,units="pixels")

    gm=x.createboxfill()
    x.plot(s,gm,bg=1)
    x.animate.create()
    print "Saving now"
    prefix= os.path.split(__file__)[1][:-3]
    x.animate.save("%s.mp4"%prefix)
    pngs = x.animate.close(preserve_pngs = True) # so we can look at them again
    src_pth = sys.argv[1]
    pth = os.path.join(src_pth,prefix)
    ret = 0
    for p in pngs:
      print "Checking:",p
      ret += checkimage.check_result_image(p,os.path.join(pth,os.path.split(p)[1]),checkimage.defaultThreshold)
    if ret == 0:
        os.removedirs(os.path.split(p)[0])
        os.remove("%s.mp4" % prefix)

    x.close()
    return ret


ret = runTest()
del runTest

gc.collect()

import objgraph
import random
import sys
import inspect

objgraph.show_most_common_types(5000)

objType = "BoxfillPipeline"
objCount = len(objgraph.by_type(objType))
print "Generating %d graphs for '%s'"%(objCount, objType)
for i in range(objCount):
    obj = objgraph.by_type(objType)[i]
    print "Object:",str(obj)
    print "RefCount:",sys.getrefcount(obj)
    objgraph.show_backrefs(obj, max_depth=100, refcounts=True,
                           filename='/tmp/debug/objgraph-%d.png'%i)

print "ObjGraphs written."

sys.exit(ret)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants