// @(#)root/proofplayer:$Id$
// Author: Kristjan Gulbrandsen   11/05/04

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TPerfStats                                                           //
//                                                                      //
// Provides the interface for the PROOF internal performance measurment //
// and event tracing.                                                   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////


#include "TPerfStats.h"

#include "Riostream.h"
#include "TCollection.h"
#include "TEnv.h"
#include "TError.h"
#include "TFile.h"
#include "TH1.h"
#include "TH2.h"
#include "TDSet.h"
#include "TProofDebug.h"
#include "TProof.h"
#include "TProofServ.h"
#include "TSlave.h"
#include "TStatus.h"
#include "TTree.h"
#include "TSQLServer.h"
#include "TSQLResult.h"
#include "TParameter.h"
#include "TPluginManager.h"
#include "TROOT.h"
#include "TTimeStamp.h"
#include "TProofMonSender.h"

ClassImp(TPerfEvent)
ClassImp(TPerfStats)


//------------------------------------------------------------------------------

//______________________________________________________________________________
TPerfEvent::TPerfEvent(TTimeStamp *offset)
   : fEvtNode("-3"), fType(TVirtualPerfStats::kUnDefined), fSlave(),
     fEventsProcessed(0), fBytesRead(0), fLen(0), fLatency(0.0), fProcTime(0.0), fCpuTime(0.0),
     fIsStart(kFALSE), fIsOk(kFALSE)
{
   // Constructor

   if (gProofServ != 0) {
      fEvtNode = gProofServ->GetOrdinal();
   } else {
      if (gProof && gProof->IsLite())
         fEvtNode = "0";
      else
         fEvtNode = "-2"; // not on a PROOF server
   }

   if (offset != 0) {
      fTimeStamp = TTimeStamp(fTimeStamp.GetSec() - offset->GetSec(),
                     fTimeStamp.GetNanoSec() - offset->GetNanoSec());
   }
}

//______________________________________________________________________________
Int_t TPerfEvent::Compare(const TObject *obj) const
{
   // Compare method. Must return -1 if this is smaller than obj,
   // 0 if objects are equal and 1 if this is larger than obj.

   const TPerfEvent *pe = dynamic_cast<const TPerfEvent*>(obj);

   if (!pe) {
      Error("Compare", "input is not a TPerfEvent object");
      return 0;
   }

   if (fTimeStamp < pe->fTimeStamp) {
      return -1;
   } else if (fTimeStamp == pe->fTimeStamp) {
      return 0;
   } else {
      return 1;
   }
}

//______________________________________________________________________________
void TPerfEvent::Print(Option_t *) const
{
   // Dump content of this instance

   TString where;
   if (fEvtNode == -2) {
      where = "TPerfEvent: StandAlone ";
   } else if ( fEvtNode == -1 ) {
      where = "TPerfEvent: Master ";
   } else {
      where.Form("TPerfEvent: Worker %s ", fEvtNode.Data());
   }
   Printf("%s %s %f", where.Data(),
                      TVirtualPerfStats::EventType(fType), double(fTimeStamp));
}

Long_t TPerfStats::fgVirtMemMax = -1;
Long_t TPerfStats::fgResMemMax = -1;

