from Sue Kasahara: TTree::Autosave mechanism for online dispatcher

Link

I've done some testing of the TTree::Autosave mechanism to determine
its applicability to our situation where we wish to read event
information from a file which is still being written to. 
  I attach the test routines I am using.  The first is used to fill
the tree with event information for 300 events. It autosaves the tree after 
each event.  The second routine is used to read the tree from the open
file generated by the first routine.  The "events" that I'm using 
are from the Event class defined in one of the $ROOTSYS/test examples 
provided with the root distribution.  Each of these "events" fills the 
tree with on average 45000 bytes/event of data.    
  The autosave mechanism seems to work as advertised in that it
is possible to read the open file written by the first routine with
the second routine.  It also performs as Nick predicted by writing
a new tree each time to the file with a new version number.  I have
added a 
gDirectory -> Purge();
beneath the AutoSave command to get rid of older tree's so that the
output file doesn't become to large.
  Each AutoSave is expensive in terms of CPU.  In a test with and without
the AutoSave mechanism: 
Number of events = 300     
                w/AutoSave    w/o Autosave
CPU             121.35 sec      3.68 sec          Times are for 300 events
Realtime        166.55 sec      5.91 sec
File size      11,670 kbytes  10,940 kbytes 

Some of this is dependent on the basketsize set when defining the tree
branches, since the baskets are dumped to disk when they exceed the 
predefined basketsize (64 kbytes in this example), and AutoSave won't 
rewrite this information to file. 
  So my conclusions (so far) are:
1)Autosave works
2)We won't lose much in disk space if we purge old trees
3)We will lose something in processing time.
There may be other ways to approach this problem, I am still on a learning
curve and have been debugging through the code to understand the root
file structure better.      

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "Event.h"      //Event class from $ROOTSYS/test

//////////////////////////////////////////////////////////////////////////////
//                                                                          //
// Program to test root i/o capabilities                                    //
// Based on MainEvent.cxx example from $ROOTSYS/test                        //
//                                                                          //
// User can supply up to 4 arguments:                                       //
// argv[1]=number of events to generate (default=400)                       //
// argv[2]=compression level (default=1)                                    //
// argv[3]=split level for Event branch (default=1)                         //
// argv[4]=average number of tracks per event (default=600)                 //
//                                                                          //
//////////////////////////////////////////////////////////////////////////////

