Gepetto / gepetto-viewer

Graphical Interface for Pinocchio and HPP.
BSD 2-Clause "Simplified" License
40 stars 30 forks source link

Memory leak when destroying visual objects #213

Open nmansard opened 1 year ago

nmansard commented 1 year ago

I post this issue for future reference. The title sounds bad but I actually don't think it is so important as it does not correspond to a typical usage of Gepetto-Viewer.

When iteratively deleting nodes then re-creating them, we observed that the memory usage of Gepetto-viewer keep growing.

Gepetto-viewer is typically used in situations where we want to avoid re-loading the visual objects, so this situation is unlikely to happen. A minimal answer is to take care of raising the user awareness when writing an application where nodes are systematically deleted. A second level of answer could be to add automatic warning in Gepetto-viewer itself, when observing unusual node deletion (say after 1000 deletions, emit a warning to the console). Of course, ideally, this bug should be fixed.

Note that it was only tested with XYZaxis features, maybe simpler visual objects are not causing it.

with more details ...

The bug can be observed with the following code:

import time
import os
import gepetto
import sys

# Open the connection to gepetto viewer
try:
    viewer=gepetto.corbaserver.Client()
    gv = viewer.gui
except:
    print("Error while starting the viewer client. ")
    print("Check whether Gepetto-viewer is properly started")
    sys.exit(-1)

# Open a window for displaying your model.
try:
    # If the window already exists, do not do anything.
    windowName = 'pinocchio'
    windowID = gv.getWindowID (windowName)
    print("Warning: window '"+windowName+"' already created.")
    print("The previously created objects will not be destroyed and do not have to be created again.")
except:
    # Otherwise, create the empty window.
    windowID = gv.createWindow (windowName)
    # Start a new "scene" in this window, named "world", with just a floor.
    gv.createScene("world")
    gv.addSceneToWindow("world",windowID)

for trial in range(100):
    print(f'Run {trial} !' )
    for i in range(100):
        name = f'world/xyz{i}'
        gv.deleteNode(name,True)
        gv.addXYZaxis(name,[1.,1,1.,1.],.01,.2)
        gv.applyConfiguration(name,[i*.01,0,i**2*.001,0,0,0,1])
    gv.refresh()
    os.system('free -h')

    duration = 1
    print(f'Now sleeping for {duration}' )
    time.sleep(duration)

(you need to start gepetto-gui corba server first).

The memory raise is displayed on the following plot: image (this plot can be reproduced with pmap using https://gitlab.laas.fr/-/snippets/17 and lanching pmapnitor.py gepetto-gui then the script above.

florent-lamiraux commented 1 year ago

I have been able to reproduce the issue. However, when counting the number of nodes allocated by increasing a counter in each constructor and decreasing it in the destructor, the total number of objects at the end of the test is 105. The problems does not come from nodes not being destroyed.

Any idea ?

nim65s commented 1 year ago

Destruction might not be destructive enough. Valgrind could help track this.