Memory resident trees

Hi All,

I have written a class that has a TFile and a TTree, which is filled by member functions. I initialise the objects as follows:

file = TFile::Open(“FileName.root”,“CREATE”);
tree = new TTree(“TreeName”,“Tree Title”);

The memory used by the program increases gradually until it eventually reaches the computers limit. To avoid this I have tried the following:

After I declared the tree I included the line
tree->SetDirectory(file);
In hope of linking the tree with the file. Each time I filled an the tree I called
file->Flush();
I hoped that this would flush the tree information in memory to the file and clear the RAM. This does not seem to work.

Is there any way that this can be done? Can the tree be written in stages to the file?

Cheers,

Ben

Hi Ben,

when creating a TTree after having opened the file the TTree will write into that file (the SetDirectory() is automatic). So what you do is ok. I expect however that you just have some memory leak during filling of the tree. Do you delete the object you created for each TTree::Fill()?

Cheers, Fons.

Hi Fons,

Here is the structure of the code I have written:

class MyClass {

public:

Tfile* file;

private:
TTree* tree;
int SimpleInteger;
int* ArrayInteger;
TLorentzVector* ALorentzVector;
TClonesArray* LorentzVectorArray;

void Initialize() {
file = TFile::Open(“FileName.root”,“CREATE”);
tree = new TTree(“treename”,“Tree Title”);
tree->SetDirectory(file);
CreateBranches();
}

void CreateBranches() {
SimpleInteger = 10; //Will give the size of the arrays
tree->Branch(“SimpleInteger”, &SimpleInteger, “SimpleInteger/I”,32000);
ArrayInteger = new int[SimpleInteger];
tree->Branch(“ArrayInteger”, ArrayInteger, “ArrayInteger[SimpleInteger]/I”, 32000);
ALorentzVector = new TLorentzVector(-1000,-1000,-1000,-1000);
tree->Branch(“ALorentzVector”, “TLorentzVector”, &ALorentzVector, 32000, 99);
LorentzVectorArray = new TClonesArray(“TLorentzVector”, SimpleInteger);
tree->Branch(“LorentzVectorArray”, “TClonesArray”, &LorentzVectorArray, 32000, 99);
}

void AddEvent(Event EventObject) {
// The Class Event has many member functions which yield integers, doubles, TVector3
// and TLorentzVector’s. So the branch variables are equated to a new number/object
// each time. Simple integer is not changed.

ALorentzVector = InitialParticleMomentum; //Filled once per event

//loop over trajectories in the event, many per event
for(int i=0; …) {
ArrayInteger[i] = trajectoryID;
new((*LorentzVectorArray)[i]) TLorentzVector(trajectoryMomentum);
}

tree->Fill(); //Fill the tree every event
}

void finalise() {
file->cd();
tree->Write();
}

};

The initialize is invoked once and the AddEvent is invoked every event and the finalise is invoked at the end of looping over events.

I have tried using valgrind to find the memory leak and it seems to be in the AddEvent function some where. I have many TClonesArray’s and other objects that I fill each event. The program steadily increase the memory it uses by about 2Mb every ~5mins

Thanks for your help,

Ben

Hi,

In the subset of code you provided there does not seem to be any obvious memory leaks. However:void AddEvent(Event EventObject) is a red-herring. You are passing the Event by value which means that it is copied (and deleted) each time you call AddEvent (and then you copy it again in your auxiliary data members.

The leaks is most likely in the Copy Constructor of EventObject (and/or its destructor).

Also I strongly recommend that instead of those copies and extra data member, you simply make EventObject persistent and directly use it in a (single) top branch.

Cheers,
Philippe.