TTree memory overhead

I am using multiple memory-resident trees in an application. They typically have a few branches of simple types, like int and float.

I have noticed that I can can fill and e.g. call GetEntry on a tree and it maintains a very small memory profile. But as soon as I draw from the tree substantial memory cost is incurred (~50 MB even for a tree with only a few hundred bytes of data.)

Is there a way to return a tree to its state before a Draw was performed, so I can release the associated memory?

Thank you,
Brian

ROOT is optimized to use the strict minimum memory when generating (typically in batch mode) histograms and Trees.
When drawing histograms and trees many more shared libs are dynamically linked when calling for example tree.Draw. Just to give an idea I have looked on my system,
the program creating a memory resident Tree and filling it takes 28 MBytes of virtual memory. When adding tree.Draw the virtual memory increases to 67 MBytes. The difference is in the following libs

libHist: 3400 Kb libMatrix : 2000 LibGui : 6000 libGraf: 1700 libGraf3d: 900 libGpad: 750 libX11: 2000 libHistPainter: 600 libTreePlayer: 1600 libASImage: 600

  • around 18 MBytes of dynamic allocations by the system for global symbols and dictionaries. Of course, once these libs are loaded the memory remains constant.

Rene

I am seeing the overhead for each tree that a Draw() is applied to.

At the bottom is a little script that illustrates it. When I run it I see the following output:
root [2] TestTree1()
Start: Res Mem=38244 Virt Mem=31172
Creating and Filling 30 trees
Filled: Res Mem=38416 Virt Mem=31312
Drawn: Res Mem=43504 Virt Mem=740784

So it is more like 25 MB per tree than 50, but still for each tree.
Thank you.
Brian

[code]//=======================================
#include “TSystem.h”
#include “TTree.h”
#include “TRandom.h”

TTree **t = 0;
int nt = 30;
ProcInfo_t pi;
void TestTree1();
void FillTree();
void DrawTree();
void TestTree1()
{
gSystem->GetProcInfo(&pi);
printf(“Start: Res Mem=%d Virt Mem=%d\n”,pi.fMemResident, pi.fMemVirtual);

FillTree();
DrawTree();
}
void FillTree()
{
int ne = 10;
int pad = 32;
float x1,x2,x3;
t = new TTree*[nt];
char tName[16];
TRandom r;
printf(“Creating and Filling %d trees\n”,nt);
for(int i=0;i<nt;++i)
{
int branchSize = (pad+ne)sizeof(Float_t);
sprintf(tName,“t%d”,i);
t[i] = new TTree(tName, “Events”);
t[i]->SetDirectory(0);
t[i]->Branch(“x1”,&x1,“x1/F”,branchSize);
t[i]->Branch(“x2”,&x2,“x2/F”,branchSize);
t[i]->Branch(“x3”,&x3,“x3/F”,branchSize);
t[i]->SetBranchStatus("
",1);

  for(int ie=0;ie<ne;++ie)
  {
     x1 = r.Rndm();
     x2 = r.Rndm();
     x3 = r.Rndm();
     t[i]->Fill();
  }

}
gSystem->GetProcInfo(&pi);
printf(“Filled: Res Mem=%d Virt Mem=%d\n”,pi.fMemResident, pi.fMemVirtual);
}
void DrawTree()
{
for(int i=0;i<nt;++i)
{
t[i]->Draw(“x1:x2”,"",“goff”);
}
gSystem->GetProcInfo(&pi);
printf(“Drawn: Res Mem=%d Virt Mem=%d\n”, pi.fMemResident, pi.fMemVirtual);
}
//=======================================[/code]

problem understood. The first time Ttree::Draw is called for a Tree, it makes a reservation of fEstimate values for each dimension to be drawn. fEstimate is set to the number of entries in the Tree if it is >1000 or 1000000 otherwise.
You can force teh fEstimate parameter as shown in your modified function DrawTree below.

void DrawTree() { for(int i=0;i<10;++i) { Long64_t nentries = t[i]->GetEntries(); t[i]->SetEstimate(nentries); t[i]->Draw("x1:x2","","goff"); } gSystem->GetProcInfo(&pi); printf("Drawn: Res Mem=%d Virt Mem=%d\n", pi.fMemResident, pi.fMemVirtual); }

Rene

That works. Thank you for your help!

Brian