//______________________________________________________________________________
TPerfStats::TPerfStats(TList *input, TList *output)
   : fTrace(0), fPerfEvent(0), fPacketsHist(0), fProcPcktHist(0),
      fEventsHist(0), fLatencyHist(0),
      fProcTimeHist(0), fCpuTimeHist(0), fBytesRead(0),
      fTotCpuTime(0.), fTotBytesRead(0), fTotEvents(0), fNumEvents(0),
      fSlaves(0), fDoHist(kFALSE),
      fDoTrace(kFALSE), fDoTraceRate(kFALSE), fDoSlaveTrace(kFALSE), fDoQuota(kFALSE),
      fMonitorPerPacket(kFALSE), fMonSenders(3),
      fDataSet("+++none+++"), fDataSetSize(-1), fOutput(output)
{
   // Normal constructor.

   TProof *proof = (gProofServ) ? gProofServ->GetProof() : gProof;

   // Master flag
   Bool_t isMaster = ((proof && proof->TestBit(TProof::kIsMaster)) ||
                      (gProofServ && gProofServ->IsMaster())) ? kTRUE : kFALSE;
   Bool_t isEndMaster = ((gProofServ && gProofServ->IsEndMaster()) ||
                         (proof && proof->IsLite())) ? kTRUE : kFALSE;

   TList *l = proof ? proof->GetListOfSlaveInfos() : 0 ;
   TIter nextslaveinfo(l);
   while (TSlaveInfo *si = dynamic_cast<TSlaveInfo*>(nextslaveinfo()))
      if (si->fStatus == TSlaveInfo::kActive) fSlaves++;

   PDB(kMonitoring,1) Info("TPerfStats", "Statistics for %d slave(s)", fSlaves);

   fDoHist = (input->FindObject("PROOF_StatsHist") != 0);
   fDoTrace = (input->FindObject("PROOF_StatsTrace") != 0);
   fDoTraceRate = (input->FindObject("PROOF_RateTrace") != 0);
   fDoSlaveTrace = (input->FindObject("PROOF_SlaveStatsTrace") != 0);
   PDB(kMonitoring,1)
      Info("TPerfStats", "master:%d  hist:%d,trace:%d,rate:%d,wrktrace:%d",
                         isMaster, fDoHist, fDoTrace, fDoTraceRate, fDoSlaveTrace);

   // Check per packet monitoring
   Int_t perpacket = -1;
   if (TProof::GetParameter(input, "PROOF_MonitorPerPacket", perpacket) != 0) {
      // Check if there is a global monitor-per-packet setting
      perpacket = gEnv->GetValue("Proof.MonitorPerPacket", 0);
   }
   fMonitorPerPacket = (perpacket == 1) ? kTRUE : kFALSE;
   if (fMonitorPerPacket)
      Info("TPerfStats", "sending full information after each packet");

   // Extract the name of the dataset
   TObject *o = 0;
   TIter nxi(input);
   while ((o = nxi()))
      if (!strncmp(o->ClassName(), "TDSet", strlen("TDSet"))) break;
   if (o) {
      fDSet = (TDSet *) o;
      fDataSetSize = fDSet->GetNumOfFiles();
      if (fDataSetSize > 0) {
         fDataSet = "";
         TString grus = (gProofServ) ? TString::Format("/%s/%s/", gProofServ->GetGroup(),
                                                                  gProofServ->GetUser()) : TString("");
         TString dss = fDSet->GetName(), ds;
         Ssiz_t fd = 0, nq = kNPOS;
         while (dss.Tokenize(ds, fd, "[,| ]")) {
            if ((nq = ds.Index("?")) != kNPOS) ds.Remove(nq);
            ds.ReplaceAll(grus, "");
            if (!fDataSet.IsNull()) fDataSet += ",";
            fDataSet += ds;
         }
      }
   }

   // Dataset string limited in length: get the authorized size
   fDataSetLen = gEnv->GetValue("Proof.Monitor.DataSetLen", 512);
   if (fDataSetLen != 512)
      Info("TPerfStats", "dataset string length truncated to %d chars", fDataSetLen);
   if (fDataSet.Length() > fDataSetLen) fDataSet.Resize(fDataSetLen);
   //
   PDB(kMonitoring,1)
      Info("TPerfStats", "dataset: '%s', # files: %d", fDataSet.Data(), fDataSetSize);

   if ((isMaster && (fDoTrace || fDoTraceRate)) || (!isMaster && fDoSlaveTrace)) {
      // Construct tree
      gDirectory->RecursiveRemove(gDirectory->FindObject("PROOF_PerfStats"));
      fTrace = new TTree("PROOF_PerfStats", "PROOF Statistics");
      fTrace->SetDirectory(0);
      fTrace->Bronch("PerfEvents", "TPerfEvent", &fPerfEvent, 64000, 0);
      output->Add(fTrace);
      PDB(kMonitoring,1)
         Info("TPerfStats", "tree '%s' added to the output list", fTrace->GetName());
   }

   if (fDoHist && isEndMaster) {
      // Make Histograms
      Double_t time_per_bin = 1e-3; // 10ms
      Double_t min_time = 0;
      Int_t ntime_bins = 1000;

      gDirectory->RecursiveRemove(gDirectory->FindObject("PROOF_PacketsHist"));
      fPacketsHist = new TH1D("PROOF_PacketsHist", "Packets processed per Worker",
                              fSlaves, 0, fSlaves);
      fPacketsHist->SetFillColor(kCyan);
      fPacketsHist->SetDirectory(0);
      fPacketsHist->SetMinimum(0);
      output->Add(fPacketsHist);
      PDB(kMonitoring,1)
         Info("TPerfStats", "histo '%s' added to the output list", fPacketsHist->GetName());

      gDirectory->RecursiveRemove(gDirectory->FindObject("PROOF_ProcPcktHist"));
      fProcPcktHist = new TH1I("PROOF_ProcPcktHist", "Packets being processed per Worker",
                              fSlaves, 0, fSlaves);
      fProcPcktHist->SetFillColor(kRed);
      fProcPcktHist->SetDirectory(0);
      fProcPcktHist->SetMinimum(0);
      output->Add(fProcPcktHist);
      PDB(kMonitoring,1)
         Info("TPerfStats", "histo '%s' added to the output list", fProcPcktHist->GetName());

      gDirectory->RecursiveRemove(gDirectory->FindObject("PROOF_EventsHist"));
      fEventsHist = new TH1D("PROOF_EventsHist", "Events processed per Worker",
                             fSlaves, 0, fSlaves);
      fEventsHist->SetFillColor(kGreen);
      fEventsHist->SetDirectory(0);
      fEventsHist->SetMinimum(0);
      output->Add(fEventsHist);
      PDB(kMonitoring,1)
         Info("TPerfStats", "histo '%s' added to the output list", fEventsHist->GetName());

      gDirectory->RecursiveRemove(gDirectory->FindObject("PROOF_NodeHist"));
      fNodeHist = new TH1D("PROOF_NodeHist", "Slaves per Fileserving Node",
                           fSlaves, 0, fSlaves);
      fNodeHist->SetDirectory(0);
      fNodeHist->SetMinimum(0);
      fNodeHist->SetCanExtend(TH1::kAllAxes);
      output->Add(fNodeHist);
      PDB(kMonitoring,1)
         Info("TPerfStats", "histo '%s' added to the output list", fNodeHist->GetName());

      gDirectory->RecursiveRemove(gDirectory->FindObject("PROOF_LatencyHist"));
      fLatencyHist = new TH2D("PROOF_LatencyHist", "GetPacket Latency per Worker",
                              fSlaves, 0, fSlaves,
                              ntime_bins, min_time, time_per_bin);
      fLatencyHist->SetDirectory(0);
      fLatencyHist->SetMarkerStyle(4);
      fLatencyHist->SetCanExtend(TH1::kAllAxes);
      output->Add(fLatencyHist);
      PDB(kMonitoring,1)
         Info("TPerfStats", "histo '%s' added to the output list", fLatencyHist->GetName());

      gDirectory->RecursiveRemove(gDirectory->FindObject("PROOF_ProcTimeHist"));
      fProcTimeHist = new TH2D("PROOF_ProcTimeHist", "Packet Processing Time per Worker",
                               fSlaves, 0, fSlaves,
                               ntime_bins, min_time, time_per_bin);
      fProcTimeHist->SetDirectory(0);
      fProcTimeHist->SetMarkerStyle(4);
      fProcTimeHist->SetCanExtend(TH1::kAllAxes);
      output->Add(fProcTimeHist);
      PDB(kMonitoring,1)
         Info("TPerfStats", "histo '%s' added to the output list", fProcTimeHist->GetName());

      gDirectory->RecursiveRemove(gDirectory->FindObject("PROOF_CpuTimeHist"));
      fCpuTimeHist = new TH2D("PROOF_CpuTimeHist", "Packet CPU Time per Worker",
                              fSlaves, 0, fSlaves,
                              ntime_bins, min_time, time_per_bin);
      fCpuTimeHist->SetDirectory(0);
      fCpuTimeHist->SetMarkerStyle(4);
      fCpuTimeHist->SetCanExtend(TH1::kAllAxes);
      output->Add(fCpuTimeHist);
      PDB(kMonitoring,1)
         Info("TPerfStats", "histo '%s' added to the output list", fCpuTimeHist->GetName());

      nextslaveinfo.Reset();
      Int_t slavebin=1;
      while (TSlaveInfo *si = dynamic_cast<TSlaveInfo*>(nextslaveinfo())) {
         if (si->fStatus == TSlaveInfo::kActive) {
            fPacketsHist->GetXaxis()->SetBinLabel(slavebin, si->GetOrdinal());
            fProcPcktHist->GetXaxis()->SetBinLabel(slavebin, si->GetOrdinal());
            fEventsHist->GetXaxis()->SetBinLabel(slavebin, si->GetOrdinal());
            fNodeHist->GetXaxis()->SetBinLabel(slavebin, si->GetOrdinal());
            fLatencyHist->GetXaxis()->SetBinLabel(slavebin, si->GetOrdinal());
            fProcTimeHist->GetXaxis()->SetBinLabel(slavebin, si->GetOrdinal());
            fCpuTimeHist->GetXaxis()->SetBinLabel(slavebin, si->GetOrdinal());
            slavebin++;
         }
      }
   }

   if (isMaster) {

      // Monitoring for query performances using monitoring system (e.g. Monalisa, SQL, ...)
      //
      // We support multiple specifications separated by ',' or '|' or '\' (the latter need
      // top be escaped three times in the regular experession), e.g.
      // ProofServ.Monitoring:  Monalisa bla bla bla,
      // +ProofServ.Monitoring:  SQL blu blu blu

      TString mons = gEnv->GetValue("ProofServ.Monitoring", ""), mon;
      Ssiz_t fmon = 0;
      TProofMonSender *monSender = 0;
      while (mons.Tokenize(mon, fmon, "[,|\\\\]")) {
         if (mon != "") {
            // Extract arguments (up to 9 'const char *')
            TString a[10];
            Int_t from = 0;
            TString tok, sendopts;
            Int_t na = 0;
            while (mon.Tokenize(tok, from, " ")) {
               if (tok.BeginsWith("sendopts:")) {
                  tok.ReplaceAll("sendopts:", "");
                  sendopts = tok;
               } else {
                  a[na++] = tok;
               }
            }
            na--;
            // Get monitor object from the plugin manager
            TPluginHandler *h = 0;
            if ((h = gROOT->GetPluginManager()->FindHandler("TProofMonSender", a[0]))) {
               if (h->LoadPlugin() != -1) {
                  monSender =
                     (TProofMonSender *) h->ExecPlugin(na, a[1].Data(), a[2].Data(), a[3].Data(),
                                                           a[4].Data(), a[5].Data(), a[6].Data(),
                                                           a[7].Data(), a[8].Data(), a[9].Data());
                  if (monSender && monSender->TestBit(TObject::kInvalidObject)) SafeDelete(monSender);
                  if (monSender && monSender->SetSendOptions(sendopts) != 0) SafeDelete(monSender);
               }
            }
         }

         if (monSender) {
            fMonSenders.Add(monSender);
            PDB(kMonitoring,1)
               Info("TPerfStats", "created monitoring object: %s - # of active monitors: %d",
                                  mon.Data(), fMonSenders.GetEntries());
            fDoQuota = kTRUE;
         }
         monSender = 0;
      }
   }
}

