Memory problem

Hi,

I am writing a program which reads a ROOT file, which contains several directories, with O(10000) histograms each. These histograms are then fitted, and saved to another ROOT file, including the fits.

The problem is that the memory of the job seems to streadily grow. At first, I had a single TFIle::Write() call at the very end, thinking that ROOT would automatically optimize the management of the memory. But even adding a TFile::Write() call after the histograms in each directory are fitted didn’t change the behavior … what am I doing wrong?

Thanks a lot,
Philipp

Hi Philipp,

TFile::Write only does the writing in the physical file of the objects belonging to the TFile (I.e. directories, trees, histograms and other object attached using Append). In particular it does not delete the object. The deletion is done by the method Close.

However, it is safe for your to delete the histograms right after the call to Write.

Cheers,
Philippe.

Hi Philippe,

thanks! I was trying to go down that road, but it seems I haven’t quite gotten it right yet …

I loop over the directories in my input files, variable idir; I then create a directory of the same name in the output file, variable odir. I replaced the ofile->Write() calls after each output directorz is complete with odir-Write(); I then added

odir->DeleteAll();
delete odir;
idir->DeleteAll();
delete idir;

all in an attempt to delete all histogrmas currently held in memory. but the memory keeps rising, to about 600MB after the first dir, and about 1.2GB after the second.

What is the correct way to achieve this?

Thanks,
Philipp

Hi Philipp,

This should have gotten rid of the Histogram objects. So I am guessing that the leak comes from somewhere else. So the next step is to really establish which objects are being accumulated.

To be able to track the allocation of TObjects, you should modify your .rootrc file - used by ROOT to setup the ROOT environment. Specifically, you want to make sure that two items are set to 1 (one):
Root.MemStat and Root.ObjectStat

Activate memory statistics (size and cnt is used to trap allocation of

blocks of a certain size after cnt times)

Root.MemStat: 1
Root.MemStat.size: -1
Root.MemStat.cnt: -1
Root.ObjectStat: 1

Then while in your ROOT interactive session, type:
gObjectTable->Print( )
This will display the contents of the memory table.

Cheers,
Philippe.

Hi Philippe,

thanks, that sounds like a good thing to do! I don’t use the interpreter however, but a compiled program. Can I activate these memory statistics from within that as well?

Cheers,
Philipp

yes

Rene

Hi,

I finally got around to look at the obj statistics, here is the result:

