Proper way of using TTree::AutoSave? (memory leak)

Hi,

I believe I am not using properly the AutoSave feature of TTree. What I am trying to do is avoid accessing the disk very often. What I end up with is a memory leak (or what appears as a memory leak). Could somebody comment if the following piece of code has a memory leak?

Thanks.

–Christos

PS. which root
/afs/cern.ch/cms/external/lcg/external/root/4.03.04a/slc3_ia32_gcc323/root/bin/root

// root stuff
#include <TROOT.h>
#include <TChain.h>
#include <TFile.h>
#include <TLeaf.h>
#include <TBranch.h>
#include <TRandom.h>

// maximum # of tracks in event
const int N_MAX = 50;

/// class containing output root-tuple structure
class Event : public TObject {
public: 
  /// number of tracks
  Int_t N;
  /// event #
  Int_t evt_no;
  // px, py
  Float_t * px; // [N]
  Float_t * py; // [N]
  
  // constructor
  Event(void){
    px = new Float_t[N_MAX];
    py = new Float_t[N_MAX];
  }
  
  // destructor
  ~Event(void){
    delete [] px; delete [] py;
  }

  ClassDef(Event, 1)
};

int variableLengthArray(void)
{
  
  TFile * output_file = new TFile("temp.root", "recreate");
  TTree * root_tree = new TTree("tree", "root-tuple description");
  root_tree->SetDirectory(output_file);
  
  Event * evt = new Event();
  TBranch * branch = root_tree->Branch("myTuple", "Event", &evt, 8000, 2);

  for(int i = 0; i != 1000000; ++i)
    { // loop over events

      // get # of tracks for event
      evt->N = int(gRandom->Gaus(10, 2) ); // gauss with mean = 10, sigma = 2

      // do not go beyond maximum length!
      if(evt->N > N_MAX)evt->N = N_MAX;

      evt->evt_no = i;

      for(int j = 0; j < evt->N; ++j)
	{ // loop over tracks in event
	  
	  evt->px[j] = gRandom->Gaus(0, 5); // gauss with mean = 0, sigma = 5
	  evt->py[j] = gRandom->Gaus(3, 2); // gauss with mean = 3, sigma = 2
	  
	} // loop over tracks in event

      root_tree->Fill();
      if(i % 50000 == 0)
	{
	  cout << " Autosaving root tree for vent #: " << i << endl;
	  root_tree->AutoSave();
	}
    } // loop over events
  
  root_tree->Write();
  output_file->Close();

  return 0;

}

Hi,

You probably just need to add: delete output_file; delete evt;With those I do not see any memory increase if I repeatedly run the variableLengthArray function.

Also you may want to initialize N in your Event default constructor.

Cheers,
Philippe.

Hi Philippe.

I don’t think I made myself clear. I’m talking about the fact the program’s memory keeps increasing while the program is running, ie. not that there is uncleaned memory after the program is finished.

I think I would like to save the root-tree (via AutoSave or Write; I’m not sure) periodically, then flush/reset(?) its contents from the memory. The next time I want to call AutoSave, I should just append the new data. I assume that my root_tree is the reason that the memory gets bigger & bigger. I use “Fill()” but never “Reset” (or “something like Reset”).

Hope this is more clear…

[quote]I think I would like to save the root-tree (via AutoSave or Write; I’m not sure) periodically, then flush/reset(?) its contents from the memory.[/quote]Technically for that to work properly you need to

  • write the tree or write the file
  • detach the tree for the file
  • close the file
  • reset the tree
  • open new file
  • attach the tree to the new file
  • go on

There are some information that the TTree has to keep in memory. For example you are using small baskets 8K while the TTree need to keep in memory the location of each of those on file. Increasing the size of the basket would reduce the rate of increase of this “list” of value.

Cheers,
Philippe.

Ok, so I think that this is what I need to do.

The thing is that my program is an on-line monitoring utility that needs to periodically save some data, but it is supposed to run for many days at a time.

However, it is not clear from what you are saying if the (new) tree will append its data to the file. Is this possible?

Let me see if I can say this with some pseudo-code

if(i % 50000 == 0) 
{
TFile * file = new TFile("temp.root"); // open old file if already exists
root_tree->Append() ; // ie. do not overwrite();
root_tree->Reset(); // size in memory for root_tree is  now 0
file->Close();
}

Thanks.

–Christos

[quote]However, it is not clear from what you are saying if the (new) tree will append its data to the file.[/quote]No, you should use a new file and later use them in a chain (and/or merge them).

[quote]Is this possible? [/quote]Yes but it would defeat the purpose.

It does more than that, it remove all data from the tree.
Philippe.