//______________________________________________________________________________
TPerfStats::~TPerfStats()
{
   // Destructor

   // Shutdown the monitor writers, if any
   fMonSenders.SetOwner(kTRUE);
   fMonSenders.Delete();
}

//______________________________________________________________________________
void TPerfStats::SimpleEvent(EEventType type)
{
   // Simple event.

   if (type == kStop && fPacketsHist != 0) {
      fPacketsHist->LabelsDeflate("X");
      fPacketsHist->LabelsOption("auv","X");
   }

   if (type == kStop && fDoQuota)
      WriteQueryLog();

   if (fTrace == 0) return;

   TPerfEvent pe(&fTzero);
   pe.fType = type;

   fPerfEvent = &pe;
   fTrace->SetBranchAddress("PerfEvents",&fPerfEvent);
   fTrace->Fill();
   fPerfEvent = 0;
}

//______________________________________________________________________________
void TPerfStats::PacketEvent(const char *slave, const char* slavename, const char* filename,
                             Long64_t eventsprocessed, Double_t latency, Double_t proctime,
                             Double_t cputime, Long64_t bytesRead)
{
   // Packet event.
   // See WriteQueryLog for the descripition of the structure sent for monitoring
   // when fMonitorPerPacket is kTRUE.

   if (fDoTrace && fTrace != 0) {
      TPerfEvent pe(&fTzero);

      pe.fType = kPacket;
      pe.fSlaveName = slavename;
      pe.fFileName = filename;
      pe.fSlave = slave;
      pe.fEventsProcessed = eventsprocessed;
      pe.fBytesRead = bytesRead;
      pe.fLatency = latency;
      pe.fProcTime = proctime;
      pe.fCpuTime = cputime;

      fPerfEvent = &pe;
      fTrace->SetBranchAddress("PerfEvents",&fPerfEvent);
      fTrace->Fill();
      fPerfEvent = 0;
   }

   PDB(kMonitoring,1)
      Info("PacketEvent","%s: fDoHist: %d, fPacketsHist: %p, eventsprocessed: %lld",
                         slave, fDoHist, fPacketsHist, eventsprocessed);

   if (fDoHist && fPacketsHist != 0) {
      fPacketsHist->Fill(slave, 1);
      fEventsHist->Fill(slave, eventsprocessed);
      fLatencyHist->Fill(slave, latency, 1);
      fProcTimeHist->Fill(slave, proctime, 1);
      fCpuTimeHist->Fill(slave, cputime, 1);
   }

   if (fDoQuota) {
      fTotCpuTime += cputime;
      fTotBytesRead += bytesRead;
      fTotEvents += eventsprocessed;
   }

   // Write to monitoring system, if requested
   if (!fMonSenders.IsEmpty() && fMonitorPerPacket) {
      TQueryResult *qr = (gProofServ && gProofServ->GetProof()) ?
                          gProofServ->GetProof()->GetQueryResult() : 0;
      if (!gProofServ || !gProofServ->GetSessionTag() || !gProofServ->GetProof() || !qr) {
         Error("PacketEvent", "some required object are undefined (%p %p %p %p)",
               gProofServ, (gProofServ ? gProofServ->GetSessionTag() : 0),
              (gProofServ ? gProofServ->GetProof() : 0),
              ((gProofServ && gProofServ->GetProof()) ? qr : 0));
         return;
      }

      TTimeStamp stop;
      TString identifier;
      identifier.Form("%s-q%d", gProofServ->GetSessionTag(), qr->GetSeqNum());

      TList values;
      values.SetOwner();
      values.Add(new TParameter<int>("id", 0));
      values.Add(new TNamed("user", gProofServ->GetUser()));
      values.Add(new TNamed("proofgroup", gProofServ->GetGroup()));
      values.Add(new TNamed("begin", fTzero.AsString("s")));
      values.Add(new TNamed("end", stop.AsString("s")));
      values.Add(new TParameter<int>("walltime", stop.GetSec()-fTzero.GetSec()));
      values.Add(new TParameter<Long64_t>("bytesread", fTotBytesRead));
      values.Add(new TParameter<Long64_t>("events", fTotEvents));
      values.Add(new TParameter<Long64_t>("totevents", fNumEvents));
      values.Add(new TParameter<int>("workers", fSlaves));
      values.Add(new TNamed("querytag", identifier.Data()));

      // Memory usage on workers
      TStatus *pst = (fOutput) ? (TStatus *) fOutput->FindObject("PROOF_Status") : 0;
      // This most likely will be always NULL when sending from GetNextPacket ...
      Long64_t vmxw = (pst) ? (Long64_t) pst->GetVirtMemMax() : -1;
      Long64_t rmxw = (pst) ? (Long64_t) pst->GetResMemMax() : -1;
      values.Add(new TParameter<Long64_t>("vmemmxw", vmxw));
      values.Add(new TParameter<Long64_t>("rmemmxw", rmxw));
      // Memory usage on master
      values.Add(new TParameter<Long64_t>("vmemmxm", (Long64_t) fgVirtMemMax));
      values.Add(new TParameter<Long64_t>("rmemmxm", (Long64_t) fgResMemMax));
      // Dataset information
      values.Add(new TNamed("dataset", fDataSet.Data()));
      values.Add(new TParameter<int>("numfiles", fDataSetSize));
      // Missing files
      TList *mfls = (fOutput) ? (TList *) fOutput->FindObject("MissingFiles") : 0;
      Int_t nmiss = (mfls && mfls->GetSize() > 0) ? mfls->GetSize() : 0;
      values.Add(new TParameter<int>("missfiles", nmiss));
      // Query status
      Int_t est = (pst) ? pst->GetExitStatus() : -1;
      values.Add(new TParameter<int>("status", est));
      // Root version
      TString rver = TString::Format("%s|%s", gROOT->GetVersion(), gROOT->GetGitCommit());
      values.Add(new TNamed("rootver", rver.Data()));

      for (Int_t i = 0; i < fMonSenders.GetEntries(); i++) {
         TProofMonSender *m = (TProofMonSender *) fMonSenders[i];
         if (m) {
            // Send query summary
            if (m->SendSummary(&values, identifier) != 0)
               Error("PacketEvent", "sending of summary info failed (%s)", m->GetName());
         } else {
            Warning("PacketEvent", "undefined entry found in monitors array for id: %d", i);
         }
      }
   }
}

