Hello,
I am having a problem with the memory consumption of one of my python scripts. Basically, running something like this:
f = ROOT.TFile("myfile.root")
for i in range(100):
sums = f.Get("Sums")
fills up my RAM in no time even though “sums” should be out of scope at the end of the loop. Sums is a TList holding a few TNtuple and histograms. Also, closing the file does not release the memory. How can I avoid this leak?
calling sums->Delete() or delete Sums, does not make a difference. The memory occupied in the loop is not freed at the end of the execution. Is there a different way in root if I want to read “Sums” many times in my script?
I would expect that with both the sums->Delete(); and the delete sums, all the memory would be freed.
[quote]Also, closing the file does not release the memory.[/quote]A TList is not managed by the TFile and once returned by Get, it is the responsibility of the calling code to delete the list.
In addition, TList are not ‘owner’ of their content by default and thus the content is not deleted when the list is deleted. You either need to call sums->Delete() or sums->SetOwner(true) to insure that after ‘delete sums’ all the memory is released.
I am not sure what the problem is, it has to be related to the content of the list.
You could run a memory profiler (valgrind’s massif or igprof or something else) to pin point the issue.
Alternatively you could send us the data file so we can take a look it.
So the outer call to Delete does delete the list themselves but does not delete the contains of the sub-list.
In order to properly delete this structure (I suspect the producing code contains equivalent code (or at least it should):TIter next(sums);
TObject *obj = nullptr;
while( obj = next() ) {
TList *list = dynamic_cast<TList*>(obj);
if (list) list->Delete(); // alternatively list->SetOwner(true);
}
sums->Delete(); // alternatively list->SetOwner(true);
delete sums;
Cheers,
Philippe.
PS. Alternatively the list could be made owner of their content in the writing program.