ROOT  6.06/09
Reference Guide
TProofPerfAnalysis.cxx
Go to the documentation of this file.
1 // @(#)root/proofx:$Id$
2 // Author: G.Ganis Nov 2011
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 //////////////////////////////////////////////////////////////////////////
13 // //
14 // TProofPerfAnalysis //
15 // //
16 // Set of tools to analyse the performance tree //
17 // //
18 //////////////////////////////////////////////////////////////////////////
19 #include <errno.h>
20 
21 #include "TProofPerfAnalysis.h"
22 #include "TCanvas.h"
23 #include "TFile.h"
24 #include "TGraph.h"
25 #include "TH1F.h"
26 #include "TH2F.h"
27 #include "THashList.h"
28 #include "TKey.h"
29 #include "TList.h"
30 #include "TSortedList.h"
31 #include "TPerfStats.h"
32 #include "TRegexp.h"
33 #include "TStyle.h"
34 #include "TSystem.h"
35 #include "TTree.h"
36 #include "TMath.h"
37 
38 //
39 // Auxilliary internal classes
40 ////////////////////////////////////////////////////////////////////////////////
41 
42 class TProofPerfAnalysis::TWrkInfo : public TNamed {
43 public:
44  TWrkInfo(const char *ord, const char *name) :
45  TNamed(ord, name), fPackets(0), fRemotePackets(0), fEventsProcessed(0),
46  fBytesRead(0), fLatency(0), fProcTime(0), fCpuTime(0), fStart(0), fStop(-1),
47  fRateT(0), fRateRemoteT(0), fMBRateT(0), fMBRateRemoteT(0), fLatencyT(0) { }
48  virtual ~TWrkInfo() { SafeDelete(fRateT); SafeDelete(fRateRemoteT);
49  SafeDelete(fMBRateT); SafeDelete(fMBRateRemoteT);
50  SafeDelete(fLatencyT); }
51 
52  Int_t fPackets; // Number of packets processed
53  Int_t fRemotePackets; // Number of processed packet from non-local files
54  Long64_t fEventsProcessed; // Tot events processed
55  Long64_t fBytesRead; // Tot bytes read
56  Double_t fLatency; // Tot latency
57  Double_t fProcTime; // Tot proc time
58  Double_t fCpuTime; // Tot CPU time
59 
60  Float_t fStart; // Start time
61  Float_t fStop; // Stop time
62 
63  TGraph *fRateT; // Event processing rate vs time
64  TGraph *fRateRemoteT; // Event processing rate of remote packets vs time
65  TGraph *fMBRateT; // Byte processing rate vs time
66  TGraph *fMBRateRemoteT; // Byte processing rate of remote packets vs time
67  TGraph *fLatencyT; // Packet latency vs time
68 
69  Double_t AvgRate() { if (fProcTime > 0) return (fEventsProcessed/fProcTime); return -1.; }
70  Double_t AvgIO() { if (fProcTime > 0) return (fBytesRead/fProcTime); return -1.; }
71 
72  void Print(Option_t * = "") const {
73  Printf(" +++ TWrkInfo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
74  Printf(" +++ Worker: %s, %s", GetName(), GetTitle());
75  Printf(" +++ Activity interval: %f -> %f", fStart, fStop);
76  Printf(" +++ Amounts processed: %d packets (%d remote), %lld evts, %lld bytes",
77  fPackets, fRemotePackets, fEventsProcessed, fBytesRead);
78  if (fProcTime) {
79  Printf(" +++ Processing time: %f s (CPU: %f s)", fProcTime, fCpuTime);
80  Printf(" +++ Averages: %f evts/s, %f MB/s", (Double_t)fEventsProcessed / fProcTime, (Double_t)fBytesRead /1024./1024./fProcTime);
81  }
82  Printf(" +++ Total latency: %f", fLatency);
83  Printf(" +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
84  }
85 
86  Int_t Compare(const TObject *o) const { TWrkInfo *wi = (TWrkInfo *)o;
87  if (wi) {
88  if (fStop < wi->fStop) {
89  return -1;
90  } else if (fStop == wi->fStop) {
91  return 0;
92  }
93  }
94  return 1; }
95 };
96 
97 
98 class TProofPerfAnalysis::TPackInfo : public TNamed {
99 public:
100  TPackInfo(const char *ord, const char *host) : TNamed(ord, host), fStart(0), fStop(-1), fSize(0), fMBRate(0.) { }
101  TPackInfo(const char *ord, const char *host, Float_t start, Float_t stop, Long64_t sz, Double_t mbr)
102  : TNamed(ord, host), fStart(start), fStop(stop), fSize(sz), fMBRate(mbr) { }
103  Float_t fStart; // When the packet has been assigned
104  Float_t fStop; // When the packet has been finished
105  Long64_t fSize; // Packet size
106  Double_t fMBRate; // Processing rate MB/s
107  void Print(Option_t *opt= "") const {
108  if (!strcmp(opt, "S")) {
109  Printf(" \t%10lld evts, \t%12.2f MB/s, \t%12.3f -> %12.3f s", fSize, fMBRate, fStart, fStop);
110  } else {
111  Printf(" %s:\t%s \t%10lld evts, \t%12.2f MB/s, \t%12.3f -> %12.3f s", GetTitle(), GetName(), fSize, fMBRate, fStart, fStop);
112  }
113  }
114 };
115 
116 class TProofPerfAnalysis::TWrkInfoFile : public TNamed {
117 public:
118  TWrkInfoFile(const char *ord, const char *name) : TNamed(ord, name) { }
119  ~TWrkInfoFile() {fPackets.SetOwner(kFALSE); fPackets.Clear("nodelete");}
120  TList fPackets; // Packest from this file processed by this worker
121  void Print(Option_t *opt= "") const {
122  if (!strcmp(opt, "R")) {
123  Printf(" Worker: %s,\tpacket(s): %d", GetName(), fPackets.GetSize());
124  } else {
125  Printf(" Worker: %s,\t%d packet(s) from file: %s", GetName(), fPackets.GetSize(), GetTitle());
126  }
127  TIter nxp(&fPackets);
128  TObject *o = 0;
129  while ((o = nxp())) { o->Print("S"); }
130  }
131 };
132 
133 class TProofPerfAnalysis::TWrkEntry : public TObject {
134 public:
135  TWrkEntry(Double_t xx, Double_t er, Double_t mbr, Double_t pt) : fXx(xx), fEvtRate(er), fMBRate(mbr), fProcTime(pt) { }
136  Double_t fXx; // Bin center
137  Double_t fEvtRate; // Event processing rate from this worker for this packet
138  Double_t fMBRate; // I/O processing rate from this worker for this packet
139  Double_t fProcTime; // Processing time
140  void Print(Option_t * = "") const { Printf("%.4f \t%.3f evt/s \t%.3f MB/s \t%.3f s ", fXx, fEvtRate, fMBRate, fProcTime); }
141 };
142 
143 ////////////////////////////////////////////////////////////////////////////////
144 
145 class TProofPerfAnalysis::TFileInfo : public TNamed {
146 public:
147  TFileInfo(const char *name, const char *srv) :
148  TNamed(name, srv), fPackets(0), fRPackets(0), fStart(0), fStop(-1),
149  fSizeAvg(0), fSizeMax(-1.), fSizeMin(-1.),
150  fMBRateAvg(0), fMBRateMax(-1.), fMBRateMin(-1.), fSizeP(0),
151  fRateP(0), fRatePRemote(0), fMBRateP(0), fMBRatePRemote(0) { }
152  virtual ~TFileInfo() {SafeDelete(fSizeP);
153  SafeDelete(fRateP); SafeDelete(fRatePRemote);
154  SafeDelete(fMBRateP); SafeDelete(fMBRatePRemote);
155  fPackList.SetOwner(kTRUE); fPackList.Clear();
156  fWrkList.SetOwner(kTRUE); fWrkList.Clear();
157  fRWrkList.SetOwner(kTRUE); fRWrkList.Clear();}
158 
159  Int_t fPackets; // Number of packets from this file
160  Int_t fRPackets; // Number of different remote workers processing this file
161 
162  TList fPackList; // List of packet info
163  TList fWrkList; // List of worker names processing this packet
164  TList fRWrkList; // List of remote worker names processing this packet
165 
166  Float_t fStart; // When the first packet has been assigned
167  Float_t fStop; // When the last packet has been finished
168 
169  Long64_t fSizeAvg; // Average Packet size
170  Long64_t fSizeMax; // Max packet size
171  Long64_t fSizeMin; // Min packet size
172 
173  Double_t fMBRateAvg; // Average MB rate
174  Double_t fMBRateMax; // Max MB rate
175  Double_t fMBRateMin; // Min MB rate
176 
177  TGraph *fSizeP; // Packet size vs packet (all)
178  TGraph *fRateP; // Event processing rate vs packet (all)
179  TGraph *fRatePRemote; // Event processing rate vs packet (remote workers)
180  TGraph *fMBRateP; // Byte processing rate vs packet (all)
181  TGraph *fMBRatePRemote; // Byte processing rate vs packet (remote workers)
182 
183  void Print(Option_t *opt = "") const {
184  Printf(" +++ TFileInfo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
185  Printf(" +++ Server: %s", GetTitle());
186  Printf(" +++ File: %s", GetName());
187  Printf(" +++ Processing interval: %f -> %f", fStart, fStop);
188  Printf(" +++ Packets: %d (%d remote)", fPackets, fRPackets);
189  Printf(" +++ Processing wrks: %d (%d remote)", fWrkList.GetSize(), fRWrkList.GetSize());
190  if (!strcmp(opt, "P")) fPackList.Print();
191  if (!strcmp(opt, "WP")) fWrkList.Print("R");
192  if (fPackets > 0) {
193  Printf(" +++ MB rates: %f MB/s (avg), %f MB/s (min), %f MB/s (max)",
194  fMBRateAvg / fPackets, fMBRateMin, fMBRateMax);
195  Printf(" +++ Sizes: %lld (avg), %lld (min), %lld (max)",
196  fSizeAvg / fPackets, fSizeMin, fSizeMax);
197  }
198  Printf(" +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
199  }
200 
201  Int_t Compare(const TObject *o) const { TFileInfo *wi = (TFileInfo *)o;
202  if (wi) {
203  if (fStop < wi->fStop) {
204  return -1;
205  } else if (fStop == wi->fStop) {
206  return 0;
207  }
208  }
209  return 1; }
210 };
211 
212 Bool_t TProofPerfAnalysis::fgDebug = kTRUE;
213 ////////////////////////////////////////////////////////////////////////////////
214 /// Constructor: open the file and attach to the tree
215 
217  const char *title, const char *treename)
218  : TNamed(perffile, title), fFile(0), fTreeName(treename), fTree(0),
219  fInitTime(-1.), fMergeTime(-1.), fMaxTime(-1.),
220  fEvents(0), fPackets(0),
221  fEvtRateMax(-1.), fMBRateMax(-1.), fLatencyMax(-1.),
222  fEvtRate(0), fEvtRateRun(0), fMBRate(0), fMBRateRun(0),
223  fEvtRateAvgMax(-1.), fMBRateAvgMax(-1.),
224  fEvtRateAvg(-1.), fMBRateAvg(0),
225  fFileResult(""), fSaveResult(kFALSE),
226  fDebug(0)
227 {
228  // Use default title, if not specified
229  if (!title) SetTitle("PROOF Performance Analysis");
230 
231  fTree = 0;
232  fFile = TFile::Open(perffile);
233  if (!fFile || (fFile && fFile->IsZombie())) {
234  SafeDelete(fFile);
235  Error("TProofPerfAnalysis", "problems opening file '%s'",
236  perffile ? perffile : "<undef>");
238  return;
239  }
240 
241  // Set the subdirectory name, if any
242  if (fTreeName.Contains("/")) {
245  }
246 
247  // Adjust the name, if requested
248  if (fTreeName.BeginsWith("+"))
249  fTreeName.Replace(0, 1, "PROOF_PerfStats");
250 
251  // Point to the right TDirectory
252  TDirectory *dir = fFile;
253  if (!fDirName.IsNull()) {
254  if (!(dir = dynamic_cast<TDirectory *>(fFile->Get(fDirName)))) {
255  Error("TProofPerfAnalysis", "directory '%s' not found or not loadable", fDirName.Data());
256  fFile->Close();
257  SafeDelete(fFile);
259  return;
260  }
261  }
262 
263  // Load the performance tree
264  LoadTree(dir);
265  if (!fTree) {
266  Error("TProofPerfAnalysis", "tree '%s' not found or not loadable", fTreeName.Data());
267  fFile->Close();
268  SafeDelete(fFile);
270  return;
271  }
272  if (fgDebug)
273  Printf(" +++ TTree '%s' has %lld entries", fTreeName.Data(), fTree->GetEntries());
274 
275  // Init worker information
276  FillWrkInfo();
277 
278  // Init file information
279  FillFileInfo();
280 
281  // Done
282  return;
283 }
284 
285 ////////////////////////////////////////////////////////////////////////////////
286 /// Constructor: open the file and attach to the tree
287 
289  : TNamed("", title), fFile(0), fTree(0),
290  fInitTime(-1.), fMergeTime(-1.), fMaxTime(-1.),
291  fEvents(0), fPackets(0),
292  fEvtRateMax(-1.), fMBRateMax(-1.), fLatencyMax(-1.),
293  fEvtRate(0), fEvtRateRun(0), fMBRate(0), fMBRateRun(0),
294  fEvtRateAvgMax(-1.), fMBRateAvgMax(-1.),
295  fEvtRateAvg(-1.), fMBRateAvg(0),
296  fDebug(0)
297 {
298  // The tree must be defined
299  if (!tree) {
301  return;
302  }
303 
304  // Use default title, if not specified
305  if (!title) SetTitle("PROOF Performance Analysis");
306 
307  fTree = tree;
308  fTreeName = fTree->GetName();
309  SetName(TString::Format("heap_%s", fTreeName.Data()));
310 
311  // Adjust the name, if requested
312  if (fTreeName.BeginsWith("+"))
313  fTreeName.Replace(0, 1, "PROOF_PerfStats");
314 
315  if (fgDebug)
316  Printf(" +++ TTree '%s' has %lld entries", fTreeName.Data(), fTree->GetEntries());
317 
318  // Init worker information
319  FillWrkInfo();
320 
321  // Init file information
322  FillFileInfo();
323 
324  // Done
325  return;
326 }
327 
328 ////////////////////////////////////////////////////////////////////////////////
329 /// Destructor: detach the tree and close the file
330 
332 {
334  SafeDelete(fPackets);
335  if (fFile) fFile->Close();
336  SafeDelete(fFile);
337 }
338 
339 ////////////////////////////////////////////////////////////////////////////////
340 /// If defined, add '- <this title>' to the canvas title 't'
341 
343 {
344  if (fTitle.IsNull()) return TString(t);
345 
346  TString newt;
347  if (t && strlen(t) > 0) {
348  newt.Form("%s - %s", t, GetTitle());
349  } else {
350  newt = GetTitle();
351  }
352  // Done
353  return newt;
354 }
355 
356 ////////////////////////////////////////////////////////////////////////////////
357 /// Load tree fTreeName from directory 'dir'. If not found, look for the
358 /// first TTree in the directory (and sub-directories) with the name containing
359 /// fTreeName.
360 /// The tree pointer is saved in fTree.
361 
363 {
364  fTree = 0;
365  if (!dir) return;
366 
367  // Try first the full name in the top directory
368  if ((fTree = dynamic_cast<TTree *>(dir->Get(fTreeName)))) return;
369 
370  TRegexp re(fTreeName);
371  // Now look inside: iter on the list of keys first
372  TIter nxk(dir->GetListOfKeys());
373  TKey *k = 0;
374  while ((k = (TKey *) nxk())) {
375  if (!strcmp(k->GetClassName(), "TDirectoryFile")) {
376  TDirectory *kdir = (TDirectory *) dir->Get(k->GetName());
377  LoadTree(kdir);
378  if (fTree) return;
379  } else if (!strcmp(k->GetClassName(), "TTree")) {
380  TString tn(k->GetName());
381  if (tn.Index(re) != kNPOS) {
382  if ((fTree = dynamic_cast<TTree *>(dir->Get(tn)))) {
383  fTreeName = tn;
384  if (fgDebug) Printf(" +++ Found and loaded TTree '%s'", tn.Data());
385  return;
386  }
387  }
388  }
389  }
390 
391  // Nothing found
392  return;
393 }
394 
395 ////////////////////////////////////////////////////////////////////////////////
396 /// Analyse the file distribution. If writedet, underling details are
397 /// written out to a text file.
398 
400 {
401  if (!IsValid()) {
402  Error("FileDist","not a valid instance - do nothing");
403  return;
404  }
405 
406  // Fill file info
407  TList *wrkList = new TList;
408  TList *srvList = new TList;
409  GetWrkFileList(wrkList, srvList);
410  Info("FileDist", "%d workers were active during this query", wrkList->GetSize());
411  Info("FileDist", "%d servers were active during this query", srvList->GetSize());
412 
413  // Fill the worker-data server mapping
414  TIter nxs(srvList);
415  TIter nxw(wrkList);
416  TNamed *sn = 0, *wn = 0;
417  while ((sn = (TNamed *)nxs())) {
418  nxw.Reset();
419  while ((wn = (TNamed *) nxw())) {
420  if (!strcmp(TUrl(sn->GetName()).GetHostFQDN(), wn->GetTitle())) {
421  sn->SetTitle(wn->GetName());
422  }
423  }
424  }
425 
426  // Reorder the lists following the title
427  TList *nwl = new TList;
428  TList *nsl = new TList;
429  nxw.Reset();
430  while ((wn = (TNamed *) nxw())) {
431  TIter nnxw(nwl);
432  TNamed *nwn = 0;
433  while ((nwn = (TNamed *) nnxw())) {
434  if (CompareOrd(wn->GetName(), nwn->GetName()) < 0) {
435  nwl->AddBefore(nwn, wn);
436  break;
437  }
438  }
439  if (!nwn) nwl->Add(wn);
440  // Find the server name, if any
441  nxs.Reset();
442  while ((sn = (TNamed *)nxs())) {
443  if (!strcmp(sn->GetTitle(), wn->GetName())) {
444  TIter nnxs(nsl);
445  TNamed *nsn = 0;
446  while ((nsn = (TNamed *) nnxs())) {
447  if (CompareOrd(sn->GetTitle(), nsn->GetTitle()) < 0) {
448  nsl->AddBefore(nsn, sn);
449  break;
450  }
451  }
452  if (!nsn) nsl->Add(sn);
453  break;
454  }
455  }
456  if (sn) srvList->Remove(sn);
457  }
458  // Add remaining servers at the end
459  nxs.Reset();
460  while ((sn = (TNamed *)nxs())) {
461  nsl->Add(sn);
462  }
463  // Clean the orginal lists
464  wrkList->SetOwner(kFALSE);
465  srvList->SetOwner(kFALSE);
466  delete wrkList;
467  delete srvList;
468  wrkList = nwl;
469  srvList = nsl;
470 
471  // Notify
472  wrkList->ls();
473  srvList->ls();
474 
475  // Separate out the case with only one file server
476  if (srvList->GetSize() == 1) {
477 
478  Printf("\n +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ");
479  Printf(" + Only one data server found: full analysis meaningful + ");
480  Printf(" + only when there are more file servers + ");
481  Printf(" +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ \n");
482 
483 
484  // Create a 1D histo for cross packets
485  TH1F *hxpak = new TH1F("hxpak", "MBytes / Worker",
486  wrkList->GetSize(), 0., (Double_t)wrkList->GetSize());
487  hxpak->SetDirectory(0);
488  hxpak->SetMinimum(0.);
489  hxpak->GetXaxis()->SetTitle("Worker");
490 
491  // Set the labels
492  Int_t j = 1;
493  TIter nxsw(wrkList);
494  while ((wn = (TNamed *)nxsw())) {
495  hxpak->GetXaxis()->SetBinLabel(j++, wn->GetName());
496  }
497 
498  // Fill the histograms
499  FillFileDistOneSrv(hxpak, writedet);
500 
501  // Display histos
502  gStyle->SetOptStat(0);
503 
504  TCanvas *c2 = new TCanvas("cv-hxpak", GetCanvasTitle(hxpak->GetTitle()), 800,350,700,700);
505  c2->cd();
506  DoDraw(hxpak);
507  c2->Update();
508 
509  } else {
510  // Create a 1D histo for file distribution
511  TH1F *hfdis = new TH1F("hfdis", "Packet dist",
512  srvList->GetSize(), 0., (Double_t)srvList->GetSize());
513  hfdis->SetDirectory(0);
514  hfdis->SetMinimum(0);
515  hfdis->GetXaxis()->SetTitle("Server");
516  TH1F *hbdis = new TH1F("hbdis", "MBytes dist",
517  srvList->GetSize(), 0., (Double_t)srvList->GetSize());
518  hbdis->SetDirectory(0);
519  hbdis->SetMinimum(0);
520  hbdis->GetXaxis()->SetTitle("Server");
521  // Create a 2D histo for cross packets
522  TH2F *hxpak = new TH2F("hxpak", "MBytes / {Worker,Server}",
523  srvList->GetSize(), 0., (Double_t)srvList->GetSize(),
524  wrkList->GetSize(), 0., (Double_t)wrkList->GetSize());
525  hxpak->SetDirectory(0);
526  hxpak->GetYaxis()->SetTitle("Worker");
527  hxpak->GetXaxis()->SetTitle("Server");
528  hxpak->GetXaxis()->SetTitleOffset(1.4);
529  hxpak->GetYaxis()->SetTitleOffset(1.7);
530 
531  // Set the labels
532  Int_t j = 1;
533  TIter nxsw(wrkList);
534  while ((wn = (TNamed *)nxsw())) {
535  hxpak->GetYaxis()->SetBinLabel(j++, wn->GetName());
536  }
537  j = 1;
538  TIter nxss(srvList);
539  while ((sn = (TNamed *)nxss())) {
540  hfdis->GetXaxis()->SetBinLabel(j, sn->GetName());
541  hbdis->GetXaxis()->SetBinLabel(j, sn->GetName());
542  hxpak->GetXaxis()->SetBinLabel(j++, sn->GetName());
543  }
544 
545  // Fill the histograms
546  FillFileDist(hfdis, hbdis, hxpak, writedet);
547 
548  j = 1;
549  nxss.Reset();
550  while ((sn = (TNamed *)nxss())) {
551  TString lab(sn->GetName());
552  lab = TUrl(sn->GetName()).GetHost();
553  if (strcmp(sn->GetTitle(), "remote") && lab.Index(".") != kNPOS) lab.Remove(lab.Index("."));
554  hfdis->GetXaxis()->SetBinLabel(j, lab);
555  hbdis->GetXaxis()->SetBinLabel(j, lab);
556  hxpak->GetXaxis()->SetBinLabel(j++, lab);
557  }
558 
559  // Display histos
560  gStyle->SetOptStat(0);
561 
562  TCanvas *c1 = new TCanvas("cv-hfdis", GetCanvasTitle(hfdis->GetTitle()), 800,50,700,700);
563  c1->Divide(1,2);
564  TPad *pad1 = (TPad *) c1->GetPad(1);
565  TPad *pad2 = (TPad *) c1->GetPad(2);
566  pad1->cd();
567  DoDraw(hfdis);
568  pad2->cd();
569  DoDraw(hbdis);
570  c1->Update();
571 
572  TCanvas *c2 = new TCanvas("cv-hxpak", GetCanvasTitle(hxpak->GetTitle()), 500,350,700,700);
573  c2->cd();
574  DoDraw(hxpak, "lego");
575  c2->Update();
576  }
577  // Done
578  return;
579 }
580 
581 ////////////////////////////////////////////////////////////////////////////////
582 /// Fill file info
583 
585 {
586  if (!wl || !sl) return;
587 
588  // Extract information
589  TPerfEvent pe;
590  TPerfEvent* pep = &pe;
591  fTree->SetBranchAddress("PerfEvents", &pep);
592  Long64_t entries = fTree->GetEntries();
593  TNamed *wn = 0, *sn = 0;
594  for (Long64_t k=0; k<entries; k++) {
595  fTree->GetEntry(k);
596  // Analyse only packets
597  if (pe.fType != TVirtualPerfStats::kPacket) continue;
598  // Find out the worker instance
599  TString wrk(TUrl(pe.fSlaveName.Data()).GetHostFQDN());
600  wn = (TNamed *) wl->FindObject(pe.fSlave.Data());
601  if (!wn) {
602  wn = new TNamed(pe.fSlave.Data(), wrk.Data());
603  wl->Add(wn);
604  }
605  // Find out the file server instance
606  TUrl uf(pe.fFileName);
607  TString srv(uf.GetUrl());
608  Int_t ifn = srv.Index(uf.GetFile());
609  if (ifn != kNPOS) srv.Remove(ifn);
610  sn = (TNamed *) sl->FindObject(srv.Data());
611  if (!sn) {
612  sn = new TNamed(srv.Data(), "remote");
613  sl->Add(sn);
614  }
615  }
616 
617  // Done
618  return;
619 }
620 
621 ////////////////////////////////////////////////////////////////////////////////
622 /// Return -1 if ord1 comes before ord2, 0 i they are equal,
623 /// 1 if ord1 comes after ord2
624 
625 Int_t TProofPerfAnalysis::CompareOrd(const char *ord1, const char *ord2)
626 {
627  TString o1(ord1), o2(ord2), p1, p2;
628  Int_t o1d = 0, o2d = 0;
629  if ((o1d = o1.CountChar('.')) > (o2d = o2.CountChar('.'))) {
630  return 1;
631  } else if (o1d < o2d) {
632  return -1;
633  } else {
634  o1.ReplaceAll(".", " ");
635  o2.ReplaceAll(".", " ");
636  Bool_t b1 = o1.Tokenize(p1, o1d, " ");
637  Bool_t b2 = o2.Tokenize(p2, o2d, " ");
638  while (b1 && b2) {
639  if (p1.Atoi() > p2.Atoi()) {
640  return 1;
641  } else if (p1.Atoi() < p2.Atoi()) {
642  return -1;
643  } else {
644  b1 = o1.Tokenize(p1, o1d, " ");
645  b2 = o2.Tokenize(p2, o2d, " ");
646  }
647  }
648  if (b1 && !b2) {
649  return 1;
650  } else if (b2 && !b1) {
651  return -1;
652  } else {
653  return 0;
654  }
655  }
656 }
657 
658 ////////////////////////////////////////////////////////////////////////////////
659 /// Fill file info
660 
662 {
663  if (!hf || !hb || !hx) return;
664 
665  TString fnout;
666  FILE *fout = 0;
667  if (wdet) {
668  fnout.Form("%s-FileDist-Details.txt", GetName());
669  if (!(fout = fopen(fnout.Data(), "w"))) {
670  Warning("FillFileDist", "asked to save details in '%s' but file could"
671  " not be open (errno: %d)", fnout.Data(), (int)errno);
672  } else {
673  Info("FillFileDist", "saving details to '%s'", fnout.Data());
674  }
675  }
676  // Extract information
677  TPerfEvent pe;
678  TPerfEvent* pep = &pe;
679  fTree->SetBranchAddress("PerfEvents",&pep);
680  Long64_t entries = fTree->GetEntries();
681  for (Long64_t k=0; k<entries; k++) {
682  fTree->GetEntry(k);
683  // Analyse only packets
684  if (pe.fType != TVirtualPerfStats::kPacket) continue;
685  // Find out the labels ...
686  TString wrk(pe.fSlave.Data());
687  TUrl uf(pe.fFileName);
688  TString srv(uf.GetUrl());
689  Int_t ifn = srv.Index(uf.GetFile());
690  if (ifn != kNPOS) srv.Remove(ifn);
691  // ... and the bins
692  Double_t xhf = hf->GetXaxis()->GetBinCenter(hf->GetXaxis()->FindBin(srv.Data()));
693  Double_t xhx = hx->GetXaxis()->GetBinCenter(hx->GetXaxis()->FindBin(srv.Data()));
694  Double_t yhx = hx->GetYaxis()->GetBinCenter(hx->GetYaxis()->FindBin(wrk.Data()));
695  // Save details, if asked
696  if (fout)
697  fprintf(fout, "%s,%s -> %f,%f (%f)\n",
698  srv.Data(), wrk.Data(), xhx, yhx, pe.fBytesRead / 1024.);
699  // Fill now
700  hf->Fill(xhf);
701  hb->Fill(xhf, pe.fBytesRead / 1024. / 1024.);
702  hx->Fill(xhx, yhx, pe.fBytesRead / 1024. / 1024.);
703  }
704  if (fout) fclose(fout);
705  // Done
706  return;
707 }
708 
709 ////////////////////////////////////////////////////////////////////////////////
710 /// Fill file info when there is only one file server
711 
713 {
714  if (!hx) return;
715 
716  TString fnout;
717  FILE *fout = 0;
718  if (wdet) {
719  fnout.Form("%s-FileDist-Details.txt", GetName());
720  if (!(fout = fopen(fnout.Data(), "w"))) {
721  Warning("FillFileDistOneSrv", "asked to save details in '%s' but file could"
722  " not be open (errno: %d)", fnout.Data(), (int)errno);
723  } else {
724  Info("FillFileDistOneSrv", "saving details to '%s'", fnout.Data());
725  }
726  }
727  // Extract information
728  TPerfEvent pe;
729  TPerfEvent* pep = &pe;
730  fTree->SetBranchAddress("PerfEvents",&pep);
731  Long64_t entries = fTree->GetEntries();
732  for (Long64_t k=0; k<entries; k++) {
733  fTree->GetEntry(k);
734  // Analyse only packets
735  if (pe.fType != TVirtualPerfStats::kPacket) continue;
736  // Find out the labels ...
737  TString wrk(pe.fSlave.Data());
738  TUrl uf(pe.fFileName);
739  TString srv(uf.GetUrl());
740  Int_t ifn = srv.Index(uf.GetFile());
741  if (ifn != kNPOS) srv.Remove(ifn);
742  // ... and the bins
743  Double_t xhx = hx->GetXaxis()->GetBinCenter(hx->GetXaxis()->FindBin(wrk.Data()));
744  // Save details, if asked
745  if (fout)
746  fprintf(fout, "%s,%s -> %f (%f)\n",
747  srv.Data(), wrk.Data(), xhx, pe.fBytesRead / 1024.);
748  // Fill now
749  hx->Fill(xhx, pe.fBytesRead / 1024. / 1024.);
750  }
751  if (fout) fclose(fout);
752  // Done
753  return;
754 }
755 
756 ////////////////////////////////////////////////////////////////////////////////
757 /// Measure the worker activity
758 
760 {
761  if (!IsValid()) {
762  Error("WorkerActivity","not a valid instance - do nothing");
763  return;
764  }
765 
766  // Fill basic worker info
767  if (!WrkInfoOK()) FillWrkInfo();
768  if (!WrkInfoOK()) {
769  Error("WorkerActivity", "workers information not available - do nothing");
770  return;
771  }
772 
773  TObject *o = 0;
774  // Create the histograms with activity vs time
775  if ((o = gDirectory->FindObject("act10"))) delete o;
776  Float_t t0 = fMergeTime - 2.* (fMaxTime - fMergeTime);
777  Float_t t1 = 2.*fInitTime;
778  if (t1 > t0) t1 = t0;
779  TH1F *hact10 = new TH1F("act10", "Worker activity start (seconds)", 50, 0., t1);
780  hact10->GetXaxis()->SetTitle("Query Processing Time (s)");
781  if ((o = gDirectory->FindObject("act11"))) delete o;
782  TH1F *hact11 = new TH1F("act11", "Worker activity stop (seconds)", 50, t0, fMaxTime);
783  hact11->GetXaxis()->SetTitle("Query Processing Time (s)");
784  if ((o = gDirectory->FindObject("act2"))) delete o;
785  TH1F *hact2 = new TH1F("act2", "End of activity (seconds)", 50, t0, fMaxTime);
786  hact2->GetXaxis()->SetTitle("Query Processing Time (s)");
787 
788  // Fine-tune stat printing
789  Int_t curoptstat = gStyle->GetOptStat();
790  gStyle->SetOptStat(1100);
791 
792  // Create the sorted list
793  TIter nxw(&fWrksInfo);
794  TWrkInfo *wi = 0;
795  while ((wi = (TWrkInfo *)nxw())) {
796  Int_t j = 0;
797  for (j = 1; j < hact10->GetNbinsX()+1 ; j++) {
798  if (wi->fStart < hact10->GetBinLowEdge(j))
799  hact10->Fill(hact10->GetBinCenter(j));
800  }
801  for (j = 1; j < hact11->GetNbinsX()+1 ; j++) {
802  if (wi->fStop > hact11->GetBinLowEdge(j))
803  hact11->Fill(hact11->GetBinCenter(j));
804  }
805  hact2->Fill(wi->fStop);
806  }
807 
808  // Display histos
809  TCanvas *c1 = new TCanvas("perf", GetCanvasTitle("Activity histos"), 800,10,700,780);
810  c1->Divide(1,2);
811  TPad *pad1 = (TPad *) c1->GetPad(1);
812  pad1->Divide(2,1);
813  TPad *pad10 = (TPad *) pad1->GetPad(1);
814  TPad *pad11 = (TPad *) pad1->GetPad(2);
815  pad10->cd();
816  DoDraw(hact10);
817  pad11->cd();
818  DoDraw(hact11);
819  TPad *pad2 = (TPad *) c1->GetPad(2);
820  pad2->cd();
821  DoDraw(hact2);
822  c1->cd();
823  c1->Update();
824 
825  // Restore stat options
826  gStyle->SetOptStat(curoptstat);
827 
828  // Done
829  return;
830 }
831 
832 ////////////////////////////////////////////////////////////////////////////////
833 /// Print information for all or the slowest showlast workers.
834 /// Use showlast < 0 to print all
835 
837 {
838  // Create the sorted list
839  Int_t k = fWrksInfo.GetSize();
840  TIter nxw(&fWrksInfo);
841  TWrkInfo *wi = 0;
842  while ((wi = (TWrkInfo *)nxw())) {
843  // Print info about slowest workers
844  k--;
845  if (showlast < 0 || k < showlast) wi->Print();
846  }
847 }
848 
849 ////////////////////////////////////////////////////////////////////////////////
850 /// Print information for worker 'wn' (ordinal) or on the machine whose
851 /// ordinal or fqdn matches 'wn'. Multiple specifications separated by ','
852 /// or ' ' are supported, as well as wildcards '*', e.g. '0.2*,lxb10* lxf2323.doma.in"
853 
855 {
856  if (!wn || (wn && strlen(wn) <= 0)) {
857  Error("PrintWrkInfo", "worker name or host must be defined!");
858  return;
859  }
860 
861  // Check exact name
862  TWrkInfo *wi = (TWrkInfo *) fWrksInfo.FindObject(wn);
863  if (wi) {
864  wi->Print();
865  } else {
866  // Check matching
867  TString ww(wn), w;
868  TIter nxw(&fWrksInfo);
869  while ((wi = (TWrkInfo *)nxw())) {
870  TString n(wi->GetName()), t(wi->GetTitle());
871  Ssiz_t from = 0;
872  while (ww.Tokenize(w, from, "[, ]")) {
873  TRegexp re(w, kTRUE);
874  if (n.Index(re) != kNPOS || t.Index(re) != kNPOS) wi->Print();
875  }
876  }
877  }
878 }
879 
880 ////////////////////////////////////////////////////////////////////////////////
881 /// Print information for all or the slowest showlast workers.
882 /// Use showlast < 0 to print all
883 
884 void TProofPerfAnalysis::PrintFileInfo(Int_t showlast, const char *opt, const char *out)
885 {
886  RedirectHandle_t rh;
887  if (out && strlen(out) > 0) gSystem->RedirectOutput(out, "w", &rh);
888 
889  // Create the sorted list
890  Int_t k = fFilesInfo.GetSize();
891  TIter nxf(&fFilesInfo);
892  TFileInfo *fi = 0;
893  while ((fi = (TFileInfo *)nxf())) {
894  // Print info about files processed last
895  k--;
896  if (showlast < 0 || k < showlast) fi->Print(opt);
897  }
898 
899  if (out && strlen(out) > 0) gSystem->RedirectOutput(0, 0, &rh);
900 }
901 
902 ////////////////////////////////////////////////////////////////////////////////
903 /// Print information for file 'fn' (path including directory) or server 'fn'.
904 /// Multiple specifications separated by ','
905 /// or ' ' are supported, as well as wildcards '*', e.g. 'pippo.root, h4mu*,lxb10*"
906 
907 void TProofPerfAnalysis::PrintFileInfo(const char *fn, const char *opt, const char *out)
908 {
909  if (!fn || (fn && strlen(fn) <= 0)) {
910  Error("PrintFileInfo", "file path must be defined!");
911  return;
912  }
913 
914  RedirectHandle_t rh;
915  if (out && strlen(out) > 0) gSystem->RedirectOutput(out, "w", &rh);
916 
917  // Check exact name
918  TFileInfo *fi = (TFileInfo *) fFilesInfo.FindObject(fn);
919  if (fi) {
920  fi->Print(opt);
921  } else {
922  // Check matching
923  TString fw(fn), f;
924  TIter nxf(&fFilesInfo);
925  while ((fi = (TFileInfo *)nxf())) {
926  TString n(fi->GetName()), s(fi->GetTitle());
927  Ssiz_t from = 0;
928  while (fw.Tokenize(f, from, "[, ]")) {
929  TRegexp re(f, kTRUE);
930  if (n.Index(re) != kNPOS || s.Index(re) != kNPOS) fi->Print(opt);
931  }
932  }
933  }
934 
935  if (out && strlen(out) > 0) gSystem->RedirectOutput(0, 0, &rh);
936 }
937 
938 ////////////////////////////////////////////////////////////////////////////////
939 /// Fill basic worker info; if 'force' rescan the TTree even already done
940 
942 {
943  // Nothing to do if already called
944  if (fWrksInfo.GetSize() > 0 && !force) return;
945 
946  // Cleanup existing information
948  fWrksInfo.Clear();
949  fInitTime = -1.;
950  fMergeTime = -1.;
951  fMaxTime = -1.;
952  fEvtRateMax = -1.;
953  fMBRateMax = -1.;
954  fLatencyMax = -1.;
955 
956  TList *wl = new TList;
957  // Extract worker information
958  TPerfEvent pe;
959  TPerfEvent* pep = &pe;
960  fTree->SetBranchAddress("PerfEvents",&pep);
961  Long64_t entries = fTree->GetEntries();
962 
963  // First determine binning for global rates
964  Int_t nraw = entries * 2, jj = 0, kk = 0;
965  Double_t *xraw = new Double_t[nraw];
966  for (Long64_t k=0; k<entries; k++) {
967  fTree->GetEntry(k);
968  // Analyse only packets
969  if (pe.fType == TVirtualPerfStats::kPacket) {
970  Float_t stop = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
971  Float_t start = stop - pe.fProcTime;
972  // Bins
973  xraw[jj++] = start;
974  xraw[jj++] = stop;
975  }
976  }
977  Int_t nbins = jj;
978  Int_t *jidx = new Int_t[nbins];
979  memset(jidx, 0, nbins * sizeof(Int_t));
980  TMath::Sort(nbins, xraw, jidx, kFALSE);
981  Double_t *xbins = new Double_t[nbins];
982  jj = 0;
983  for (kk = 0; kk < nbins; kk++) {
984  Double_t xtmp = xraw[jidx[kk]];
985  if (jj == 0 || xtmp > xbins[jj - 1] + .5) {
986  xbins[jj] = xtmp;
987  jj++;
988  }
989  }
990  nbins = jj;
991  delete [] xraw;
992  delete [] jidx;
993 
994  // Create the global histograms
995  Int_t nbin = nbins - 1;
996  TObject *o = 0;
997  if ((o = gDirectory->FindObject("gEvtRate"))) delete o;
998  fEvtRate = new TH1F("gEvtRate", "Total event processing rate (evt/s)", nbin, xbins);
999  fEvtRate->SetMinimum(0.);
1002  fEvtRate->GetXaxis()->SetTitle("Query Processing Time (s)");
1003  if ((o = gDirectory->FindObject("gEvtRateAvg"))) delete o;
1004  fEvtRateRun = new TH1F("gEvtRateAvg", "Event processing rate running average (evt/s)", nbin, xbins);
1005  fEvtRateRun->SetMinimum(0.);
1008  fEvtRateRun->GetXaxis()->SetTitle("Query Processing Time (s)");
1009  if ((o = gDirectory->FindObject("gMBRate"))) delete o;
1010  fMBRate = new TH1F("gMBRate", "Total processing rate (MB/s)", nbin, xbins);
1011  fMBRate->SetMinimum(0.);
1012  fMBRate->SetStats(kFALSE);
1013  fMBRate->SetFillColor(kCyan-8);
1014  fMBRate->GetXaxis()->SetTitle("Query Processing Time (s)");
1015  if ((o = gDirectory->FindObject("gMBRateAvg"))) delete o;
1016  fMBRateRun = new TH1F("gMBRateAvg", "Processing rate running average (MB/s)", nbin, xbins);
1017  fMBRateRun->SetMinimum(0.);
1020  fMBRateRun->GetXaxis()->SetTitle("Query Processing Time (s)");
1021  // Not needed any longer
1022  delete [] xbins;
1023 
1024  THashList gBins;
1025  TList *gwl = 0, *gbl = 0;
1026 
1027  // Extract the worker info now
1028  TWrkInfo *wi = 0;
1029  for (Long64_t k=0; k<entries; k++) {
1030  fTree->GetEntry(k);
1031  // Analyse only packets
1032  if (pe.fType == TVirtualPerfStats::kPacket) {
1033  // Find out the worker instance
1034  if (!(wi = (TWrkInfo *) wl->FindObject(pe.fSlave.Data()))) {
1035  wi = new TWrkInfo(pe.fSlave.Data(), pe.fSlaveName.Data());
1036  wl->Add(wi);
1037  wi->fRateT = new TGraph(100);
1038  wi->fRateRemoteT = new TGraph(100);
1039  wi->fMBRateT = new TGraph(100);
1040  wi->fMBRateRemoteT = new TGraph(100);
1041  wi->fLatencyT = new TGraph(100);
1042  }
1043  // Add Info now
1044  Float_t stop = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
1045  Float_t start = stop - pe.fProcTime;
1046  if (wi->fPackets <= 0) {
1047  wi->fStart = start;
1048  } else {
1049  wi->fStop = stop;
1050  }
1051  TUrl uf(pe.fFileName), uw(pe.fSlaveName);
1052  fMaxTime = stop;
1053  wi->fEventsProcessed += pe.fEventsProcessed;
1054  wi->fBytesRead += pe.fBytesRead;
1055  wi->fLatency += pe.fLatency;
1056  wi->fProcTime += pe.fProcTime;
1057  wi->fCpuTime += pe.fCpuTime;
1058  // Fill graphs
1059  Double_t tt = stop;
1060  Double_t ert = pe.fEventsProcessed / pe.fProcTime ;
1061  Double_t brt = pe.fBytesRead / pe.fProcTime / 1024. / 1024. ;
1062  wi->fRateT->SetPoint(wi->fPackets, tt, ert);
1063  if (brt > 0.) wi->fMBRateT->SetPoint(wi->fPackets, tt, brt);
1064  wi->fLatencyT->SetPoint(wi->fPackets, tt, pe.fLatency);
1065  if (!pe.fFileName.IsNull() && strcmp(uf.GetHostFQDN(), uw.GetHostFQDN())) {
1066  wi->fRateRemoteT->SetPoint(wi->fRemotePackets, tt, ert);
1067  wi->fMBRateRemoteT->SetPoint(wi->fRemotePackets, tt, brt);
1068  wi->fRemotePackets++;
1069  }
1070  wi->fPackets++;
1071  if (ert > fEvtRateMax) fEvtRateMax = ert;
1072  if (brt > fMBRateMax) fMBRateMax = brt;
1073  if (pe.fLatency > fLatencyMax) fLatencyMax = pe.fLatency;
1074 
1075  // Fill global rate histos
1076  for (kk = 1; kk <= nbins; kk++) {
1077  Double_t mi = fEvtRate->GetBinLowEdge(kk);
1078  if (mi > stop) break;
1079  Double_t wd = fEvtRate->GetBinWidth(kk);
1080  Double_t mx = mi + wd;
1081  Double_t xx = fEvtRate->GetBinCenter(kk);
1082  // Overlap length
1083  Double_t olap = stop - mi;
1084  if (start > mi) olap = mx - start;
1085  if (olap >= 0) {
1086  TString sb = TString::Format("%d", kk);
1087  if (!(gbl = (TList *) gBins.FindObject(sb))) {
1088  gbl = new TList;
1089  gbl->SetName(sb);
1090  gBins.Add(gbl);
1091  }
1092  if (!(gwl = (TList *) gbl->FindObject(pe.fSlave))) {
1093  gwl = new TList;
1094  gwl->SetName(pe.fSlave);
1095  gbl->Add(gwl);
1096  }
1097  gwl->Add(new TWrkEntry(xx, ert, brt, pe.fProcTime));
1098  }
1099  }
1100 
1101  // Notify
1102  if (fDebug > 1) {
1103  if (pe.fProcTime > 0.) {
1104  Printf(" +++ %s #:%d at:%fs lat:%fs proc:%fs evts:%lld bytes:%lld (rates:%f evt/s, %f MB/s)",
1105  wi->GetName(), wi->fPackets, fMaxTime - pe.fProcTime,
1107  ert, brt);
1108  } else {
1109  Printf(" +++ %s #:%d at:%fs lat:%fs proc:%fs rate:-- evt/s (-- bytes/s)",
1110  wi->GetName(), wi->fPackets, fMaxTime, pe.fLatency, pe.fProcTime);
1111  }
1112  }
1113  } else if (pe.fType == TVirtualPerfStats::kStart) {
1114  Float_t start = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
1115  if (fDebug > 1) Printf(" +++ %s Start: %f s", pe.fEvtNode.Data(), start);
1116  } else if (pe.fType == TVirtualPerfStats::kStop) {
1117  Float_t stop = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
1118  if (fDebug > 1) Printf(" +++ %s Stop: %f s", pe.fEvtNode.Data(), stop);
1119  } else {
1120  if (fDebug > 2) Printf(" +++ Event type: %d", pe.fType);
1121  }
1122  }
1123 
1124  TIter nxb(&gBins);
1125  gbl = 0;
1126  while ((gbl = (TList *) nxb())) {
1127  gwl = 0;
1128  TIter nxw(gbl);
1129  while ((gwl = (TList *) nxw())) {
1130  Double_t er = 0, br = 0, pt = 0, xx = 0;
1131  TIter nxp(gwl);
1132  TWrkEntry *we = 0;
1133  while ((we = (TWrkEntry *) nxp())) {
1134  if (we->fProcTime > 0) {
1135  er += we->fEvtRate * we->fProcTime;
1136  br += we->fMBRate * we->fProcTime;
1137  pt += we->fProcTime;
1138  }
1139  xx = we->fXx;
1140  }
1141  if (pt > 0.) {
1142  er /= pt;
1143  br /= pt;
1144  fEvtRate->Fill(xx, er);
1145  if (br > 0.) fMBRate->Fill(xx, br);
1146  }
1147  }
1148  }
1149 
1150  // Running averages
1151  Double_t er = 0, br = 0, pt = 0;
1152  for (kk = 1; kk < nbins; kk++) {
1153  Double_t wd = fEvtRate->GetBinWidth(kk);
1154  Double_t wx = fEvtRate->GetBinCenter(kk);
1155  Double_t wer = fEvtRate->GetBinContent(kk);
1156  Double_t wbr = fMBRate->GetBinContent(kk);
1157 
1158  if (kk == 1) {
1159  er = wer;
1160  br = wbr;
1161  pt = wd;
1162  } else {
1163  er *= pt;
1164  br *= pt;
1165  pt += wd;
1166  er += wer * wd;
1167  br += wbr * wd;
1168  er /= pt;
1169  br /= pt;
1170  }
1171  if (er > fEvtRateAvgMax) fEvtRateAvgMax = er;
1172  if (br > fMBRateAvgMax) fMBRateAvgMax = br;
1173  fEvtRateAvg = er;
1174  fMBRateAvg = br;
1175  // Fill
1176  fEvtRateRun->Fill(wx, er);
1177  fMBRateRun->Fill(wx, br);
1178  }
1179 
1180 
1181  // Final analysis to find relevant times
1182  TIter nxw(wl);
1183  while ((wi = (TWrkInfo *) nxw())) {
1184  fWrksInfo.Add(wi);
1185  if (wi->fStart > fInitTime) fInitTime = wi->fStart;
1186  // Resize the graphs
1187  wi->fRateT->Set(wi->fPackets);
1188  wi->fRateRemoteT->Set(wi->fRemotePackets);
1189  wi->fLatencyT->Set(wi->fPackets);
1190  wi->fMBRateT->Set(wi->fPackets);
1191  wi->fMBRateRemoteT->Set(wi->fRemotePackets);
1192  }
1193  wl->SetOwner(kFALSE);
1194  delete wl;
1195 
1196  // Final analysis to find relevant times
1197  fMergeTime = fMaxTime;
1198  Int_t rsw = (fWrksInfo.GetSize() > 1) ? 2 : 2, ksw = 0;
1199  TIter nxsw(&fWrksInfo);
1200  while ((wi = (TWrkInfo *) nxsw())) {
1201  if (wi->fStop > 0.) ksw++;
1202  if (ksw == rsw) break;
1203  }
1204  if (wi) fMergeTime = wi->fStop;
1205 
1206  // (Re-)create the event and packet distribution histograms
1208  SafeDelete(fPackets);
1209  fEvents = new TH1F("hevents", "Events per worker", fWrksInfo.GetSize(), -.5, fWrksInfo.GetSize()-.5);
1210  fEvents->SetDirectory(0);
1211  fPackets = new TH1F("hpackets", "Packets per worker", fWrksInfo.GetSize(), -.5, fWrksInfo.GetSize()-.5);
1212  fPackets->SetDirectory(0);
1213  Int_t j = 0;
1214  TIter nxwi(&fWrksInfo);
1215  while ((wi = (TWrkInfo *)nxwi())) {
1216  fEvents->GetXaxis()->SetBinLabel(j+1, wi->GetName());
1217  fEvents->Fill(j, wi->fEventsProcessed);
1218  fPackets->GetXaxis()->SetBinLabel(j+1, wi->GetName());
1219  fPackets->Fill(j++, wi->fPackets);
1220  }
1221  fEvents->SetMinimum(0.);
1222  fPackets->SetMinimum(0.);
1223  fEvents->SetFillColor(38);
1224  fPackets->SetFillColor(38);
1225  fEvents->GetYaxis()->SetTitle("Events");
1226  fEvents->GetXaxis()->SetTitle("Worker");
1227  fPackets->GetYaxis()->SetTitle("Packets");
1228  fPackets->GetXaxis()->SetTitle("Worker");
1229 
1230  // Print summary
1231  if (fgDebug) Summary();
1232 }
1233 
1234 ////////////////////////////////////////////////////////////////////////////////
1235 /// Print summary of query. Use opt = 'S' for compact version.
1236 /// Output to 'out' or to screen.
1237 
1239 {
1240  TString o(out);
1241  RedirectHandle_t rh;
1242  if (!o.IsNull()) {
1243  const char *m = (o.BeginsWith("+")) ? "a" : "w";
1244  o.Remove(TString::kLeading, '+');
1245  gSystem->RedirectOutput(o, m, &rh);
1246  }
1247 
1248  // Print summary
1249  if (!strcmp(opt, "S")) {
1250  // Short version
1251  Printf("%d %f %f %f %f %f %f %f",
1254  } else {
1255  // Long version
1256  Printf(" +++ %d workers were active during this query", fWrksInfo.GetSize());
1257  Printf(" +++ Total query time: %f secs (init: %f secs, merge: %f secs)",
1259  Printf(" +++ Avg processing rates: %.4f evts/s, %.4f MB/s", fEvtRateAvg, fMBRateAvg);
1260  Printf(" +++ Max processing rates: %.4f evts/s, %.4f MB/s", fEvtRateAvgMax, fMBRateAvgMax);
1261  }
1262 
1263  if (!o.IsNull()) gSystem->RedirectOutput(0, 0, &rh);
1264 }
1265 
1266 ////////////////////////////////////////////////////////////////////////////////
1267 /// Fill basic worker info; if 'force' rescan the TTree even already done
1268 
1270 {
1271  // Nothing to do if already called
1272  if (fFilesInfo.GetSize() > 0 && !force) return;
1273 
1274  // Cleanup existing information
1276  fFilesInfo.Clear();
1277 
1278  TList *fl = new TList;
1279  // Extract worker information
1280  TPerfEvent pe;
1281  TPerfEvent* pep = &pe;
1282  fTree->SetBranchAddress("PerfEvents",&pep);
1283  Long64_t entries = fTree->GetEntries();
1284  TFileInfo *fi = 0;
1285  for (Long64_t k=0; k<entries; k++) {
1286  fTree->GetEntry(k);
1287  // Analyse only packets
1288  if (pe.fType == TVirtualPerfStats::kPacket) {
1289  TUrl uf(pe.fFileName);
1290  TString srv(uf.GetUrl());
1291  Int_t ifn = srv.Index(uf.GetFile());
1292  if (ifn != kNPOS) srv.Remove(ifn);
1293  // Find out the file instance
1294  fi = (TFileInfo *) fl->FindObject(uf.GetFile());
1295  if (!fi) {
1296  fi = new TFileInfo(uf.GetFile(), srv.Data());
1297  fl->Add(fi);
1298  fi->fSizeP = new TGraph(10);
1299  fi->fRateP = new TGraph(10);
1300  fi->fRatePRemote = new TGraph(10);
1301  fi->fMBRateP = new TGraph(10);
1302  fi->fMBRatePRemote = new TGraph(10);
1303  }
1304  // Add Info now
1305  Float_t stop = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
1306  Float_t start = stop - pe.fProcTime;
1307  if (fi->fPackets <= 0) {
1308  fi->fStart = start;
1309  } else {
1310  fi->fStop = stop;
1311  }
1312  TUrl uw(pe.fSlaveName);
1313 
1314  // Fill size graphs
1315  fi->fSizeP->SetPoint(fi->fPackets, (Double_t) fi->fPackets, (Double_t) pe.fEventsProcessed);
1316  fi->fSizeAvg += pe.fEventsProcessed;
1317  if (pe.fEventsProcessed > fi->fSizeMax || fi->fSizeMax < 0.) fi->fSizeMax = pe.fEventsProcessed;
1318  if (pe.fEventsProcessed < fi->fSizeMin || fi->fSizeMin < 0.) fi->fSizeMin = pe.fEventsProcessed;
1319 
1320  // Fill rate graphs
1321  Double_t tt = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
1322  Double_t ert = pe.fEventsProcessed / pe.fProcTime ;
1323  Double_t brt = pe.fBytesRead / pe.fProcTime / 1024. / 1024. ;
1324  fi->fRateP->SetPoint(fi->fPackets, tt, ert);
1325  if (brt > 0.) fi->fMBRateP->SetPoint(fi->fPackets, tt, brt);
1326  if (!pe.fFileName.IsNull() && strcmp(uf.GetHostFQDN(), uw.GetHostFQDN())) {
1327  if (!(fi->fRWrkList.FindObject(pe.fSlave))) fi->fRWrkList.Add(new TNamed(pe.fSlave, pe.fSlaveName));
1328  fi->fRatePRemote->SetPoint(fi->fRPackets, tt, ert);
1329  fi->fMBRatePRemote->SetPoint(fi->fRPackets, tt, brt);
1330  fi->fRPackets++;
1331  }
1332  fi->fPackets++;
1333  if (brt > 0) {
1334  fi->fMBRateAvg += brt;
1335  if (brt > fi->fMBRateMax || fi->fMBRateMax < 0.) fi->fMBRateMax = brt;
1336  if (brt < fi->fMBRateMin || fi->fMBRateMin < 0.) fi->fMBRateMin = brt;
1337  }
1338 
1339  // Packet info
1340  TPackInfo *pi = new TPackInfo(pe.fSlave, pe.fSlaveName, start, stop, pe.fEventsProcessed, brt);
1341  fi->fPackList.Add(pi);
1342  TWrkInfoFile *wif = 0;
1343  if (!(wif = (TWrkInfoFile *) fi->fWrkList.FindObject(pe.fSlave))) {
1344  wif = new TWrkInfoFile(pe.fSlave, uf.GetFile());
1345  fi->fWrkList.Add(wif);
1346  }
1347  wif->fPackets.Add(pi);
1348 
1349  // Notify
1350  if (fDebug > 1) {
1351  if (pe.fProcTime > 0.) {
1352  Printf(" +++ %s #:%d at:%fs lat:%fs proc:%fs evts:%lld bytes:%lld (rates:%f evt/s, %f MB/s)",
1353  fi->GetName(), fi->fPackets, fMaxTime - pe.fProcTime,
1355  ert, brt);
1356  } else {
1357  Printf(" +++ %s #:%d at:%fs lat:%fs proc:%fs rate:-- evt/s (-- bytes/s)",
1358  fi->GetName(), fi->fPackets, fMaxTime, pe.fLatency, pe.fProcTime);
1359  }
1360  }
1361  } else if (pe.fType == TVirtualPerfStats::kStart) {
1362  Float_t start = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
1363  if (fDebug > 1) Printf(" +++ %s Start: %f s", pe.fEvtNode.Data(), start);
1364  } else if (pe.fType == TVirtualPerfStats::kStop) {
1365  Float_t stop = pe.fTimeStamp.GetSec() + 1e-9*pe.fTimeStamp.GetNanoSec();
1366  if (fDebug > 1) Printf(" +++ %s Stop: %f s", pe.fEvtNode.Data(), stop);
1367  } else {
1368  if (fDebug > 2) Printf(" +++ Event type: %d", pe.fType);
1369  }
1370  }
1371  // Final analysis to find relevant times
1372  TIter nxf(fl);
1373  while ((fi = (TFileInfo *) nxf())) {
1374  fFilesInfo.Add(fi);
1375  // Resize the graphs
1376  fi->fRateP->Set(fi->fPackets);
1377  fi->fRatePRemote->Set(fi->fRPackets);
1378  fi->fMBRateP->Set(fi->fPackets);
1379  fi->fMBRatePRemote->Set(fi->fRPackets);
1380  }
1381  fl->SetOwner(kFALSE);
1382  delete fl;
1383 
1384  // Print summary
1385  if (fgDebug)
1386  Printf(" +++ %d files were processed during this query", fFilesInfo.GetSize());
1387 }
1388 
1389 ////////////////////////////////////////////////////////////////////////////////
1390 /// Static setter for the verbosity level
1391 
1393 {
1394  fDebug = d;
1395 }
1396 
1397 ////////////////////////////////////////////////////////////////////////////////
1398 /// Draw object 'o' with options 'opt'
1399 /// Save it with 'name' if in saving mode (see SetSaveResult)
1400 
1402 {
1403  // Draw
1404  o->Draw(opt);
1405 
1406  // Save the result
1407  if (fSaveResult) {
1408  // Preparation is done in SetSaveResult, here we just update
1409  TDirectory *curdir = gDirectory;
1410  TFile *f = TFile::Open(fFileResult, "UPDATE");
1411  if (f && !f->IsZombie()) {
1412  const char *n = (name && strlen(name) > 0) ? name : 0;
1413  o->Write(n);
1414  f->Close();
1415  }
1416  if (f) delete f;
1417  gDirectory = curdir;
1418  }
1419 }
1420 
1421 ////////////////////////////////////////////////////////////////////////////////
1422 /// Set save result mode and validate 'file' according to 'mode'.
1423 /// Return 0 on success, -1 if any problem with the file is encountered
1424 /// (save result mode is not enabled in such a case).
1425 /// If 'file' is null saving is disabled.
1426 
1428 {
1429  // A null 'file' indicates the will to disable
1430  if (!file) {
1431  fFileResult = "";
1432  fSaveResult = kFALSE;
1433  // Notify
1434  Printf("Drawn objects saving disabled");
1435  return 0;
1436  }
1437 
1438  // Check if there is a change
1439  if (!fFileResult.IsNull() && fFileResult == file) {
1440  // No change
1441  fSaveResult = kTRUE;
1442  return 0;
1443  }
1444  // New or changed file: validate
1445  fFileResult = "";
1446  fSaveResult = kFALSE;
1447  TDirectory *curdir = gDirectory;
1448  TFile *f = TFile::Open(file, mode);
1449  if (!f || f->IsZombie()) {
1450  if (f) delete f;
1451  fFileResult = "";
1452  Error("SetSaveResult", "could not open file '%s' in mode '%s'",
1453  file ? file : "(undefined)", mode);
1454  gDirectory = curdir;
1455  return -1;
1456  }
1457  f->Close();
1458  delete f;
1459  gDirectory = curdir;
1460  // Ok
1461  fFileResult = file;
1462  fSaveResult = kTRUE;
1463  // Notify
1464  Printf("Drawn objects will be saved in file '%s'", file);
1465  return 0;
1466 }
1467 
1468 ////////////////////////////////////////////////////////////////////////////////
1469 /// Static setter for the verbosity level
1470 
1472 {
1473  fgDebug = on;
1474 }
1475 ////////////////////////////////////////////////////////////////////////////////
1476 /// Display event and packet distribution
1477 
1479 {
1480  if (!fEvents || !fPackets) {
1481  Error("EventDist", "distributions not initialized - do nothing");
1482  }
1483 
1484  // Display histos
1485  TCanvas *c1 = new TCanvas("evtdist", GetCanvasTitle("Event distributions"),800,10,700,780);
1486  c1->Divide(1,2);
1487  TPad *pad1 = (TPad *) c1->GetPad(1);
1488  pad1->cd();
1490  DoDraw(fEvents);
1491  TPad *pad2 = (TPad *) c1->GetPad(2);
1492  pad2->cd();
1493  fPackets->SetStats(kFALSE);
1494  DoDraw(fPackets);
1495  c1->cd();
1496  c1->Update();
1497 
1498 }
1499 
1500 ////////////////////////////////////////////////////////////////////////////////
1501 /// Show event processing or MB processing rate plot vs time
1502 
1503 void TProofPerfAnalysis::RatePlot(const char *wrks)
1504 {
1505  Bool_t global = (wrks && !strcmp(wrks, "global")) ? kTRUE : kFALSE;
1506 
1507  TH1F *hrt1 = 0, *hrt2 = 0;
1508  if (global) {
1509  hrt1 = fEvtRate;
1510  hrt2 = fMBRate;
1511  } else {
1512  // Create the histograms
1513  TObject *o = 0;
1514  if ((o = gDirectory->FindObject("rt1"))) delete o;
1515  hrt1 = new TH1F("rt1", "Evt processing rate (evt/s)", 100, 0., fMaxTime);
1516  hrt1->SetMinimum(0.);
1517  hrt1->SetMaximum(1.05*fEvtRateMax);
1518  hrt1->SetStats(kFALSE);
1519  hrt1->GetXaxis()->SetTitle("Query Processing Time (s)");
1520  if ((o = gDirectory->FindObject("rt2"))) delete o;
1521  hrt2 = new TH1F("rt2", "MB processing rate (MB/s)", 100, 0., fMaxTime);
1522  hrt2->SetMinimum(0.);
1523  hrt2->SetMaximum(1.05*fMBRateMax);
1524  hrt2->SetStats(kFALSE);
1525  hrt2->GetXaxis()->SetTitle("Query Processing Time (s)");
1526  }
1527 
1528  // Display histo frames
1529  TCanvas *c1 = new TCanvas("rates", GetCanvasTitle("Processing rates"), 800,10,700,780);
1530  c1->Divide(1,2);
1531  TPad *pad1 = (TPad *) c1->GetPad(1);
1532  pad1->cd();
1533  hrt1->Draw();
1534  if (global) DoDraw(fEvtRateRun, "SAME", "EvtRateRun");
1535  TPad *pad2 = (TPad *) c1->GetPad(2);
1536  pad2->cd();
1537  hrt2->Draw();
1538  if (global) DoDraw(fMBRateRun, "SAME", "MBRateRun");
1539  c1->cd();
1540  c1->Update();
1541 
1542  // Done if global
1543  if (global) return;
1544 
1545  // Which workers?
1546  THashList *wl = 0;
1547  TString ww(wrks);
1548  if (!ww.IsNull() && ww != "*" && ww != "all") {
1549  TString w;
1550  Ssiz_t from = 0;
1551  while ((ww.Tokenize(w, from, ","))) {
1552  if (!wl) wl = new THashList();
1553  wl->Add(new TObjString(w.Data()));
1554  }
1555  }
1556 
1557  // Now plot the graphs per worker
1558  Int_t ci = 40, cir = 30, ic = 0;
1559  TIter nxw(&fWrksInfo);
1560  TWrkInfo *wi = 0;
1561  while ((wi = (TWrkInfo *) nxw())) {
1562  if (wl && !wl->FindObject(wi->GetName())) continue;
1563  if (wi->fRateT && wi->fRateT->GetN() > 0) {
1564  wi->fRateT->SetNameTitle(wi->GetName(), wi->GetTitle());
1565  pad1->cd();
1566  wi->fRateT->SetLineColor(ci);
1567  DoDraw(wi->fRateT, "L", TString::Format("RateT-%s", wi->fRateT->GetName()));
1568  }
1569  if (wi->fRateRemoteT && wi->fRateRemoteT->GetN() > 0) {
1570  wi->fRateRemoteT->SetNameTitle(wi->GetName(), wi->GetTitle());
1571  pad1->cd();
1572  wi->fRateRemoteT->SetLineColor(cir);
1573  DoDraw(wi->fRateRemoteT, "L", TString::Format("RateRemoteT-%s", wi->fRateRemoteT->GetName()));
1574  }
1575  if (wi->fMBRateT && wi->fMBRateT->GetN() > 0) {
1576  wi->fMBRateT->SetNameTitle(wi->GetName(), wi->GetTitle());
1577  pad2->cd();
1578  wi->fMBRateT->SetLineColor(ci);
1579  DoDraw(wi->fMBRateT, "L", TString::Format("MBRateT-%s", wi->fMBRateT->GetName()));
1580  }
1581  if (wi->fMBRateRemoteT && wi->fMBRateRemoteT->GetN() > 0) {
1582  wi->fMBRateRemoteT->SetNameTitle(wi->GetName(), wi->GetTitle());
1583  pad2->cd();
1584  wi->fMBRateRemoteT->SetLineColor(cir);
1585  DoDraw(wi->fMBRateRemoteT, "L", TString::Format("MBRateRemoteT-%s", wi->fMBRateRemoteT->GetName()));
1586  }
1587  ic++;
1588  ci = ic%10 + 40;
1589  cir = ic%10 + 30;
1590  c1->cd();
1591  c1->Update();
1592  }
1593 
1594  // Cleanup
1595  if (wl) {
1596  wl->SetOwner(kTRUE);
1597  delete wl;
1598  }
1599 }
1600 
1601 ////////////////////////////////////////////////////////////////////////////////
1602 /// Show event processing or MB processing rate plot vs time
1603 /// Create the histograms
1604 
1605 void TProofPerfAnalysis::LatencyPlot(const char *wrks)
1606 {
1607  TObject *o = 0;
1608  if ((o = gDirectory->FindObject("lt1"))) delete o;
1609  TH1F *hlt1 = new TH1F("lt1", "Packet retrieval latency", 100, 0., fMaxTime);
1610  hlt1->SetMinimum(0.);
1611  hlt1->SetMaximum(1.05*fLatencyMax);
1612  hlt1->SetStats(kFALSE);
1613  hlt1->GetXaxis()->SetTitle("Query Processing Time (s)");
1614  hlt1->GetYaxis()->SetTitle("Latency (s)");
1615 
1616  // Display histo frames
1617  TCanvas *c1 = new TCanvas("latency", GetCanvasTitle("Packet Retrieval Latency"), 800,10,700,780);
1618  hlt1->Draw();
1619  c1->cd();
1620  c1->Update();
1621 
1622  // Which workers?
1623  THashList *wl = 0;
1624  TString ww(wrks);
1625  if (!ww.IsNull() && ww != "*" && ww != "all") {
1626  TString w;
1627  Ssiz_t from = 0;
1628  while ((ww.Tokenize(w, from, ","))) {
1629  if (!wl) wl = new THashList();
1630  wl->Add(new TObjString(w.Data()));
1631  }
1632  }
1633 
1634  // Now plot the graphs per worker
1635  Int_t ci = 40, ic = 0;
1636  TIter nxw(&fWrksInfo);
1637  TWrkInfo *wi = 0;
1638  while ((wi = (TWrkInfo *) nxw())) {
1639  if (wl && !wl->FindObject(wi->GetName())) continue;
1640  if (wi->fLatencyT) {
1641  wi->fLatencyT->SetNameTitle(wi->GetName(), wi->GetTitle());
1642  wi->fLatencyT->SetLineColor(ci);
1643  DoDraw(wi->fLatencyT, "L", TString::Format("LatencyT-%s", wi->fLatencyT->GetName()));
1644  }
1645  ic++;
1646  ci = ic%10 + 40;
1647  c1->cd();
1648  c1->Update();
1649  }
1650 
1651  // Cleanup
1652  if (wl) {
1653  wl->SetOwner(kTRUE);
1654  delete wl;
1655  }
1656 }
1657 
1658 ////////////////////////////////////////////////////////////////////////////////
1659 /// Show event processing or MB processing rate plot vs time
1660 
1661 void TProofPerfAnalysis::FileProcPlot(const char *fn, const char *out)
1662 {
1663  if (!fn || strlen(fn) <= 0) {
1664  Error("FileRatePlot", "file name is mandatory!");
1665  return;
1666  }
1667  // Get the file info object
1668  TFileInfo *fi = (TFileInfo *) fFilesInfo.FindObject(fn);
1669  if (!fi) {
1670  Error("FileRatePlot", "TFileInfo object for '%s' not found!", fn);
1671  return;
1672  }
1673 
1674  // Output text file, if required
1675  FILE *fo = stdout;
1676  if (out && strlen(out) > 0) {
1677  if (!(fo = fopen(out, "w"))) {
1678  Warning("FileRatePlot", "problems creating '%s': logging to stdout", out);
1679  fo = stdout;
1680  } else {
1681  Printf(" Details logged to %s", out);
1682  }
1683  }
1684 
1685  // Get bins
1686  Int_t nbins = fi->fPackList.GetSize() * 2;
1687  Double_t *xraw = new Double_t[nbins];
1688  Int_t jj = 0;
1689  TPackInfo *pi = 0;
1690  TIter nxp(&(fi->fPackList));
1691  while ((pi = (TPackInfo *) nxp())) {
1692  // Bins
1693  xraw[jj++] = pi->fStart;
1694  xraw[jj++] = pi->fStop;
1695  }
1696  Int_t *jidx = new Int_t[nbins];
1697  memset(jidx, 0, nbins * sizeof(Int_t));
1698  TMath::Sort(nbins, xraw, jidx, kFALSE);
1699  Double_t *xbins = new Double_t[nbins];
1700  Int_t kk =0;
1701  for (kk = 0; kk < nbins; kk++) {
1702  xbins[kk] = xraw[jidx[kk]];
1703  }
1704  delete [] xraw;
1705  delete [] jidx;
1706 
1707  // Create the histograms
1708  Int_t nbin = nbins - 1;
1709  TObject *o = 0;
1710  if ((o = gDirectory->FindObject("rt1"))) delete o;
1711  TH1F *hrt1 = new TH1F("rt1", "Total processing rate (MB/s)", nbins - 1, xbins);
1712  hrt1->SetMinimum(0.);
1713  hrt1->SetStats(kFALSE);
1714  hrt1->GetXaxis()->SetTitle("Query Processing Time (s)");
1715  if ((o = gDirectory->FindObject("rt2"))) delete o;
1716  TH1F *hrt2 = new TH1F("rt2", "Number of processing workers", nbins - 1, xbins);
1717  hrt2->SetMinimum(0.);
1718  hrt2->SetMaximum(1.2*fWrksInfo.GetSize());
1719  hrt2->SetStats(kFALSE);
1720  hrt2->GetXaxis()->SetTitle("Query Processing Time (s)");
1721  if ((o = gDirectory->FindObject("rt3"))) delete o;
1722  TH1F *hrt3 = new TH1F("rt3", "Total processing events", nbins - 1, xbins);
1723  hrt3->SetMinimum(0.);
1724  hrt3->SetStats(kFALSE);
1725  hrt3->GetXaxis()->SetTitle("Query Processing Time (s)");
1726  if ((o = gDirectory->FindObject("rt4"))) delete o;
1727  TH1F *hrt4 = new TH1F("rt4", "Weighted processing rate (MB/s)", nbins - 1, xbins);
1728  hrt4->SetMinimum(0.);
1729  hrt4->SetStats(kFALSE);
1730  hrt4->GetXaxis()->SetTitle("Query Processing Time (s)");
1731  // Not needed any longer
1732  delete [] xbins;
1733 
1734  // Fill histos now
1735  Int_t ii = 0;
1736  for (ii = 1; ii <= nbin; ii++) {
1737  Double_t mi = hrt1->GetBinLowEdge(ii);
1738  Double_t wd = hrt1->GetBinWidth(ii);
1739  Double_t mx = mi + wd;
1740  Double_t xx = hrt1->GetBinCenter(ii);
1741  fprintf(fo, " Bin: %d/%d [%f, %f]\n", ii, nbin, mi, mx);
1742  pi = 0;
1743  kk = 0;
1744  nxp.Reset();
1745  while ((pi = (TPackInfo *) nxp())) {
1746  // Overlap length
1747  Double_t olap = pi->fStop - mi;
1748  if (pi->fStart > mi) olap = mx - pi->fStart;
1749  if (olap >= 0) {
1750  hrt1->Fill(xx, pi->fMBRate);
1751  hrt2->Fill(xx, 1.);
1752  hrt3->Fill(xx, pi->fSize);
1753  hrt4->Fill(xx, pi->fMBRate * pi->fSize);
1754  fprintf(fo, " %d: %s \t%lld \tevts \t%f \tMB/s\n", kk++, pi->GetName(), pi->fSize, pi->fMBRate);
1755  }
1756  }
1757  }
1758  if (fo != stdout) fclose(fo);
1759 
1760  // Display histo frames
1761  TCanvas *c1 = new TCanvas("rates", GetCanvasTitle("File processing info"), 800,10,700,780);
1762  c1->Divide(1,3);
1763  TPad *pad1 = (TPad *) c1->GetPad(1);
1764  pad1->cd();
1765  DoDraw(hrt1);
1766  TPad *pad2 = (TPad *) c1->GetPad(2);
1767  pad2->cd();
1768  DoDraw(hrt2);
1769  TPad *pad4 = (TPad *) c1->GetPad(3);
1770  pad4->cd();
1771  hrt4->Divide(hrt3);
1772  DoDraw(hrt4);
1773  c1->cd();
1774  c1->Update();
1775 }
1776 
1777 ////////////////////////////////////////////////////////////////////////////////
1778 /// Show MB processing rate plot per file vs time
1779 
1781 {
1782  // Create the histograms
1783  TObject *o = 0;
1784  if ((o = gDirectory->FindObject("rt1"))) delete o;
1785  TH1F *hrt1 = new TH1F("rt1", "Event processing rate per packet (evt/s)", 100, 0., fMaxTime);
1786  hrt1->SetMinimum(0.);
1787  hrt1->SetMaximum(1.05*fEvtRateMax);
1788  hrt1->SetStats(kFALSE);
1789  hrt1->GetXaxis()->SetTitle("Query Processing Time (s)");
1790  if ((o = gDirectory->FindObject("rt2"))) delete o;
1791  TH1F *hrt2 = new TH1F("rt2", "I/O processing rate per packet (MB/s)", 100, 0., fMaxTime);
1792  hrt2->SetMinimum(0.);
1793  hrt2->SetMaximum(1.05*fMBRateMax);
1794  hrt2->SetStats(kFALSE);
1795  hrt2->GetXaxis()->SetTitle("Query Processing Time (s)");
1796 
1797  // Display histo frames
1798  TCanvas *c1 = new TCanvas("rates", GetCanvasTitle("Processing rates"), 800,10,700,780);
1799  c1->Divide(1,2);
1800  TPad *pad1 = (TPad *) c1->GetPad(1);
1801  pad1->cd();
1802  hrt1->Draw();
1803  TPad *pad2 = (TPad *) c1->GetPad(2);
1804  pad2->cd();
1805  hrt2->Draw();
1806  c1->cd();
1807  c1->Update();
1808 
1809  // Which workers?
1810  THashList *fl = 0;
1811  TString fw(fns);
1812  if (!fw.IsNull() && fw != "*" && fw != "all") {
1813  TString w;
1814  Ssiz_t from = 0;
1815  while ((fw.Tokenize(w, from, ","))) {
1816  if (!fl) fl = new THashList();
1817  fl->Add(new TObjString(w.Data()));
1818  }
1819  }
1820 
1821  // Now plot the graphs per worker
1822  Int_t ci = 40, cir = 30, ic = 0;
1823  TIter nxf(&fFilesInfo);
1824  TFileInfo *fi = 0;
1825  while ((fi = (TFileInfo *) nxf())) {
1826  if (fl && !fl->FindObject(fi->GetName())) continue;
1827  if (fi->fRateP && fi->fRateP->GetN() > 0) {
1828  fi->fRateP->SetNameTitle(fi->GetName(), fi->GetTitle());
1829  pad1->cd();
1830  fi->fRateP->SetLineColor(ci);
1831  DoDraw(fi->fRateP, "L", TString::Format("RateP-%d", ic));
1832  }
1833  if (fi->fRatePRemote && fi->fRatePRemote->GetN() > 0) {
1834  fi->fRatePRemote->SetNameTitle(fi->GetName(), fi->GetTitle());
1835  pad1->cd();
1836  fi->fRatePRemote->SetLineColor(cir);
1837  DoDraw(fi->fRatePRemote, "L", TString::Format("RatePRemote-%d", ic));
1838  }
1839  if (fi->fMBRateP && fi->fMBRateP->GetN() > 0) {
1840  fi->fMBRateP->SetNameTitle(fi->GetName(), fi->GetTitle());
1841  pad2->cd();
1842  fi->fMBRateP->SetLineColor(ci);
1843  DoDraw(fi->fMBRateP, "L", TString::Format("MBRateP-%d", ic));
1844  }
1845  if (fi->fMBRatePRemote && fi->fMBRatePRemote->GetN() > 0) {
1846  fi->fMBRatePRemote->SetNameTitle(fi->GetName(), fi->GetTitle());
1847  pad2->cd();
1848  fi->fMBRatePRemote->SetLineColor(cir);
1849  DoDraw(fi->fMBRatePRemote, "L", TString::Format("MBRatePRemote-%d", ic));
1850  }
1851  ic++;
1852  ci = ic%10 + 40;
1853  cir = ic%10 + 30;
1854  c1->cd();
1855  c1->Update();
1856  }
1857 
1858  // Cleanup
1859  if (fl) {
1860  fl->SetOwner(kTRUE);
1861  delete fl;
1862  }
1863 }
TString fTitle
Definition: TNamed.h:37
void SetDebug(Int_t d=0)
Static setter for the verbosity level.
virtual void SetTitleOffset(Float_t offset=1)
Set distance between the axis and the axis title Offset is a correction factor with respect to the "s...
Definition: TAttAxis.cxx:244
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:928
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Write this object to the current directory.
Definition: TObject.cxx:823
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:52
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition: TH1.cxx:3159
TVirtualPerfStats::EEventType fType
Definition: TPerfStats.h:54
virtual ~TProofPerfAnalysis()
Destructor: detach the tree and close the file.
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition: TH1.cxx:4629
long long Long64_t
Definition: RtypesCore.h:69
virtual void SetMaximum(Double_t maximum=-1111)
Definition: TH1.h:394
void Print(Option_t *options="") const
Print information about this object.
Definition: TFileInfo.cxx:475
virtual TList * GetListOfKeys() const
Definition: TDirectory.h:155
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
Definition: TDirectory.cxx:727
virtual void Draw(Option_t *option="")=0
Default Draw method for all objects.
const double pi
Collectable string class.
Definition: TObjString.h:32
float Float_t
Definition: RtypesCore.h:53
virtual void ls(Option_t *option="") const
List (ls) all objects in this collection.
virtual void SetDirectory(TDirectory *dir)
By default when an histogram is created, it is added to the list of histogram objects in the current ...
Definition: TH1.cxx:8266
TString GetCanvasTitle(const char *t)
If defined, add '- ="">' to the canvas title 't'.
THist< 2, float > TH2F
Definition: THist.h:321
void PrintFileInfo(Int_t showlast=10, const char *opt="", const char *out=0)
Print information for all or the slowest showlast workers.
const char Option_t
Definition: RtypesCore.h:62
TCanvas * c1
Definition: legend1.C:2
TObject * FindObject(const char *name) const
Find object using its name.
Definition: THashList.cxx:212
This class represents a WWW compatible URL.
Definition: TUrl.h:41
R__EXTERN TStyle * gStyle
Definition: TStyle.h:423
#define gDirectory
Definition: TDirectory.h:218
virtual void SetName(const char *name)
Change (i.e.
Definition: TNamed.cxx:128
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:892
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:45
TVirtualPad * cd(Int_t subpadnumber=0)
Set current canvas & pad.
Definition: TCanvas.cxx:659
Regular expression class.
Definition: TRegexp.h:35
virtual TObject * Get(const char *namecycle)
Return pointer to object identified by namecycle.
THist< 1, float > TH1F
Definition: THist.h:315
virtual void SetMinimum(Double_t minimum=-1111)
Definition: TH1.h:395
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all branches of entry and return total number of bytes read.
Definition: TTree.cxx:5163
TString fSlaveName
Definition: TPerfStats.h:55
Bool_t IsZombie() const
Definition: TObject.h:141
Basic string class.
Definition: TString.h:137
1-D histogram with a float per channel (see TH1 documentation)}
Definition: TH1.h:570
struct staticInitHelper gbl
int Int_t
Definition: RtypesCore.h:41
virtual const char * DirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:996
bool Bool_t
Definition: RtypesCore.h:59
Bool_t IsValid() const
const Bool_t kFALSE
Definition: Rtypes.h:92
Int_t GetOptStat() const
Definition: TStyle.h:253
virtual void Draw(Option_t *option="")
Default Draw method for all objects.
Definition: TObject.cxx:254
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:496
int nbins[3]
virtual Int_t GetNbinsX() const
Definition: TH1.h:296
Double_t fCpuTime
Definition: TPerfStats.h:65
void LoadTree(TDirectory *dir)
Load tree fTreeName from directory 'dir'.
TLatex * t1
Definition: textangle.C:20
virtual void SetNameTitle(const char *name, const char *title)
Change (i.e. set) all the TNamed parameters (name and title).
Definition: TNamed.cxx:142
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:558
void Reset()
Definition: TCollection.h:161
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:732
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:625
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=1, Int_t netopt=0)
Create / open a file.
Definition: TFile.cxx:3851
void FileDist(Bool_t writedet=kFALSE)
Analyse the file distribution.
virtual Double_t GetBinWidth(Int_t bin) const
return bin width for 1D historam Better to use h1.GetXaxis().GetBinWidth(bin)
Definition: TH1.cxx:8492
void FileProcPlot(const char *fn, const char *out=0)
Show event processing or MB processing rate plot vs time.
const char * Data() const
Definition: TString.h:349
virtual void Clear(Option_t *option="")
Set name and title to empty strings ("").
Definition: TNamed.cxx:53
#define SafeDelete(p)
Definition: RConfig.h:436
Int_t CompareOrd(const char *ord1, const char *ord2)
Return -1 if ord1 comes before ord2, 0 i they are equal, 1 if ord1 comes after ord2.
TVirtualPad * cd(Int_t subpadnumber=0)
Set Current pad.
Definition: TPad.cxx:514
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2334
virtual Double_t GetBinLowEdge(Int_t bin) const
return bin lower edge for 1D historam Better to use h1.GetXaxis().GetBinLowEdge(bin) ...
Definition: TH1.cxx:8481
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition: THashList.h:36
virtual Int_t SetBranchAddress(const char *bname, void *add, TBranch **ptr=0)
Change branch address, dealing with clone trees properly.
Definition: TTree.cxx:7529
const char * ord
Definition: TXSlave.cxx:46
TText * tt
Definition: textangle.C:16
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:33
void EventDist()
Display event and packet distribution.
static double p2(double t, double a, double b, double c)
Bool_t WrkInfoOK() const
TString fEvtNode
Definition: TPerfStats.h:52
void FileRatePlot(const char *fns=0)
Show MB processing rate plot per file vs time.
void Sort(Index n, const Element *a, Index *index, Bool_t down=kTRUE)
Definition: TMath.h:1002
void RatePlot(const char *wrks=0)
Show event processing or MB processing rate plot vs time.
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1964
Book space in a file, create I/O buffers, to fill them, (un)compress them.
Definition: TKey.h:30
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
char * out
Definition: TBase64.cxx:29
TProofPerfAnalysis(const char *perffile, const char *title="", const char *treename="PROOF_PerfStats")
Constructor: open the file and attach to the tree.
virtual Int_t Compare(const TObject *obj) const
Compare two TNamed objects.
Definition: TNamed.cxx:74
virtual Bool_t Divide(TF1 *f1, Double_t c1=1)
Performs the operation: this = this/(c1*f1) if errors are defined (see TH1::Sumw2), errors are also recalculated.
Definition: TH1.cxx:2630
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition: TObject.cxx:594
A doubly linked list.
Definition: TList.h:47
virtual void SetLineColor(Color_t lcolor)
Definition: TAttLine.h:54
time_t GetSec() const
Definition: TTimeStamp.h:140
virtual Double_t GetBinCenter(Int_t bin) const
return bin center for 1D historam Better to use h1.GetXaxis().GetBinCenter(bin)
Definition: TH1.cxx:8470
TPaveText * pt
Int_t SetSaveResult(const char *file="results.root", Option_t *mode="RECREATE")
Set save result mode and validate 'file' according to 'mode'.
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
virtual void Draw(Option_t *option="")
Draw this histogram with options.
Definition: TH1.cxx:2878
virtual void SetFillColor(Color_t fcolor)
Definition: TAttFill.h:50
Long64_t fEventsProcessed
Definition: TPerfStats.h:60
Double_t fProcTime
Definition: TPerfStats.h:64
2-D histogram with a float per channel (see TH1 documentation)}
Definition: TH2.h:256
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:674
Int_t GetNanoSec() const
Definition: TTimeStamp.h:141
const char * GetHostFQDN() const
Return fully qualified domain name of url host.
Definition: TUrl.cxx:467
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2321
The most important graphics class in the ROOT system.
Definition: TPad.h:46
static void SetgDebug(Bool_t on=kTRUE)
Static setter for the verbosity level.
TMarker * m
Definition: textangle.C:8
TString fFileName
Definition: TPerfStats.h:57
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
TAxis * GetYaxis()
Definition: TH1.h:320
static double p1(double t, double a, double b)
Bool_t IsNull() const
Definition: TString.h:387
virtual void Print(Option_t *option="") const
Print TNamed name and title.
Definition: TNamed.cxx:117
void SetName(const char *name)
Definition: TCollection.h:116
void WorkerActivity()
Measure the worker activity.
virtual void AddBefore(const TObject *before, TObject *obj)
Insert object before object before in the list.
Definition: TList.cxx:172
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2240
#define Printf
Definition: TGeoToOCC.h:18
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition: TUrl.cxx:385
virtual void Print(Option_t *option="") const
Default print for collections, calls Print(option, 1).
virtual Int_t FindBin(Double_t x)
Find bin number corresponding to abscissa x.
Definition: TAxis.cxx:264
virtual Int_t RedirectOutput(const char *name, const char *mode="a", RedirectHandle_t *h=0)
Redirect standard output (stdout, stderr) to the specified file.
Definition: TSystem.cxx:1677
TString & Remove(Ssiz_t pos)
Definition: TString.h:616
int Ssiz_t
Definition: RtypesCore.h:63
The Canvas class.
Definition: TCanvas.h:48
TTimeStamp fTimeStamp
Definition: TPerfStats.h:53
return c2
Definition: legend2.C:14
virtual Int_t GetSize() const
Definition: TCollection.h:95
TString fSlave
Definition: TPerfStats.h:59
double f(double x)
void GetWrkFileList(TList *wl, TList *sl)
Fill file info.
double Double_t
Definition: RtypesCore.h:55
Describe directory structure in memory.
Definition: TDirectory.h:41
TNamed()
Definition: TNamed.h:40
void DoDraw(TObject *o, Option_t *opt="", const char *name=0)
Draw object 'o' with options 'opt' Save it with 'name' if in saving mode (see SetSaveResult) ...
virtual void SetBinLabel(Int_t bin, const char *label)
Set label for bin.
Definition: TAxis.cxx:793
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:348
Definition: Rtypes.h:61
void FillFileDistOneSrv(TH1F *hx, Bool_t wdet=kFALSE)
Fill file info when there is only one file server.
#define name(a, b)
Definition: linkTestLib0.cpp:5
virtual Double_t GetBinCenter(Int_t bin) const
Return center of bin.
Definition: TAxis.cxx:449
Mother of all ROOT objects.
Definition: TObject.h:58
void FillFileDist(TH1F *hf, TH1F *hb, TH2F *hx, Bool_t wdet=kFALSE)
Fill file info.
Long64_t fBytesRead
Definition: TPerfStats.h:61
virtual TVirtualPad * GetPad(Int_t subpadnumber) const
Get a pointer to subpadnumber of this pad.
Definition: TPad.cxx:2774
virtual void Divide(Int_t nx=1, Int_t ny=1, Float_t xmargin=0.01, Float_t ymargin=0.01, Int_t color=0)
Automatic pad generation by division.
Definition: TPad.cxx:1077
virtual void Add(TObject *obj)
Definition: TList.h:81
const Ssiz_t kNPOS
Definition: Rtypes.h:115
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
A Graph is a graphics object made of two arrays X and Y with npoints each.
Definition: TGraph.h:53
void SetOptStat(Int_t stat=1)
The type of information printed in the histogram statistics box can be selected via the parameter mod...
Definition: TStyle.cxx:1252
Double_t fLatency
Definition: TPerfStats.h:63
virtual Long64_t GetEntries() const
Definition: TTree.h:382
A TTree object has a header with a name and a title.
Definition: TTree.h:94
Definition: Rtypes.h:61
Class describing a generic file including meta information.
Definition: TFileInfo.h:50
void Add(TObject *obj)
void LatencyPlot(const char *wrks=0)
Show event processing or MB processing rate plot vs time Create the histograms.
virtual void Update()
Update canvas pad buffers.
Definition: TCanvas.cxx:2179
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
void FillFileInfo(Bool_t force=kFALSE)
Fill basic worker info; if 'force' rescan the TTree even already done.
const Bool_t kTRUE
Definition: Rtypes.h:91
Int_t Fill(Double_t)
Invalid Fill method.
Definition: TH2.cxx:285
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:459
virtual void SetTitle(const char *title="")
Change (i.e. set) the title of the TNamed.
Definition: TNamed.cxx:152
const Int_t n
Definition: legend1.C:16
void FillWrkInfo(Bool_t force=kFALSE)
Fill basic worker info; if 'force' rescan the TTree even already done.
virtual void SetStats(Bool_t stats=kTRUE)
Set statistics option on/off.
Definition: TH1.cxx:8320
const char * GetFile() const
Definition: TUrl.h:78
TAxis * GetXaxis()
Definition: TH1.h:319
void Summary(Option_t *opt="", const char *out="")
Print summary of query.
virtual void Close(Option_t *option="")
Close a file.
Definition: TFile.cxx:898
void PrintWrkInfo(Int_t showlast=10)
Print information for all or the slowest showlast workers.
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904