//______________________________________________________________________________
void TPerfStats::FileEvent(const char *slave, const char *slavename, const char *nodename,
                            const char *filename, Bool_t isStart)
{
   // File event.

   if (fDoTrace && fTrace != 0) {
      TPerfEvent pe(&fTzero);

      pe.fType = kFile;
      pe.fSlaveName = slavename;
      pe.fNodeName = nodename;
      pe.fFileName = filename;
      pe.fSlave = slave;
      pe.fIsStart = isStart;

      fPerfEvent = &pe;
      fTrace->SetBranchAddress("PerfEvents",&fPerfEvent);
      fTrace->Fill();
      fPerfEvent = 0;
   }

   if (fDoHist && fPacketsHist != 0) {
      fNodeHist->Fill(nodename, isStart ? 1 : -1);
   }
}

//______________________________________________________________________________
void TPerfStats::FileOpenEvent(TFile *file, const char *filename, Double_t start)
{
   // Open file event.

   if (fDoTrace && fTrace != 0) {
      TPerfEvent pe(&fTzero);

      pe.fType = kFileOpen;
      pe.fFileName = filename;
      pe.fFileClass = file != 0 ? file->ClassName() : "none";
      pe.fProcTime = double(TTimeStamp())-start;
      pe.fIsOk = (file != 0);

      fPerfEvent = &pe;
      fTrace->SetBranchAddress("PerfEvents",&fPerfEvent);
      fTrace->Fill();
      fPerfEvent = 0;
   }
}

//______________________________________________________________________________
void TPerfStats::FileReadEvent(TFile *file, Int_t len, Double_t start)
{
   // Read file event.

   if (fDoTrace && fTrace != 0) {
      TPerfEvent pe(&fTzero);

      pe.fType = kFileRead;
      pe.fFileName = file->GetName();
      pe.fFileClass = file->ClassName();
      pe.fLen = len;
      pe.fProcTime = double(TTimeStamp())-start;

      fPerfEvent = &pe;
      fTrace->SetBranchAddress("PerfEvents",&fPerfEvent);
      fTrace->Fill();
      fPerfEvent = 0;
   }
}

//______________________________________________________________________________
void TPerfStats::UnzipEvent(TObject * /* tree */, Long64_t /* pos */,
                            Double_t /* start */, Int_t /* complen */,
                            Int_t /* objlen */)
{
   // Record TTree file unzip event.
   // start is the TimeStamp before unzip
   // pos is where in the file the compressed buffer came from
   // complen is the length of the compressed buffer
   // objlen is the length of the de-compressed buffer

   // Do nothing for now.
}

//______________________________________________________________________________
void TPerfStats::RateEvent(Double_t proctime, Double_t deltatime,
                           Long64_t eventsprocessed, Long64_t bytesRead)
{
   // Rate event.

   if ((fDoTrace || fDoTraceRate) && fTrace != 0) {
      TPerfEvent pe(&fTzero);

      pe.fType = kRate;
      pe.fEventsProcessed = eventsprocessed;
      pe.fBytesRead = bytesRead;
      pe.fProcTime = proctime;
      pe.fLatency = deltatime;

      fPerfEvent = &pe;
      fTrace->SetBranchAddress("PerfEvents",&fPerfEvent);
      fTrace->Fill();
      fPerfEvent = 0;
   }
}

//______________________________________________________________________________
void TPerfStats::SetBytesRead(Long64_t num)
{
   // Set number of bytes read.

   fBytesRead = num;
}

//______________________________________________________________________________
Long64_t TPerfStats::GetBytesRead() const
{
   // Get number of bytes read.

   return fBytesRead;
}

//______________________________________________________________________________
void TPerfStats::WriteQueryLog()
{
   // Send to the connected monitoring servers information related to this query.
   // The information is of three types: 'summary', 'dataset' and 'files'.
   // Actual 'table' formatting is done by the relevant sender, implementation of
   // TProofMonSender, where the details are given.

   TTimeStamp stop;

   // Write to monitoring system
   if (!fMonSenders.IsEmpty()) {
      TQueryResult *qr = (gProofServ && gProofServ->GetProof()) ?
                          gProofServ->GetProof()->GetQueryResult() : 0;
      if (!gProofServ || !gProofServ->GetSessionTag() || !gProofServ->GetProof() || !qr) {
         Error("WriteQueryLog", "some required object are undefined (%p %p %p %p)",
               gProofServ, (gProofServ ? gProofServ->GetSessionTag() : 0),
              (gProofServ ? gProofServ->GetProof() : 0),
              ((gProofServ && gProofServ->GetProof()) ? qr : 0));
         return;
      }

      TString identifier;
      identifier.Form("%s-q%d", gProofServ->GetSessionTag(), qr->GetSeqNum());

      TList values;
      values.SetOwner();
      values.Add(new TParameter<int>("id", 0));
      values.Add(new TNamed("user", gProofServ->GetUser()));
      values.Add(new TNamed("proofgroup", gProofServ->GetGroup()));
      values.Add(new TNamed("begin", fTzero.AsString("s")));
      values.Add(new TNamed("end", stop.AsString("s")));
      values.Add(new TParameter<int>("walltime", stop.GetSec()-fTzero.GetSec()));
      values.Add(new TParameter<float>("cputime", fTotCpuTime));
      values.Add(new TParameter<Long64_t>("bytesread", fTotBytesRead));
      values.Add(new TParameter<Long64_t>("events", fTotEvents));
      values.Add(new TParameter<Long64_t>("totevents", fTotEvents));
      values.Add(new TParameter<int>("workers", fSlaves));
      values.Add(new TNamed("querytag", identifier.Data()));

      TList *mfls = (fOutput) ? (TList *) fOutput->FindObject("MissingFiles") : 0;
      // Memory usage on workers
      TStatus *pst = (fOutput) ? (TStatus *) fOutput->FindObject("PROOF_Status") : 0;
      Long64_t vmxw = (pst) ? (Long64_t) pst->GetVirtMemMax() : -1;
      Long64_t rmxw = (pst) ? (Long64_t) pst->GetResMemMax() : -1;
      values.Add(new TParameter<Long64_t>("vmemmxw", vmxw));
      values.Add(new TParameter<Long64_t>("rmemmxw", rmxw));
      // Memory usage on master
      values.Add(new TParameter<Long64_t>("vmemmxm", (Long64_t) fgVirtMemMax));
      values.Add(new TParameter<Long64_t>("rmemmxm", (Long64_t) fgResMemMax));
      // Dataset information
      values.Add(new TNamed("dataset", fDataSet.Data()));
      values.Add(new TParameter<int>("numfiles", fDataSetSize));
      // Missing files
      Int_t nmiss = (mfls && mfls->GetSize() > 0) ? mfls->GetSize() : 0;
      values.Add(new TParameter<int>("missfiles", nmiss));
      // Query status
      Int_t est = (pst) ? pst->GetExitStatus() : -1;
      values.Add(new TParameter<int>("status", est));
      // Root version
      TString rver = TString::Format("%s|%s", gROOT->GetVersion(), gROOT->GetGitCommit());
      values.Add(new TNamed("rootver", rver.Data()));

      for (Int_t i = 0; i < fMonSenders.GetEntries(); i++) {
         TProofMonSender *m = (TProofMonSender *) fMonSenders[i];
         if (m) {
            // Send query summary
            if (m->SendSummary(&values, identifier) != 0)
               Error("WriteQueryLog", "sending of summary info failed (%s)", m->GetName());
            // Send dataset information
            if (m->SendDataSetInfo(fDSet, mfls, fTzero.AsString("s"), identifier) != 0)
               Error("WriteQueryLog", "sending of dataset info failed (%s)", m->GetName());
            // Send file information
            if (m->SendFileInfo(fDSet, mfls, fTzero.AsString("s"), identifier) != 0)
               Error("WriteQueryLog", "sending of files info failed (%s)", m->GetName());
         } else {
            Warning("WriteQueryLog", "undefined entry found in monitors array for id: %d", i);
         }
      }
   }
}