int main(int argc, char **argv)
{
// Instantiate TROOT
  TROOT simple("simple","Example of creation of a tree");

  Int_t nevent = 300;               // by default create 300 events
  if(argc > 1)nevent=atoi(argv[1]);
  Int_t comp = 1;                   // by default file is compressed
  if(argc > 2)nevent=atoi(argv[2]);
  Int_t split = 1;                  // by default split Event into sub branches
  if(argc > 3)nevent=atoi(argv[3]);
  Int_t navgtrk=600;                // by default avg ntracks per event = 600
  if(argc > 4)nevent=atoi(argv[4]);

// Instantiate one Event
  Event *event = new Event();

// Set debug flag for extra printout
// gDebug = TTabCom::kDebug ;

// Create a timer object to benchmark time spent
  TStopwatch timer;
  timer.Start();
  
// Create a new ROOT binary machine independent file
// This file becomes the current directory.
  TFile *hfile=new TFile("Event.root","RECREATE","TTree benchmark ROOT file");
  hfile->SetCompressionLevel(comp);

// Create a ROOT tree
// arguments = name,title,maxvirtualsize (default = 64 Mbytes)
  TTree *tree = new TTree("T","An example of a ROOT tree");

// Create a superbranch
  Int_t bufsize=256000;        //Basket buffer size (bytes)
  if(split)bufsize /= 4; 
// arguments = branch name, class name, address of a pointer to Event object,
// basket buffer size (buffers are written to disk when they exceed this), 
// split level 
  tree->Branch("event","Event",&event,bufsize,split);

// Loop over events
  Int_t nbtot =0;       // Total bytes written to tree
  Int_t nb;             // Bytes written to tree for individual event
  Int_t oldprt =-1;     // Print flag
  Float_t sigmat,sigmas;

  for (Int_t ievt=0; ievt < nevent; ievt++) {

    // Determine and set event parameters
    gRandom->Rannor(sigmat,sigmas);
    Int_t ntrack = Int_t(navgtrk+navgtrk*sigmat/120.);
    Float_t random = gRandom->Rndm(1);

    event->SetHeader(ievt,200,991019,random);
    event->SetNseg(Int_t(10*ntrack+20*sigmas));
    event->SetNvertex(1);
    event->SetFlag(UInt_t(random+0.5));
    event->SetTemperature(random+20.);

    // Create and fill the track objects
    for (Int_t itrk=0; itrk < ntrack; itrk++) event->AddTrack(random);

    // Fill the tree, returns number of bytes added to tree in this event
    nb = tree->Fill();   // Fill the tree
    nbtot += nb;         // Total number of bytes added to tree so far

    cout<<"Event " << ievt<< " " << nb <<" bytes added to tree for total of "
        << nbtot << " bytes." << endl;

    tree -> AutoSave();  // Call AutoSave to save the tree to disk
    gDirectory -> Purge(); // Purge the directory to get rid of old trees


    if(ievt/50 != oldprt){
    // Every 50 events print directory and tree structure
      oldprt += 1;
      hfile -> ls();
      tree -> Print();
    }

    event->Clear();
  }

// Write the tree to file
  hfile->Write();

// Print final summary of the tree contents
  tree ->Print();

// Stop timer and print results
  timer.Stop();
  Double_t rtime = timer.RealTime();
  Double_t ctime = timer.CpuTime();

  cout << nevent << " events and " << nbtot << " bytes processed" << endl;
  cout << "The execution of this program took " << rtime << " secs realtime"<< endl;
  cout << "or " << nbtot/rtime << " bytes/Realtime sec " << endl;
  cout << "The execution of this program took " << ctime << " secs cputime"<< endl;
  cout << "or " << nbtot/ctime << " bytes/Cputime sec " << endl;

  return 0;

}


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "Event.h"      //Event class from $ROOTSYS/test

//////////////////////////////////////////////////////////////////////////////
//                                                                          //
// Program to test root i/o capabilities                                    //
// Based on MainEvent.cxx example from $ROOTSYS/test                        //
//                                                                          //
// This program attempts to read an open .root file                         //
//                                                                          //
// No user supplied arguments.                                              //
//                                                                          //
//////////////////////////////////////////////////////////////////////////////

int main(int argc, char **argv)
{
// Instantiate TROOT, the "entry point" to the ROOT system
  TROOT simple("simple","Example of creation of a tree");

// Instantiate one Event
  Event *event = new Event();

// Set debug flag for extra printout
//  gDebug = TTabCom::kDebug ;

// Create a timer object to benchmark time spent
  TStopwatch timer;
  timer.Start();
  
// Read open ROOT binary machine independent file
// This file becomes the current directory.
  TFile *hfile=new TFile("Event.root","READ");
  TTree *tree = (TTree*)hfile->Get("T");
  TBranch *branch = tree->GetBranch("event");
  branch->SetAddress(&event);

  Int_t nevent = (Int_t)tree->GetEntries();

// Loop over all events  
  Int_t nb;        // bytes per event
  Int_t nbtot = 0;     // Total bytes read in
  for (Int_t ievt=0; ievt < nevent; ievt++) {
    nb = tree->GetEntry(ievt);       //read complete event in memory
    nbtot += nb;                     //total bytes read in so far
    cout << "Event " << ievt << " size " << nb << " for total "<Print();

// Stop timer and print results
  timer.Stop();
  Double_t rtime = timer.RealTime();
  Double_t ctime = timer.CpuTime();

  cout << nevent << " events and " << nbtot << " bytes processed" << endl;
  cout << "The execution of this program took " << rtime << " secs realtime"<< endl;
  cout << "or " << nbtot/rtime << " bytes/Realtime sec " << endl;
  cout << "The execution of this program took " << ctime << " secs cputime"<< endl;
  cout << "or " << nbtot/ctime << " bytes/Cputime sec " << endl;

  return 0;

}