Object statistics
class                         cnt    on heap     size    total size    heap size
================================================================================
TRootGuiFactory                 1          1       28            28           28
TVirtualX                       1          1       84            84           84
TTimer                          1          0       64            64            0
TGlobal                       993        993       32         31776        31776
TBenchmark                      1          1       52            52           52
TFitter                         1          1      168           168          168
TList                        2250       2249       44         99000        98956
TGFontPool                      1          1       32            32           32
TImagePalette                   2          2       36            72           72
TObjectTable                    1          1       24            24           24
TROOT                           1          0      296           296            0
TStreamerBase                  21         21      128          2688         2688
TClassMenuItem                 86         86       60          5160         5160
TPluginManager                  1          1       24            24           24
TFileHandler                    2          2       40            80           80
TObject                       125        125       12          1500         1500
TStreamerInfo                  25         25       96          2400         2400
TFile                           2          2      412           824          824
THashTable                     21         21       40           840          840
TClassTable                     1          1       12            12           12
TStreamerString                 8          8      120           960          960
TGFrame                         1          1      112           112          112
TGResourcePool                  1          1      200           200          200
TGFont                          4          4     1388          5552         5552
TRandom3                        1          1     2532          2532         2532
THashList                      11         11       48           528          528
TUrl                            2          2       96           192          192
TGuiFactory                     1          1       28            28           28
TPosixThreadFactory             1          0       28            28            0
TProcessID                      1          1       36            36           36
TObjString                    982        982       20         19640        19640
TFormulaPrimitive             164        164      104         17056        17056
TEnv                            2          2       28            56           56
TGX11TTF                        1          1      276           276          276
TStreamerObject                 3          3      120           360          360
TEnvRec                      1982       1982       44         87208        87208
TClass                         76         76      196         14896        14896
TRealData                     430        430       36         15480        15480
TQClass                         8          8      212          1696         1696
TFolder                        19         19       36           684          684
TGGCPool                        1          1       24            24           24
TRint                           1          1      164           164          164
TDataMember                   258        258       88         22704        22704
TNamed                         11         11       28           308          308
TMap                            1          0       28            28            0
TMessageHandler                 1          1       72            72           72
TFree                           1          1       28            28           28
TCint                           1          1      256           256          256
TPair                         884        884       20         17680        17680
TObjArray                   17880      17880       40        715200       715200
TStreamerBasicType             55         55      124          6820         6820
TUnixSystem                     1          1      268           268          268
TGMimeTypes                     1          1       32            32           32
TOrdCollection                  8          8       44           352          352
TSignalHandler                  1          1       40            40           40
TBits                        8881       8881       24        213144       213144
TStreamerBasicPointer           2          2      144           288          288
TMethod                       853        853       76         64828        64828
TGGC                           12         12      128          1536         1536
TMinuit                         1          1     2496          2496         2496
TExMap                          1          1       24            24           24
TStreamerObjectAny              3          3      120           360          360
TColor                        344        344       60         20640        20640
TGPicturePool                   1          1       28            28           28
TDataType                     492        492       52         25584        25584
TMethodArg                      3          3       40           120          120
TStyle                          6          6      812          4872         4872
TPluginHandler                 20         20       76          1520         1520
TStreamerObjectPointer          2          2      120           240          240
TKey                            7          7       96           672          672
TSystemDirectory                1          1       44            44           44
TGClient                        1          1      108           108          108
TF1                          8880       8880      356       3161280      3161280
TBaseClass                     50         50       40          2000         2000
TMethodCall                    17         17       60          1020         1020
TProcessUUID                    1          1       44            44           44
--------------------------------------------------------------------------------
Total:                      45918      45913    13548       4577468      4577008
================================================================================

So it looks as if the fit functions are still around, even though they were stored with the histograms, which are in the directories which are destroyed? How can I get rid of them?

Thanks,
Philipp

Hi Philipp,

How do you create the Fitting function?
You may have to go through gROOT->GetListOfFunctions to remove the function you no longer need.

Cheers,
Philippe.

Hi Philippe,

I recreate the fitfnc in a loop for an iterative fitting procedure, the relevant lines I think are:

TF1* fitfnc(0);
for (int iiter=0;iiter<niter;iiter++) {
    fitfnc = new TF1("fit","gaus",fitrange_min,fitrange_max);
    hrsp->GetListOfFunctions()->Delete(); // seems to leave old fnc in mem?
    hrsp->Fit(fitfnc,"RQ0");                                              
}

I observe that if I set niter from 3 to 1, the object table shows only a third of the TF1 objects, so the Delete() call doesn’t seem to delete the old fit functions from memory.

But even with just one iteration, the function remain in memory, despite my

output_dir->Write();
output_dir->DeleteAll();
delete output_dir;

before printing the object table.

Cheers,
Philipp

Do:

TF1* fitfnc(0); for (int iiter=0;iiter<niter;iiter++) { fitfnc = new TF1("fit","gaus",fitrange_min,fitrange_max); hrsp->Fit(fitfnc,"RQ0"); delete }

Rene

Hi Rene,

thanks, the following takes care of all function but the one actually remaining in the histogram:

TF1* fitfnc(0);
for (int iiter=0;iiter<niter;iiter++) {
  fitfnc = new TF1("fit","gaus",fitrange_min,fitrange_max);
  hrsp->Fit(fitfnc,"RQ0");
  delete fitfnc;
}

The number of TF1 histograms however was still non-zero, until I added

hrsp->Write();
TF1* f = hrsp->GetFunction("fit"); if (0!=f) delete f;

Is that to be expected? Well it appears to solve my problem at least, as all the fits now made it savely into my file, why the memory stays constant if I apply this to many directories in the same job:) Thank you all for your help!

Cheers,
Philipp