//______________________________________________________________________________
void TPerfStats::Setup(TList *input)
{
   // Setup the PROOF input list with requested statistics and tracing options.

   const Int_t ntags=3;
   const char *tags[ntags] = {"StatsHist", "StatsTrace", "SlaveStatsTrace"};

   TString varname, parname;
   for (Int_t i=0; i<ntags; i++) {
      varname.Form("Proof.%s", tags[i]);
      parname.Form("PROOF_%s", tags[i]);
      if (!input->FindObject(parname))
         if (gEnv->GetValue(varname, 0)) input->Add(new TNamed(parname.Data(),""));
   }
}

//______________________________________________________________________________
void TPerfStats::Start(TList *input, TList *output)
{
   // Initialize PROOF statistics run.

   if (gPerfStats)
      delete gPerfStats;
   fgVirtMemMax = -1;
   fgResMemMax = -1;
   TPerfStats::SetMemValues();

   gPerfStats = new TPerfStats(input, output);
   if (gPerfStats && !gPerfStats->TestBit(TObject::kInvalidObject)) {
      // This measures the time taken by the constructor: not negligeable ...
      gPerfStats->SimpleEvent(TVirtualPerfStats::kStart);
   } else {
      SafeDelete(gPerfStats);
   }
}

//______________________________________________________________________________
void TPerfStats::Stop()
{
   // Terminate the PROOF statistics run.

   if (!gPerfStats) return;

   TPerfStats::SetMemValues();
   gPerfStats->SimpleEvent(TVirtualPerfStats::kStop);

   delete gPerfStats;
   gPerfStats = 0;
}

//______________________________________________________________________________
void TPerfStats::SetMemValues()
{
   // Record memory usage

   ProcInfo_t pi;
   if (!gSystem->GetProcInfo(&pi)){
      if (pi.fMemVirtual > fgVirtMemMax) fgVirtMemMax = pi.fMemVirtual;
      if (pi.fMemResident > fgResMemMax) fgResMemMax = pi.fMemResident;
   }
}

//______________________________________________________________________________
void TPerfStats::GetMemValues(Long_t &vmax, Long_t &rmax)
{
   // Get memory usage

   vmax = fgVirtMemMax;
   rmax = fgResMemMax;
}
 TPerfStats.cxx:1
 TPerfStats.cxx:2
 TPerfStats.cxx:3
 TPerfStats.cxx:4
 TPerfStats.cxx:5
 TPerfStats.cxx:6
 TPerfStats.cxx:7
 TPerfStats.cxx:8
 TPerfStats.cxx:9
 TPerfStats.cxx:10
 TPerfStats.cxx:11
 TPerfStats.cxx:12
 TPerfStats.cxx:13
 TPerfStats.cxx:14
 TPerfStats.cxx:15
 TPerfStats.cxx:16
 TPerfStats.cxx:17
 TPerfStats.cxx:18
 TPerfStats.cxx:19
 TPerfStats.cxx:20
 TPerfStats.cxx:21
 TPerfStats.cxx:22
 TPerfStats.cxx:23
 TPerfStats.cxx:24
 TPerfStats.cxx:25
 TPerfStats.cxx:26
 TPerfStats.cxx:27
 TPerfStats.cxx:28
 TPerfStats.cxx:29
 TPerfStats.cxx:30
 TPerfStats.cxx:31
 TPerfStats.cxx:32
 TPerfStats.cxx:33
 TPerfStats.cxx:34
 TPerfStats.cxx:35
 TPerfStats.cxx:36
 TPerfStats.cxx:37
 TPerfStats.cxx:38
 TPerfStats.cxx:39
 TPerfStats.cxx:40
 TPerfStats.cxx:41
 TPerfStats.cxx:42
 TPerfStats.cxx:43
 TPerfStats.cxx:44
 TPerfStats.cxx:45
 TPerfStats.cxx:46
 TPerfStats.cxx:47
 TPerfStats.cxx:48
 TPerfStats.cxx:49
 TPerfStats.cxx:50
 TPerfStats.cxx:51
 TPerfStats.cxx:52
 TPerfStats.cxx:53
 TPerfStats.cxx:54
 TPerfStats.cxx:55
 TPerfStats.cxx:56
 TPerfStats.cxx:57
 TPerfStats.cxx:58
 TPerfStats.cxx:59
 TPerfStats.cxx:60
 TPerfStats.cxx:61
 TPerfStats.cxx:62
 TPerfStats.cxx:63
 TPerfStats.cxx:64
 TPerfStats.cxx:65
 TPerfStats.cxx:66
 TPerfStats.cxx:67
 TPerfStats.cxx:68
 TPerfStats.cxx:69
 TPerfStats.cxx:70
 TPerfStats.cxx:71
 TPerfStats.cxx:72
 TPerfStats.cxx:73
 TPerfStats.cxx:74
 TPerfStats.cxx:75
 TPerfStats.cxx:76
 TPerfStats.cxx:77
 TPerfStats.cxx:78
 TPerfStats.cxx:79
 TPerfStats.cxx:80
 TPerfStats.cxx:81
 TPerfStats.cxx:82
 TPerfStats.cxx:83
 TPerfStats.cxx:84
 TPerfStats.cxx:85
 TPerfStats.cxx:86
 TPerfStats.cxx:87
 TPerfStats.cxx:88
 TPerfStats.cxx:89
 TPerfStats.cxx:90
 TPerfStats.cxx:91
 TPerfStats.cxx:92
 TPerfStats.cxx:93
 TPerfStats.cxx:94
 TPerfStats.cxx:95
 TPerfStats.cxx:96
 TPerfStats.cxx:97
 TPerfStats.cxx:98
 TPerfStats.cxx:99
 TPerfStats.cxx:100
 TPerfStats.cxx:101
 TPerfStats.cxx:102
 TPerfStats.cxx:103
 TPerfStats.cxx:104
 TPerfStats.cxx:105
 TPerfStats.cxx:106
 TPerfStats.cxx:107
 TPerfStats.cxx:108
 TPerfStats.cxx:109
 TPerfStats.cxx:110
 TPerfStats.cxx:111
 TPerfStats.cxx:112
 TPerfStats.cxx:113
 TPerfStats.cxx:114
 TPerfStats.cxx:115
 TPerfStats.cxx:116
 TPerfStats.cxx:117
 TPerfStats.cxx:118
 TPerfStats.cxx:119
 TPerfStats.cxx:120
 TPerfStats.cxx:121
 TPerfStats.cxx:122
 TPerfStats.cxx:123
 TPerfStats.cxx:124
 TPerfStats.cxx:125
 TPerfStats.cxx:126
 TPerfStats.cxx:127
 TPerfStats.cxx:128
 TPerfStats.cxx:129
 TPerfStats.cxx:130
 TPerfStats.cxx:131
 TPerfStats.cxx:132
 TPerfStats.cxx:133
 TPerfStats.cxx:134
 TPerfStats.cxx:135
 TPerfStats.cxx:136
 TPerfStats.cxx:137
 TPerfStats.cxx:138
 TPerfStats.cxx:139
 TPerfStats.cxx:140
 TPerfStats.cxx:141
 TPerfStats.cxx:142
 TPerfStats.cxx:143
 TPerfStats.cxx:144
 TPerfStats.cxx:145
 TPerfStats.cxx:146
 TPerfStats.cxx:147
 TPerfStats.cxx:148
 TPerfStats.cxx:149
 TPerfStats.cxx:150
 TPerfStats.cxx:151
 TPerfStats.cxx:152
 TPerfStats.cxx:153
 TPerfStats.cxx:154
 TPerfStats.cxx:155
 TPerfStats.cxx:156
 TPerfStats.cxx:157
 TPerfStats.cxx:158
 TPerfStats.cxx:159
 TPerfStats.cxx:160
 TPerfStats.cxx:161
 TPerfStats.cxx:162
 TPerfStats.cxx:163
 TPerfStats.cxx:164
 TPerfStats.cxx:165
 TPerfStats.cxx:166
 TPerfStats.cxx:167
 TPerfStats.cxx:168
 TPerfStats.cxx:169
 TPerfStats.cxx:170
 TPerfStats.cxx:171
 TPerfStats.cxx:172
 TPerfStats.cxx:173
 TPerfStats.cxx:174
 TPerfStats.cxx:175
 TPerfStats.cxx:176
 TPerfStats.cxx:177
 TPerfStats.cxx:178
 TPerfStats.cxx:179
 TPerfStats.cxx:180
 TPerfStats.cxx:181
 TPerfStats.cxx:182
 TPerfStats.cxx:183
 TPerfStats.cxx:184
 TPerfStats.cxx:185
 TPerfStats.cxx:186
 TPerfStats.cxx:187
 TPerfStats.cxx:188
 TPerfStats.cxx:189
 TPerfStats.cxx:190
 TPerfStats.cxx:191
 TPerfStats.cxx:192
 TPerfStats.cxx:193
 TPerfStats.cxx:194
 TPerfStats.cxx:195
 TPerfStats.cxx:196
 TPerfStats.cxx:197
 TPerfStats.cxx:198
 TPerfStats.cxx:199
 TPerfStats.cxx:200
 TPerfStats.cxx:201
 TPerfStats.cxx:202
 TPerfStats.cxx:203
 TPerfStats.cxx:204
 TPerfStats.cxx:205
 TPerfStats.cxx:206
 TPerfStats.cxx:207
 TPerfStats.cxx:208
 TPerfStats.cxx:209
 TPerfStats.cxx:210
 TPerfStats.cxx:211
 TPerfStats.cxx:212
 TPerfStats.cxx:213
 TPerfStats.cxx:214
 TPerfStats.cxx:215
 TPerfStats.cxx:216
 TPerfStats.cxx:217
 TPerfStats.cxx:218
 TPerfStats.cxx:219
 TPerfStats.cxx:220
 TPerfStats.cxx:221
 TPerfStats.cxx:222
 TPerfStats.cxx:223
 TPerfStats.cxx:224
 TPerfStats.cxx:225
 TPerfStats.cxx:226
 TPerfStats.cxx:227
 TPerfStats.cxx:228
 TPerfStats.cxx:229
 TPerfStats.cxx:230
 TPerfStats.cxx:231
 TPerfStats.cxx:232
 TPerfStats.cxx:233
 TPerfStats.cxx:234
 TPerfStats.cxx:235
 TPerfStats.cxx:236
 TPerfStats.cxx:237
 TPerfStats.cxx:238
 TPerfStats.cxx:239
 TPerfStats.cxx:240
 TPerfStats.cxx:241
 TPerfStats.cxx:242
 TPerfStats.cxx:243
 TPerfStats.cxx:244
 TPerfStats.cxx:245
 TPerfStats.cxx:246
 TPerfStats.cxx:247
 TPerfStats.cxx:248
 TPerfStats.cxx:249
 TPerfStats.cxx:250
 TPerfStats.cxx:251
 TPerfStats.cxx:252
 TPerfStats.cxx:253
 TPerfStats.cxx:254
 TPerfStats.cxx:255
 TPerfStats.cxx:256
 TPerfStats.cxx:257
 TPerfStats.cxx:258
 TPerfStats.cxx:259
 TPerfStats.cxx:260
 TPerfStats.cxx:261
 TPerfStats.cxx:262
 TPerfStats.cxx:263
 TPerfStats.cxx:264
 TPerfStats.cxx:265
 TPerfStats.cxx:266
 TPerfStats.cxx:267
 TPerfStats.cxx:268
 TPerfStats.cxx:269
 TPerfStats.cxx:270
 TPerfStats.cxx:271
 TPerfStats.cxx:272
 TPerfStats.cxx:273
 TPerfStats.cxx:274
 TPerfStats.cxx:275
 TPerfStats.cxx:276
 TPerfStats.cxx:277
 TPerfStats.cxx:278
 TPerfStats.cxx:279
 TPerfStats.cxx:280
 TPerfStats.cxx:281
 TPerfStats.cxx:282
 TPerfStats.cxx:283
 TPerfStats.cxx:284
 TPerfStats.cxx:285
 TPerfStats.cxx:286
 TPerfStats.cxx:287
 TPerfStats.cxx:288
 TPerfStats.cxx:289
 TPerfStats.cxx:290
 TPerfStats.cxx:291
 TPerfStats.cxx:292
 TPerfStats.cxx:293
 TPerfStats.cxx:294
 TPerfStats.cxx:295
 TPerfStats.cxx:296
 TPerfStats.cxx:297
 TPerfStats.cxx:298
 TPerfStats.cxx:299
 TPerfStats.cxx:300
 TPerfStats.cxx:301
 TPerfStats.cxx:302
 TPerfStats.cxx:303
 TPerfStats.cxx:304
 TPerfStats.cxx:305
 TPerfStats.cxx:306
 TPerfStats.cxx:307
 TPerfStats.cxx:308
 TPerfStats.cxx:309
 TPerfStats.cxx:310
 TPerfStats.cxx:311
 TPerfStats.cxx:312
 TPerfStats.cxx:313
 TPerfStats.cxx:314
 TPerfStats.cxx:315
 TPerfStats.cxx:316
 TPerfStats.cxx:317
 TPerfStats.cxx:318
 TPerfStats.cxx:319
 TPerfStats.cxx:320
 TPerfStats.cxx:321
 TPerfStats.cxx:322
 TPerfStats.cxx:323
 TPerfStats.cxx:324
 TPerfStats.cxx:325
 TPerfStats.cxx:326
 TPerfStats.cxx:327
 TPerfStats.cxx:328
 TPerfStats.cxx:329
 TPerfStats.cxx:330
 TPerfStats.cxx:331
 TPerfStats.cxx:332
 TPerfStats.cxx:333
 TPerfStats.cxx:334
 TPerfStats.cxx:335
 TPerfStats.cxx:336
 TPerfStats.cxx:337
 TPerfStats.cxx:338
 TPerfStats.cxx:339
 TPerfStats.cxx:340
 TPerfStats.cxx:341
 TPerfStats.cxx:342
 TPerfStats.cxx:343
 TPerfStats.cxx:344
 TPerfStats.cxx:345
 TPerfStats.cxx:346
 TPerfStats.cxx:347
 TPerfStats.cxx:348
 TPerfStats.cxx:349
 TPerfStats.cxx:350
 TPerfStats.cxx:351
 TPerfStats.cxx:352
 TPerfStats.cxx:353
 TPerfStats.cxx:354
 TPerfStats.cxx:355
 TPerfStats.cxx:356
 TPerfStats.cxx:357
 TPerfStats.cxx:358
 TPerfStats.cxx:359
 TPerfStats.cxx:360
 TPerfStats.cxx:361
 TPerfStats.cxx:362
 TPerfStats.cxx:363
 TPerfStats.cxx:364
 TPerfStats.cxx:365
 TPerfStats.cxx:366
 TPerfStats.cxx:367
 TPerfStats.cxx:368
 TPerfStats.cxx:369
 TPerfStats.cxx:370
 TPerfStats.cxx:371
 TPerfStats.cxx:372
 TPerfStats.cxx:373
 TPerfStats.cxx:374
 TPerfStats.cxx:375
 TPerfStats.cxx:376
 TPerfStats.cxx:377
 TPerfStats.cxx:378
 TPerfStats.cxx:379
 TPerfStats.cxx:380
 TPerfStats.cxx:381
 TPerfStats.cxx:382
 TPerfStats.cxx:383
 TPerfStats.cxx:384
 TPerfStats.cxx:385
 TPerfStats.cxx:386
 TPerfStats.cxx:387
 TPerfStats.cxx:388
 TPerfStats.cxx:389
 TPerfStats.cxx:390
 TPerfStats.cxx:391
 TPerfStats.cxx:392
 TPerfStats.cxx:393
 TPerfStats.cxx:394
 TPerfStats.cxx:395
 TPerfStats.cxx:396
 TPerfStats.cxx:397
 TPerfStats.cxx:398
 TPerfStats.cxx:399
 TPerfStats.cxx:400
 TPerfStats.cxx:401
 TPerfStats.cxx:402
 TPerfStats.cxx:403
 TPerfStats.cxx:404
 TPerfStats.cxx:405
 TPerfStats.cxx:406
 TPerfStats.cxx:407
 TPerfStats.cxx:408
 TPerfStats.cxx:409
 TPerfStats.cxx:410
 TPerfStats.cxx:411
 TPerfStats.cxx:412
 TPerfStats.cxx:413
 TPerfStats.cxx:414
 TPerfStats.cxx:415
 TPerfStats.cxx:416
 TPerfStats.cxx:417
 TPerfStats.cxx:418
 TPerfStats.cxx:419
 TPerfStats.cxx:420
 TPerfStats.cxx:421
 TPerfStats.cxx:422
 TPerfStats.cxx:423
 TPerfStats.cxx:424
 TPerfStats.cxx:425
 TPerfStats.cxx:426
 TPerfStats.cxx:427
 TPerfStats.cxx:428
 TPerfStats.cxx:429
 TPerfStats.cxx:430
 TPerfStats.cxx:431
 TPerfStats.cxx:432
 TPerfStats.cxx:433
 TPerfStats.cxx:434
 TPerfStats.cxx:435
 TPerfStats.cxx:436
 TPerfStats.cxx:437
 TPerfStats.cxx:438
 TPerfStats.cxx:439
 TPerfStats.cxx:440
 TPerfStats.cxx:441
 TPerfStats.cxx:442
 TPerfStats.cxx:443
 TPerfStats.cxx:444
 TPerfStats.cxx:445
 TPerfStats.cxx:446
 TPerfStats.cxx:447
 TPerfStats.cxx:448
 TPerfStats.cxx:449
 TPerfStats.cxx:450
 TPerfStats.cxx:451
 TPerfStats.cxx:452
 TPerfStats.cxx:453
 TPerfStats.cxx:454
 TPerfStats.cxx:455
 TPerfStats.cxx:456
 TPerfStats.cxx:457
 TPerfStats.cxx:458
 TPerfStats.cxx:459
 TPerfStats.cxx:460
 TPerfStats.cxx:461
 TPerfStats.cxx:462
 TPerfStats.cxx:463
 TPerfStats.cxx:464
 TPerfStats.cxx:465
 TPerfStats.cxx:466
 TPerfStats.cxx:467
 TPerfStats.cxx:468
 TPerfStats.cxx:469
 TPerfStats.cxx:470
 TPerfStats.cxx:471
 TPerfStats.cxx:472
 TPerfStats.cxx:473
 TPerfStats.cxx:474
 TPerfStats.cxx:475
 TPerfStats.cxx:476
 TPerfStats.cxx:477
 TPerfStats.cxx:478
 TPerfStats.cxx:479
 TPerfStats.cxx:480
 TPerfStats.cxx:481
 TPerfStats.cxx:482
 TPerfStats.cxx:483
 TPerfStats.cxx:484
 TPerfStats.cxx:485
 TPerfStats.cxx:486
 TPerfStats.cxx:487
 TPerfStats.cxx:488
 TPerfStats.cxx:489
 TPerfStats.cxx:490
 TPerfStats.cxx:491
 TPerfStats.cxx:492
 TPerfStats.cxx:493
 TPerfStats.cxx:494
 TPerfStats.cxx:495
 TPerfStats.cxx:496
 TPerfStats.cxx:497
 TPerfStats.cxx:498
 TPerfStats.cxx:499
 TPerfStats.cxx:500
 TPerfStats.cxx:501
 TPerfStats.cxx:502
 TPerfStats.cxx:503
 TPerfStats.cxx:504
 TPerfStats.cxx:505
 TPerfStats.cxx:506
 TPerfStats.cxx:507
 TPerfStats.cxx:508
 TPerfStats.cxx:509
 TPerfStats.cxx:510
 TPerfStats.cxx:511
 TPerfStats.cxx:512
 TPerfStats.cxx:513
 TPerfStats.cxx:514
 TPerfStats.cxx:515
 TPerfStats.cxx:516
 TPerfStats.cxx:517
 TPerfStats.cxx:518
 TPerfStats.cxx:519
 TPerfStats.cxx:520
 TPerfStats.cxx:521
 TPerfStats.cxx:522
 TPerfStats.cxx:523
 TPerfStats.cxx:524
 TPerfStats.cxx:525
 TPerfStats.cxx:526
 TPerfStats.cxx:527
 TPerfStats.cxx:528
 TPerfStats.cxx:529
 TPerfStats.cxx:530
 TPerfStats.cxx:531
 TPerfStats.cxx:532
 TPerfStats.cxx:533
 TPerfStats.cxx:534
 TPerfStats.cxx:535
 TPerfStats.cxx:536
 TPerfStats.cxx:537
 TPerfStats.cxx:538
 TPerfStats.cxx:539
 TPerfStats.cxx:540
 TPerfStats.cxx:541
 TPerfStats.cxx:542
 TPerfStats.cxx:543
 TPerfStats.cxx:544
 TPerfStats.cxx:545
 TPerfStats.cxx:546
 TPerfStats.cxx:547
 TPerfStats.cxx:548
 TPerfStats.cxx:549
 TPerfStats.cxx:550
 TPerfStats.cxx:551
 TPerfStats.cxx:552
 TPerfStats.cxx:553
 TPerfStats.cxx:554
 TPerfStats.cxx:555
 TPerfStats.cxx:556
 TPerfStats.cxx:557
 TPerfStats.cxx:558
 TPerfStats.cxx:559
 TPerfStats.cxx:560
 TPerfStats.cxx:561
 TPerfStats.cxx:562
 TPerfStats.cxx:563
 TPerfStats.cxx:564
 TPerfStats.cxx:565
 TPerfStats.cxx:566
 TPerfStats.cxx:567
 TPerfStats.cxx:568
 TPerfStats.cxx:569
 TPerfStats.cxx:570
 TPerfStats.cxx:571
 TPerfStats.cxx:572
 TPerfStats.cxx:573
 TPerfStats.cxx:574
 TPerfStats.cxx:575
 TPerfStats.cxx:576
 TPerfStats.cxx:577
 TPerfStats.cxx:578
 TPerfStats.cxx:579
 TPerfStats.cxx:580
 TPerfStats.cxx:581
 TPerfStats.cxx:582
 TPerfStats.cxx:583
 TPerfStats.cxx:584
 TPerfStats.cxx:585
 TPerfStats.cxx:586
 TPerfStats.cxx:587
 TPerfStats.cxx:588
 TPerfStats.cxx:589
 TPerfStats.cxx:590
 TPerfStats.cxx:591
 TPerfStats.cxx:592
 TPerfStats.cxx:593
 TPerfStats.cxx:594
 TPerfStats.cxx:595
 TPerfStats.cxx:596
 TPerfStats.cxx:597
 TPerfStats.cxx:598
 TPerfStats.cxx:599
 TPerfStats.cxx:600
 TPerfStats.cxx:601
 TPerfStats.cxx:602
 TPerfStats.cxx:603
 TPerfStats.cxx:604
 TPerfStats.cxx:605
 TPerfStats.cxx:606
 TPerfStats.cxx:607
 TPerfStats.cxx:608
 TPerfStats.cxx:609
 TPerfStats.cxx:610
 TPerfStats.cxx:611
 TPerfStats.cxx:612
 TPerfStats.cxx:613
 TPerfStats.cxx:614
 TPerfStats.cxx:615
 TPerfStats.cxx:616
 TPerfStats.cxx:617
 TPerfStats.cxx:618
 TPerfStats.cxx:619
 TPerfStats.cxx:620
 TPerfStats.cxx:621
 TPerfStats.cxx:622
 TPerfStats.cxx:623
 TPerfStats.cxx:624
 TPerfStats.cxx:625
 TPerfStats.cxx:626
 TPerfStats.cxx:627
 TPerfStats.cxx:628
 TPerfStats.cxx:629
 TPerfStats.cxx:630
 TPerfStats.cxx:631
 TPerfStats.cxx:632
 TPerfStats.cxx:633
 TPerfStats.cxx:634
 TPerfStats.cxx:635
 TPerfStats.cxx:636
 TPerfStats.cxx:637
 TPerfStats.cxx:638
 TPerfStats.cxx:639
 TPerfStats.cxx:640
 TPerfStats.cxx:641
 TPerfStats.cxx:642
 TPerfStats.cxx:643
 TPerfStats.cxx:644
 TPerfStats.cxx:645
 TPerfStats.cxx:646
 TPerfStats.cxx:647
 TPerfStats.cxx:648
 TPerfStats.cxx:649
 TPerfStats.cxx:650
 TPerfStats.cxx:651
 TPerfStats.cxx:652
 TPerfStats.cxx:653
 TPerfStats.cxx:654
 TPerfStats.cxx:655
 TPerfStats.cxx:656
 TPerfStats.cxx:657
 TPerfStats.cxx:658
 TPerfStats.cxx:659
 TPerfStats.cxx:660
 TPerfStats.cxx:661
 TPerfStats.cxx:662
 TPerfStats.cxx:663
 TPerfStats.cxx:664
 TPerfStats.cxx:665
 TPerfStats.cxx:666
 TPerfStats.cxx:667
 TPerfStats.cxx:668
 TPerfStats.cxx:669
 TPerfStats.cxx:670
 TPerfStats.cxx:671
 TPerfStats.cxx:672
 TPerfStats.cxx:673
 TPerfStats.cxx:674
 TPerfStats.cxx:675
 TPerfStats.cxx:676
 TPerfStats.cxx:677
 TPerfStats.cxx:678
 TPerfStats.cxx:679
 TPerfStats.cxx:680
 TPerfStats.cxx:681
 TPerfStats.cxx:682
 TPerfStats.cxx:683
 TPerfStats.cxx:684
 TPerfStats.cxx:685
 TPerfStats.cxx:686
 TPerfStats.cxx:687
 TPerfStats.cxx:688
 TPerfStats.cxx:689
 TPerfStats.cxx:690
 TPerfStats.cxx:691
 TPerfStats.cxx:692
 TPerfStats.cxx:693
 TPerfStats.cxx:694
 TPerfStats.cxx:695
 TPerfStats.cxx:696
 TPerfStats.cxx:697
 TPerfStats.cxx:698
 TPerfStats.cxx:699
 TPerfStats.cxx:700
 TPerfStats.cxx:701
 TPerfStats.cxx:702
 TPerfStats.cxx:703
 TPerfStats.cxx:704
 TPerfStats.cxx:705
 TPerfStats.cxx:706
 TPerfStats.cxx:707
 TPerfStats.cxx:708
 TPerfStats.cxx:709
 TPerfStats.cxx:710
 TPerfStats.cxx:711
 TPerfStats.cxx:712
 TPerfStats.cxx:713
 TPerfStats.cxx:714
 TPerfStats.cxx:715
 TPerfStats.cxx:716
 TPerfStats.cxx:717
 TPerfStats.cxx:718
 TPerfStats.cxx:719
 TPerfStats.cxx:720
 TPerfStats.cxx:721
 TPerfStats.cxx:722
 TPerfStats.cxx:723
 TPerfStats.cxx:724
 TPerfStats.cxx:725
 TPerfStats.cxx:726
 TPerfStats.cxx:727
 TPerfStats.cxx:728
 TPerfStats.cxx:729
 TPerfStats.cxx:730
 TPerfStats.cxx:731
 TPerfStats.cxx:732
 TPerfStats.cxx:733
 TPerfStats.cxx:734
 TPerfStats.cxx:735
 TPerfStats.cxx:736
 TPerfStats.cxx:737
 TPerfStats.cxx:738
 TPerfStats.cxx:739
 TPerfStats.cxx:740
 TPerfStats.cxx:741
 TPerfStats.cxx:742
 TPerfStats.cxx:743
 TPerfStats.cxx:744
 TPerfStats.cxx:745
 TPerfStats.cxx:746
 TPerfStats.cxx:747
 TPerfStats.cxx:748
 TPerfStats.cxx:749
 TPerfStats.cxx:750
 TPerfStats.cxx:751
 TPerfStats.cxx:752
 TPerfStats.cxx:753
 TPerfStats.cxx:754
 TPerfStats.cxx:755
 TPerfStats.cxx:756
 TPerfStats.cxx:757
 TPerfStats.cxx:758
 TPerfStats.cxx:759
 TPerfStats.cxx:760
 TPerfStats.cxx:761
 TPerfStats.cxx:762
 TPerfStats.cxx:763
 TPerfStats.cxx:764
 TPerfStats.cxx:765
 TPerfStats.cxx:766
 TPerfStats.cxx:767
 TPerfStats.cxx:768
 TPerfStats.cxx:769
 TPerfStats.cxx:770
 TPerfStats.cxx:771
 TPerfStats.cxx:772
 TPerfStats.cxx:773
 TPerfStats.cxx:774
 TPerfStats.cxx:775