ATLAS Offline Software
ReadStats.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // $Id: ReadStats.cxx 642099 2015-01-27 16:43:18Z krasznaa $
6 
7 // System include(s):
8 #include <cstring>
9 #include <functional>
10 #include <algorithm>
11 
12 // ROOT include(s):
13 #include <TCollection.h>
14 #include <TTree.h>
15 #include <TH1.h>
16 
17 // EDM include(s):
20 
21 // Local include(s):
23 #include "xAODCore/tools/Utils.h"
24 
27 
28 namespace {
29 
42  bool sortByEntries( const xAOD::BranchStats& b1,
43  const xAOD::BranchStats& b2 ) {
44 
45  if ( b1.readEntries() > b2.readEntries() ) {
46  return true;
47  }
48  else if ( b1.readEntries() < b2.readEntries() ) {
49  return false;
50  }
51 
52  return strcmp (b1.GetName(), b2.GetName()) < 0;
53  }
54 
65  bool sortByUnzippedBytes( const xAOD::BranchStats& b1,
66  const xAOD::BranchStats& b2 ) {
67 
68  return ( b1.unzippedBytesRead() > b2.unzippedBytesRead() );
69  }
70 
81  class SelectByEntries
82  {
83 
84  public:
86  SelectByEntries( ::Long64_t entries ) : m_entries( entries ) {}
88  SelectByEntries( const xAOD::ReadStats::Map_t& branches,
89  ::Double_t minEvFrac )
90  : m_entries( 0 ) {
91 
92  ::Long64_t maxEntries = 0;
93  xAOD::ReadStats::Vector_t::const_iterator vitr, vend;
94  xAOD::ReadStats::Map_t::const_iterator itr = branches.begin();
95  xAOD::ReadStats::Map_t::const_iterator end = branches.end();
96  for( ; itr != end; ++itr ) {
97  vitr = itr->second.begin();
98  vend = itr->second.end();
99  for( ; vitr != vend; ++vitr ) {
100  if( ! *vitr ) continue;
101  if( ( *vitr )->readEntries() > maxEntries ) {
102  maxEntries = ( *vitr )->readEntries();
103  }
104  }
105  }
106 
107  m_entries = static_cast< ::Long64_t >( minEvFrac * maxEntries );
108  }
109 
111  bool operator()( const xAOD::BranchStats& var ) const {
112 
113  return var.readEntries() >= m_entries;
114  }
115 
116  private:
117  ::Long64_t m_entries;
118 
119  }; // class SelectByEntries
120 
131  class SelectByBytes
132  {
133 
134  public:
136  SelectByBytes( ::Long64_t bytes ) : m_bytes( bytes ) {}
137 
139  SelectByBytes( const xAOD::ReadStats::Map_t& branches,
140  ::Double_t minByteFrac )
141  : m_bytes( 0 ) {
142 
143  ::Long64_t maxBytes = 0;
144  xAOD::ReadStats::Vector_t::const_iterator vitr, vend;
145  xAOD::ReadStats::Map_t::const_iterator itr = branches.begin();
146  xAOD::ReadStats::Map_t::const_iterator end = branches.end();
147  for( ; itr != end; ++itr ) {
148  vitr = itr->second.begin();
149  vend = itr->second.end();
150  for( ; vitr != vend; ++vitr ) {
151  if( ! *vitr ) continue;
152  if( ( *vitr )->zippedBytesRead() > maxBytes ) {
153  maxBytes = ( *vitr )->zippedBytesRead();
154  }
155  }
156  }
157 
158  m_bytes = static_cast< ::Long64_t >( minByteFrac * maxBytes );
159  }
160 
162  bool operator()( const xAOD::BranchStats& var ) const {
163 
164  return var.zippedBytesRead() >= m_bytes;
165  }
166 
167  private:
168  ::Long64_t m_bytes;
169 
170  }; // class SelectByBytes
171 
182  template< class SELECTOR >
183  int addToCache( ::TTree* tree, const xAOD::ReadStats::Map_t& branches,
184  const SELECTOR& selector ) {
185 
186  int result = 0;
187 
188  xAOD::ReadStats::Map_t::const_iterator itr = branches.begin();
189  xAOD::ReadStats::Map_t::const_iterator end = branches.end();
190  for( ; itr != end; ++itr ) {
191  for( size_t auxid = 0; auxid < itr->second.size(); ++auxid ) {
192  if( ! itr->second[ auxid ] ) continue;
193  if( ! selector( *( itr->second[ auxid ] ) ) ) continue;
194  if( tree ) {
195  const std::string brName = itr->first +
197  tree->AddBranchToCache( brName.c_str(), kTRUE );
198  }
199  ++result;
200  }
201  }
202 
203  return result;
204  }
205 
207 
214  template< class SELECTOR >
215  std::vector< std::string >
216  getBranches( const xAOD::ReadStats::Map_t& branches,
217  const SELECTOR& selector ) {
218 
219  // The result object:
220  std::vector< std::string > result;
221 
222  // Iterate over all the variables:
223  xAOD::ReadStats::Map_t::const_iterator itr = branches.begin();
224  xAOD::ReadStats::Map_t::const_iterator end = branches.end();
225  for( ; itr != end; ++itr ) {
226  for( size_t auxid = 0; auxid < itr->second.size(); ++auxid ) {
227  // Check if the object exists:
228  if( ! itr->second[ auxid ] ) continue;
229  // Ignore the ones failing the selection:
230  if( ! selector( *( itr->second[ auxid ] ) ) ) continue;
231  // Add this variable to the result:
232  const std::string brName = itr->first +
234  result.push_back( brName );
235  }
236  }
237 
238  return result;
239  }
240 
241 } // private namespace
242 
243 namespace xAOD {
244 
257  BranchStats::BranchStats( const char* name, const char* type,
258  ::Int_t nTreesAccessed, ::Long64_t nReadEntries,
259  ::Long64_t nUnzippedBytes, ::Long64_t nZippedBytes )
260  : TNamed( name, type ), m_treesAccessed( nTreesAccessed ),
261  m_readEntries( nReadEntries ), m_unzippedBytes( nUnzippedBytes ),
262  m_zippedBytes( nZippedBytes ) {
263 
264  }
265 
271  BranchStats::BranchStats( const BranchStats& parent )
272  : TNamed( parent ), m_treesAccessed( parent.m_treesAccessed ),
273  m_readEntries( parent.m_readEntries ),
274  m_unzippedBytes( parent.m_unzippedBytes ),
275  m_zippedBytes( parent.m_zippedBytes ) {
276 
277  }
278 
285  BranchStats& BranchStats::operator= ( const BranchStats& parent ) {
286 
287  // Check for self-assignment:
288  if( &parent == this ) {
289  return *this;
290  }
291 
292  // Set the properties of TNamed:
293  SetName( parent.GetName() );
294  SetTitle( parent.GetTitle() );
295 
296  // Set the properties of this class:
297  m_treesAccessed = parent.m_treesAccessed;
298  m_readEntries = parent.m_readEntries;
299  m_unzippedBytes = parent.m_unzippedBytes;
300  m_zippedBytes = parent.m_zippedBytes;
301 
302  return *this;
303  }
304 
305  ::Int_t BranchStats::treesAccessed() const {
306 
307  return m_treesAccessed;
308  }
309 
310  void BranchStats::setTreesAccessed( ::Int_t nTreesAccessed ) {
311 
312  m_treesAccessed = nTreesAccessed;
313  return;
314  }
315 
316  ::Long64_t BranchStats::readEntries() const {
317 
318  return m_readEntries;
319  }
320 
321  void BranchStats::setReadEntries( ::Long64_t nReadEntries ) {
322 
323  m_readEntries = nReadEntries;
324  return;
325  }
326 
327  ::Long64_t BranchStats::unzippedBytesRead() const {
328 
329  return m_unzippedBytes;
330  }
331 
332  void BranchStats::setUnzippedBytesRead( ::Long64_t nUnzippedBytes ) {
333 
334  m_unzippedBytes = nUnzippedBytes;
335  return;
336  }
337 
338  ::Long64_t BranchStats::zippedBytesRead() const {
339 
340  return m_zippedBytes;
341  }
342 
343  void BranchStats::setZippedBytesRead( ::Long64_t nZippedBytes ) {
344 
345  m_zippedBytes = nZippedBytes;
346  return;
347  }
348 
349  BranchStats& BranchStats::add( const BranchStats& rh ) {
350 
351  // Set the properties of TNamed:
352  SetName( rh.GetName() );
353  SetTitle( rh.GetTitle() );
354 
355  // Accumulate the gathered statistics:
356  m_treesAccessed += rh.m_treesAccessed;
357  m_readEntries += rh.m_readEntries;
358  m_unzippedBytes += rh.m_unzippedBytes;
359  m_zippedBytes += rh.m_zippedBytes;
360 
361  return *this;
362  }
363 
364  BranchStats& BranchStats::operator+= ( const BranchStats& rh ) {
365 
366  return add( rh );
367  }
368 
376  ::Int_t BranchStats::Merge( ::TCollection* coll ) {
377 
378  // Some security checks:
379  if( ! coll ) return 0;
380  if( coll->IsEmpty() ) return 0;
381 
382  // Iterate over the elements of the collection:
383  ::TIter next( coll );
384  ::TObject* obj = nullptr;
385  ::Int_t result = 0;
386  while( ( obj = next() ) ) {
387 
388  // Check that the element is of the right type:
389  BranchStats* vobj = dynamic_cast< BranchStats* >( obj );
390  if( ! vobj ) {
391  Error( "Merge", "Unknown object type encountered: %s",
392  obj->ClassName() );
393  return 0;
394  }
395 
396  // Add this element to this object:
397  add( *vobj );
398  ++result;
399  }
400 
401  // Return how many objects were merged into this one:
402  return result;
403  }
404 
413  void BranchStats::Print( ::Option_t* option ) const {
414 
415  // Print the most basic info:
416  Info( "Print", "Branch name \"%s\", type \"%s\", read %lli times",
417  GetName(), GetTitle(), m_readEntries );
418 
419  // Print the access statistics only if requested:
420  if( ! ::strcmp( option, "All" ) ) {
421  Info( "Print", " TTrees accessed for this branch: %i",
422  m_treesAccessed );
423  Info( "Print", " Number of entries read : %lli",
424  m_readEntries );
425  Info( "Print", " Number of unzipped bytes read : %lli",
426  m_unzippedBytes );
427  Info( "Print", " Number of zipped bytes read : %lli",
428  m_zippedBytes );
429  }
430 
431  return;
432  }
433 
441  ReadStats::ReadStats( const char* name, const char* title )
442  : ::TNamed( name, title ), m_branches(), m_containers(),
443  m_bytesRead( 0 ), m_branchNum( 0 ),
444  m_fileReads( 0 ), m_cacheSize( 0 ), m_readTime( 0.0 ),
445  m_unzipTime( 0.0 ), m_processTime( 0.0 ),
446  m_nEvents( 0 ), m_nEventsProcessed ( 0 ) {
447 
448  }
449 
455  ReadStats::ReadStats( const ReadStats& parent )
456  : ::TNamed( parent ), m_branches( parent.m_branches ),
457  m_containers(parent.m_containers),
458  m_bytesRead( parent.m_bytesRead ), m_branchNum( parent.m_branchNum ),
459  m_fileReads( parent.m_fileReads ), m_cacheSize( parent.m_cacheSize ),
460  m_readTime( parent.m_readTime ),
461  m_unzipTime( parent.m_unzipTime ),
462  m_processTime( parent.m_processTime ),
463  m_nEvents( parent.m_nEvents ),
464  m_nEventsProcessed( parent.m_nEventsProcessed ){
465 
466  }
467 
471  ReadStats::~ReadStats() {
472 
473  Map_t::iterator mitr = m_branches.begin();
474  Map_t::iterator mend = m_branches.end();
475  for( ; mitr != mend; ++mitr ) {
476  Vector_t::iterator vitr = mitr->second.begin();
477  Vector_t::iterator vend = mitr->second.end();
478  for( ; vitr != vend; ++vitr ) {
479  if( ! *vitr ) continue;
480  delete *vitr;
481  }
482  }
483  }
484 
491  ReadStats& ReadStats::operator= ( const ReadStats& parent ) {
492 
493  // Check for self-assignment:
494  if( &parent == this ) {
495  return *this;
496  }
497 
498  // Set the properties of TNamed:
499  SetName( parent.GetName() );
500  SetTitle( parent.GetTitle() );
501 
502  // Set the properties of this class:
503  m_branches = parent.m_branches;
504  m_containers = parent.m_containers;
505  m_bytesRead = parent.m_bytesRead;
506  m_branchNum = parent.m_branchNum;
507  m_fileReads = parent.m_fileReads;
508  m_cacheSize = parent.m_cacheSize;
509  m_readTime = parent.m_readTime;
510  m_unzipTime = parent.m_unzipTime;
511  m_processTime = parent.m_processTime;
512  m_nEvents = parent.m_nEvents;
513  m_nEventsProcessed = parent.m_nEventsProcessed;
514 
515  return *this;
516  }
517 
518  void ReadStats::Clear( ::Option_t* ) {
519 
520  // Clear all accumulated statistics:
521  m_branches.clear();
522  m_containers.clear();
523  m_bytesRead = 0;
524  m_branchNum = 0;
525  m_fileReads = 0;
526  m_cacheSize = 0;
527  m_readTime = 0.0;
528  m_unzipTime = 0.0;
529  m_processTime = 0.0;
530  m_nEvents = 0;
531  m_nEventsProcessed = 0;
532 
533  return;
534  }
535 
536  void ReadStats::setBytesRead( ::Long64_t num ) {
537 
538  m_bytesRead = num;
539  return;
540  }
541 
542  ::Long64_t ReadStats::bytesRead() const {
543 
544  return m_bytesRead;
545  }
546 
547  void ReadStats::setBranchNum( ::Int_t num ) {
548 
549  m_branchNum = num;
550  return;
551  }
552 
553  ::Int_t ReadStats::branchNum() const {
554 
555  return m_branchNum;
556  }
557 
558  void ReadStats::setFileReads( ::Int_t num ) {
559 
560  m_fileReads = num;
561  return;
562  }
563 
564  ::Int_t ReadStats::fileReads() const {
565 
566  return m_fileReads;
567  }
568 
569  void ReadStats::setCacheSize( ::Int_t size ) {
570 
571  m_cacheSize = size;
572  return;
573  }
574 
575  ::Int_t ReadStats::cacheSize() const {
576 
577  return m_cacheSize;
578  }
579 
580  void ReadStats::setReadTime( ::Double_t time ) {
581 
582  m_readTime = time;
583  return;
584  }
585 
586  ::Double_t ReadStats::readTime() const {
587 
588  return m_readTime;
589  }
590 
591  void ReadStats::setUnzipTime( ::Double_t time ) {
592 
593  m_unzipTime = time;
594  return;
595  }
596 
597  ::Double_t ReadStats::unzipTime() const {
598 
599  return m_unzipTime;
600  }
601 
602  void ReadStats::setProcessTime( ::Double_t time ) {
603 
604  m_processTime = time;
605  return;
606  }
607 
608  ::Double_t ReadStats::processTime() const {
609 
610  return m_processTime;
611  }
612 
620  BranchStats* ReadStats::branch( const std::string& prefix,
621  SG::auxid_t auxid ) {
622 
623  Vector_t& vec = m_branches[ prefix ];
624  // Check if it's big enough:
625  if( vec.size() <= auxid ) {
626  vec.resize( auxid + 1 );
627  }
628  // Check if the object exists already:
629  if( ! vec[ auxid ] ) {
630  // Construct its name, mangling needed for dynamic variables:
631  const std::string brName = prefix +
633  const std::type_info* brType =
635  if( ! brType ) {
636  Error( "branch", "Coudln't find type_info for aux ID %i",
637  static_cast< int >( auxid ) );
638  return nullptr;
639  }
640  const std::string brTypeName = SG::normalizedTypeinfoName( *brType );
641 
642  // Construct the new object:
643  vec[ auxid ] = new BranchStats( brName.c_str(), brTypeName.c_str() );
644  }
645 
646  // Return the object:
647  return vec[ auxid ];
648  }
649 
657  const BranchStats* ReadStats::branch( const std::string& prefix,
658  SG::auxid_t auxid ) const {
659 
660  // Search for the variable:
661  Map_t::const_iterator itr = m_branches.find( prefix );
662  if( itr != m_branches.end() ) {
663  const Vector_t& vec = itr->second;
664  if( ( vec.size() > auxid ) && vec[ auxid ] ) {
665  return vec[ auxid ];
666  }
667  }
668 
669  // Return a null pointer if the object was not found:
670  return nullptr;
671  }
672 
673  BranchStats* ReadStats::container( const std::string& name ) {
674 
675  // If it doesn't exist yet, create it now:
676  auto ret = m_containers.try_emplace (name, name.c_str(), "CONTAINER");
677  // Return a pointer to the object:
678  return &ret.first->second;
679  }
680 
681  const BranchStats* ReadStats::container( const std::string& name ) const {
682 
683  // Try to find it:
684  MapC_t::const_iterator itr = m_containers.find( name );
685  if( itr != m_containers.end() ) {
686  return &( itr->second );
687  }
688 
689  // We didn't find it:
690  return nullptr;
691  }
692 
693  const ReadStats::Map_t& ReadStats::branches() const {
694 
695  return m_branches;
696  }
697 
698  const ReadStats::MapC_t& ReadStats::containers() const {
699 
700  return m_containers;
701  }
702 
712  bool ReadStats::isCompatible( const ReadStats& rh ) const {
713 
714  return ( m_branchNum == rh.branchNum() ) &&
715 
716  ( m_cacheSize == rh.cacheSize() );
717  }
718 
724  ReadStats& ReadStats::add( const ReadStats& rh ) {
725 
726  // Merge the variable statistics one by one:
727  Map_t::const_iterator itr = rh.m_branches.begin();
728  Map_t::const_iterator end = rh.m_branches.end();
729  for( ; itr != end; ++itr ) {
730  const Vector_t& rhvec = itr->second;
731  Vector_t& vec = m_branches[ itr->first ];
732  if( vec.size() < rhvec.size() ) {
733  vec.resize( rhvec.size() );
734  }
735  for( size_t auxid = 0; auxid < rhvec.size(); ++auxid ) {
736  if( ! rhvec[ auxid ] ) continue;
737  if( ! vec[ auxid ] ) {
738  vec[ auxid ] = new BranchStats();
739  }
740  vec[ auxid ]->add( *( rhvec[ auxid ] ) );
741  }
742  }
743 
744  // Sum up the simple statistics:
745  m_bytesRead += rh.m_bytesRead;
746  m_fileReads += rh.m_fileReads;
747  m_readTime += rh.m_readTime;
748  m_unzipTime += rh.m_unzipTime;
749  m_processTime += rh.m_processTime;
750 
751  return *this;
752  }
753 
754  ReadStats& ReadStats::operator+= ( const ReadStats& rh ) {
755 
756  return add( rh );
757  }
758 
767  void ReadStats::addToTreeCache( ::TTree* tree ) const {
768 
769  // Add all the branches to the cache:
770  const int counter = addToCache( tree, m_branches,
771  SelectByEntries( 0 ) );
772 
773  // Let the user know what we did:
774  Info( "addToTreeCache", "Added %i branches to the TTreeCache",
775  counter );
776 
777  return;
778  }
779 
788  void ReadStats::addToTreeCacheByEntries( ::TTree* tree,
789  ::Long64_t minEntries ) const {
790 
791  // Add the selected branches to the cache:
792  const int counter = addToCache( tree, m_branches,
793  SelectByEntries( minEntries ) );
794 
795  // Let the user know what we did:
796  Info( "addToTreeCacheByEntries", "Added %i branches to the TTreeCache",
797  counter );
798 
799  return;
800  }
801 
812  void ReadStats::addToTreeCacheByEntryFrac( ::TTree* tree,
813  ::Double_t minEvFraction ) const {
814 
815  // Add the selected branches to the cache:
816  const int counter = addToCache( tree, m_branches,
817  SelectByEntries( m_branches,
818  minEvFraction ) );
819 
820  // Let the user know what we did:
821  Info( "addToTreeCacheByEntries", "Added %i branches to the TTreeCache",
822  counter );
823 
824  return;
825  }
826 
834  void ReadStats::addToTreeCacheByBytes( ::TTree* tree,
835  ::Long64_t minBytes ) const {
836 
837  // Add the selected branches to the cache:
838  const int counter = addToCache( tree, m_branches,
839  SelectByBytes( minBytes ) );
840 
841  // Let the user know what we did:
842  Info( "addToTreeCacheByBytes", "Added %i branches to the TTreeCache",
843  counter );
844 
845  return;
846  }
847 
856  void
857  ReadStats::addToTreeCacheByByteFrac( ::TTree* tree,
858  ::Double_t minByteFraction ) const {
859 
860  // Add the selected branches to the cache:
861  const int counter = addToCache( tree, m_branches,
862  SelectByBytes( m_branches,
863  minByteFraction ) );
864 
865  // Let the user know what we did:
866  Info( "addToTreeCacheByBytes", "Added %i branches to the TTreeCache",
867  counter );
868 
869  return;
870  }
871 
878  std::vector< std::string >
879  ReadStats::branchesByEntries( ::Long64_t minEntries ) const {
880 
881  return getBranches( m_branches, SelectByEntries( minEntries ) );
882  }
883 
890  std::vector< std::string >
891  ReadStats::branchesByEntryFrac( ::Double_t minEvFrac ) const {
892 
893  return getBranches( m_branches,
894  SelectByEntries( m_branches, minEvFrac ) );
895  }
896 
903  std::vector< std::string >
904  ReadStats::branchesByBytes( ::Long64_t minBytes ) const {
905 
906  return getBranches( m_branches, SelectByBytes( minBytes ) );
907  }
908 
916  std::vector< std::string >
917  ReadStats::branchesByByteFrac( ::Double_t minByteFraction ) const {
918 
919  return getBranches( m_branches,
920  SelectByBytes( m_branches, minByteFraction ) );
921  }
922 
930  ::TH1* ReadStats::treeAccessStat() const {
931 
932  // Find the branch(es) which accessed the most trees:
933  ::Long64_t maxTrees = 0;
934  Vector_t::const_iterator vitr, vend;
935  Map_t::const_iterator itr = m_branches.begin();
936  Map_t::const_iterator end = m_branches.end();
937  for( ; itr != end; ++itr ) {
938  vitr = itr->second.begin();
939  vend = itr->second.end();
940  for( ; vitr != vend; ++vitr ) {
941  if( ! *vitr ) continue;
942  if( ( *vitr )->treesAccessed() > maxTrees ) {
943  maxTrees = ( *vitr )->treesAccessed();
944  }
945  }
946  }
947 
948  // Create the histogram:
949  ::TH1* result = new ::TH1D( "TreeAccessStat",
950  "TTree access statistics;TTrees;Branches",
951  100, 0.0, ( ( ::Double_t ) maxTrees ) * 1.1 );
952 
953  // Fill the histogram by looping over the variables once more:
954  itr = m_branches.begin();
955  end = m_branches.end();
956  for( ; itr != end; ++itr ) {
957  vitr = itr->second.begin();
958  vend = itr->second.end();
959  for( ; vitr != vend; ++vitr ) {
960  if( ! *vitr ) continue;
961  result->Fill( ( ::Double_t ) ( *vitr )->treesAccessed() );
962  }
963  }
964 
965  return result;
966  }
967 
975  ::TH1* ReadStats::entryReadStat() const {
976 
977  // Find the branch(es) which accessed the most entries:
978  ::Long64_t maxEntries = 0;
979  Vector_t::const_iterator vitr, vend;
980  Map_t::const_iterator itr = m_branches.begin();
981  Map_t::const_iterator end = m_branches.end();
982  for( ; itr != end; ++itr ) {
983  vitr = itr->second.begin();
984  vend = itr->second.end();
985  for( ; vitr != vend; ++vitr ) {
986  if( ! *vitr ) continue;
987  if( ( *vitr )->readEntries() > maxEntries ) {
988  maxEntries = ( *vitr )->readEntries();
989  }
990  }
991  }
992 
993  // Create the histogram:
994  ::TH1* result = new ::TH1D( "EntryAccessStat",
995  "Entry access statistics;Entries;Branches",
996  100, 0.0,
997  ( ( ::Double_t ) maxEntries ) * 1.1 );
998 
999  // Fill the histogram by looping over the variables once more:
1000  itr = m_branches.begin();
1001  end = m_branches.end();
1002  for( ; itr != end; ++itr ) {
1003  vitr = itr->second.begin();
1004  vend = itr->second.end();
1005  for( ; vitr != vend; ++vitr ) {
1006  if( ! *vitr ) continue;
1007  result->Fill( ( ::Double_t ) ( *vitr )->readEntries() );
1008  }
1009  }
1010 
1011  return result;
1012  }
1013 
1021  ::TH1* ReadStats::zippedByteReadStat() const {
1022 
1023  // Find the branch(es) which accessed the most bytes:
1024  ::Long64_t maxBytes = 0;
1025  Vector_t::const_iterator vitr, vend;
1026  Map_t::const_iterator itr = m_branches.begin();
1027  Map_t::const_iterator end = m_branches.end();
1028  for( ; itr != end; ++itr ) {
1029  vitr = itr->second.begin();
1030  vend = itr->second.end();
1031  for( ; vitr != vend; ++vitr ) {
1032  if( ! *vitr ) continue;
1033  if( ( *vitr )->zippedBytesRead() > maxBytes ) {
1034  maxBytes = ( *vitr )->zippedBytesRead();
1035  }
1036  }
1037  }
1038 
1039  // Create the histogram:
1040  ::TH1* result = new ::TH1D( "ZippedByteAccessStat",
1041  "Zipped byte access statistics;Bytes;Branches",
1042  100, 0.0, ( ( ::Double_t ) maxBytes ) * 1.1 );
1043 
1044  // Fill the histogram by looping over the variables once more:
1045  itr = m_branches.begin();
1046  end = m_branches.end();
1047  for( ; itr != end; ++itr ) {
1048  vitr = itr->second.begin();
1049  vend = itr->second.end();
1050  for( ; vitr != vend; ++vitr ) {
1051  if( ! *vitr ) continue;
1052  result->Fill( ( ::Double_t ) ( *vitr )->zippedBytesRead() );
1053  }
1054  }
1055 
1056  return result;
1057  }
1058 
1066  ::TH1* ReadStats::unzippedByteReadStat() const {
1067 
1068  // Find the branch(es) which accessed the most bytes:
1069  ::Long64_t maxBytes = 0;
1070  Vector_t::const_iterator vitr, vend;
1071  Map_t::const_iterator itr = m_branches.begin();
1072  Map_t::const_iterator end = m_branches.end();
1073  for( ; itr != end; ++itr ) {
1074  vitr = itr->second.begin();
1075  vend = itr->second.end();
1076  for( ; vitr != vend; ++vitr ) {
1077  if( ! *vitr ) continue;
1078  if( ( *vitr )->unzippedBytesRead() > maxBytes ) {
1079  maxBytes = ( *vitr )->unzippedBytesRead();
1080  }
1081  }
1082  }
1083 
1084  // Create the histogram:
1085  ::TH1* result =
1086  new ::TH1D( "UnzippedByteAccessStat",
1087  "Unzipped byte access statistics;Bytes;Branches",
1088  100, 0.0, ( ( ::Double_t ) maxBytes ) * 1.1 );
1089 
1090  // Fill the histogram by looping over the variables once more:
1091  itr = m_branches.begin();
1092  end = m_branches.end();
1093  for( ; itr != end; ++itr ) {
1094  vitr = itr->second.begin();
1095  vend = itr->second.end();
1096  for( ; vitr != vend; ++vitr ) {
1097  if( ! *vitr ) continue;
1098  result->Fill( ( ::Double_t ) ( *vitr )->unzippedBytesRead() );
1099  }
1100  }
1101 
1102  return result;
1103  }
1104 
1112  ::Int_t ReadStats::Merge( ::TCollection* coll ) {
1113 
1114  // Some security checks:
1115  if( ! coll ) return 0;
1116  if( coll->IsEmpty() ) return 0;
1117 
1118  // Iterate over the elements of the collection:
1119  ::TIter next( coll );
1120  ::TObject* obj = nullptr;
1121  ::Int_t result = 0;
1122  while( ( obj = next() ) ) {
1123 
1124  // Check that the element is of the right type:
1125  ReadStats* dobj = dynamic_cast< ReadStats* >( obj );
1126  if( ! dobj ) {
1127  Error( "Merge", "Unknown object type encountered: %s",
1128  obj->ClassName() );
1129  return 0;
1130  }
1131 
1132  // The compatibility of the objects is no longer checked. When
1133  // processing a large dataset, it's probable that the objects
1134  // created by the different PROOF workers will not be "compatible".
1135 
1136  // Add this element to this object:
1137  add( *dobj );
1138  ++result;
1139  }
1140 
1141  return result;
1142  }
1143 
1156  void ReadStats::Print( ::Option_t* option ) const {
1157 
1158  Info( "Print", "Printing xAOD I/O statistics" );
1159 
1160  // Create a temporary vector of the containers, so they can be ordered
1161  // if necessary:
1162  std::vector< BranchStats > conts;
1163  MapC_t::const_iterator cont_itr = m_containers.begin();
1164  MapC_t::const_iterator cont_end = m_containers.end();
1165  for( ; cont_itr != cont_end; ++cont_itr ) {
1166  conts.push_back( cont_itr->second );
1167  }
1168 
1169  // Create a temporary vector of the branches, so they can be ordered
1170  // if necessary:
1171  std::vector< BranchStats > vars;
1172  Vector_t::const_iterator vec_itr, vec_end;
1173  Map_t::const_iterator map_itr = m_branches.begin();
1174  Map_t::const_iterator map_end = m_branches.end();
1175  for( ; map_itr != map_end; ++map_itr ) {
1176  vec_itr = map_itr->second.begin();
1177  vec_end = map_itr->second.end();
1178  for( ; vec_itr != vec_end; ++vec_itr ) {
1179  if( ! *vec_itr ) continue;
1180  vars.push_back( **vec_itr );
1181  }
1182  }
1183 
1184  // Container and branch access summary
1185  if( ! ::strcmp( option, "SmartSlimming" ) ) {
1186 
1187  Info( "Print", " " );
1188  Info( "Print", "Smart Slimming Statistics" );
1189  Info( "Print", " " );
1190 
1191  const Double_t proFrac = ( ( Double_t ) m_nEventsProcessed /
1192  ( Double_t ) m_nEvents ) * 100.0;
1193  Info( "Print", " Processed %lli events from %lli (%g%%)",
1194  m_nEventsProcessed, m_nEvents, proFrac );
1195 
1196  Info( "Print", " Number of containers in on the input: %i",
1197  static_cast< int >( m_containers.size() ) );
1198  Info( "Print", " Number of branches on the input: %i",
1199  static_cast< int >( vars.size() ) );
1200 
1201  // Sort the containers by number of accesses:
1202  std::sort( conts.begin(), conts.end(), sortByEntries );
1203 
1204  // Print which containers got accessed:
1205  Info( "Print", " " );
1206  Info( "Print", "Accessed containers:" );
1207  Info( "Print", " " );
1208  std::vector< BranchStats >::const_iterator itr = conts.begin();
1209  std::vector< BranchStats >::const_iterator end = conts.end();
1210  for( ; itr != end; ++itr ) {
1211  if( ! itr->readEntries() ) continue;
1212  itr->Print( option );
1213  }
1214 
1215  // Sort the branches by number of accesses:
1216  std::sort( vars.begin(), vars.end(), sortByEntries );
1217 
1218  // Print which branches got accessed:
1219  Info( "Print", " " );
1220  Info( "Print", "Accessed branches:" );
1221  Info( "Print", " " );
1222  itr = vars.begin();
1223  end = vars.end();
1224  for( ; itr != end; ++itr ) {
1225  if( ! itr->readEntries() ) continue;
1226  itr->Print( option );
1227  }
1228  Info( "Print", " " );
1229 
1230  // Let's exit at this point:
1231  return;
1232  }
1233 
1234  // Print the summary information:
1235  Info( "Print", " Number of variables in the input xAOD : %i",
1236  m_branchNum );
1237  const Double_t proFrac = ( ( Double_t ) m_nEventsProcessed /
1238  ( Double_t ) m_nEvents ) * 100.0;
1239  Info( "Print", " Processed events : "
1240  "%lli/%lli (%g%%)", m_nEventsProcessed, m_nEvents, proFrac );
1241  Info( "Print", " TTreeCache size used : %s",
1242  Utils::sizeToString( m_cacheSize ).c_str() );
1243  Info( "Print", " Total number of bytes read : %s",
1244  Utils::sizeToString( m_bytesRead ).c_str() );
1245  Info( "Print", " Data reading speed per process : %s",
1246  ( std::abs( m_processTime ) > 0.0001 ?
1247  Utils::speedToString( m_bytesRead / m_processTime ).c_str() :
1248  "N/A" ) );
1249  Info( "Print", " Total number of file read operations : %i",
1250  m_fileReads );
1251  const ::Long64_t readInOneGo =
1252  ( ::Long64_t ) ( ( ::Double_t ) m_bytesRead /
1253  ( ::Double_t ) m_fileReads );
1254  Info( "Print", " Data read in one go (on average) : %s",
1255  Utils::sizeToString( readInOneGo ).c_str() );
1256  Info( "Print", " Cumulative time spent processing data : %s (%s/event)",
1257  Utils::timeToString( m_processTime ).c_str(),
1258  ( m_nEventsProcessed ?
1259  Utils::timeToString( m_processTime / m_nEventsProcessed ).c_str() :
1260  "N/A" ) );
1261  Info( "Print", " Cumulative time spent reading data : %s (%s/event)",
1262  Utils::timeToString( m_readTime ).c_str(),
1263  ( m_nEventsProcessed ?
1264  Utils::timeToString( m_readTime / m_nEventsProcessed ).c_str() :
1265  "N/A" ) );
1266  Info( "Print", " Cumulative time spent unzipping data : %s (%s/event)",
1267  Utils::timeToString( m_unzipTime ).c_str(),
1268  ( m_nEventsProcessed ?
1269  Utils::timeToString( m_unzipTime / m_nEventsProcessed ).c_str() :
1270  "N/A" ) );
1271 
1272  // If we just needed summary information, stop here:
1273  if( ! ::strcmp( option, "Summary" ) ) {
1274  return;
1275  }
1276 
1277  // Select the kind of ordering for the containers:
1278  if( ! ::strcmp( option, "ByEntries" ) ) {
1279  Info( "Print", "Containers, sorted by number of accesses:" );
1280  std::sort( conts.begin(), conts.end(), sortByEntries );
1281  } else if( ! ::strcmp( option, "ByBytes" ) ) {
1282  Info( "Print", "Containers, sorted by number of bytes read:" );
1283  std::sort( conts.begin(), conts.end(), sortByUnzippedBytes );
1284  } else {
1285  Info( "Print", "Containers, sorted by name:" );
1286  }
1287 
1288  // Print the statistics from each container:
1289  std::vector< BranchStats >::const_iterator itr = conts.begin();
1290  std::vector< BranchStats >::const_iterator end = conts.end();
1291  for( ; itr != end; ++itr ) {
1292  itr->Print( option );
1293  }
1294 
1295  // Select the kind of ordering for the variables:
1296  if( ! ::strcmp( option, "ByEntries" ) ) {
1297  Info( "Print", "Variables, sorted by number of accesses:" );
1298  std::sort( vars.begin(), vars.end(), sortByEntries );
1299  } else if( ! ::strcmp( option, "ByBytes" ) ) {
1300  Info( "Print", "Variables, sorted by number of bytes read:" );
1301  std::sort( vars.begin(), vars.end(), sortByUnzippedBytes );
1302  } else {
1303  Info( "Print", "Variables, sorted by name:" );
1304  }
1305 
1306  // Print the statistics from each variable:
1307  itr = vars.begin();
1308  end = vars.end();
1309  for( ; itr != end; ++itr ) {
1310  itr->Print( option );
1311  }
1312 
1313  return;
1314  }
1315 
1326  void ReadStats::printSmartSlimmingBranchList( bool autoIncludeLinks ) const {
1327 
1329  std::map< ::TString, ::TString > items;
1330 
1331  // Collect all the containers that were accessed during the job:
1332  MapC_t::const_iterator cont_itr = m_containers.begin();
1333  MapC_t::const_iterator cont_end = m_containers.end();
1334  for( ; cont_itr != cont_end; ++cont_itr ) {
1335  // Skip non-accessed containers:
1336  if( ! cont_itr->second.readEntries() ) continue;
1337  // Remember the container:
1338  items[ cont_itr->first ] = "";
1339  }
1340 
1341  // Now look for variables in all these containers:
1342  Map_t::const_iterator br_itr = m_branches.begin();
1343  Map_t::const_iterator br_end = m_branches.end();
1344  for( ; br_itr != br_end; ++br_itr ) {
1345  // First check if any variables got accessed. It has an effect on what
1346  // to do with the ElementLink types.
1347  bool containerAccessed = false;
1348  Vector_t::const_iterator itr = br_itr->second.begin();
1349  Vector_t::const_iterator end = br_itr->second.end();
1350  for( ; itr != end; ++itr ) {
1351  if( ( *itr ) && ( *itr )->readEntries() ) {
1352  containerAccessed = true;
1353  break;
1354  }
1355  }
1356  // If none were accessed, abandon this container:
1357  if( ! containerAccessed ) continue;
1358  // Now collect all the variables:
1359  for( ; itr != end; ++itr ) {
1360  // Check if it's an ElementLink type:
1361  const bool linkType =
1362  ( ( *itr ) &&
1363  ::TString( ( *itr )->GetTitle() ).Contains( "ElementLink" ) );
1364  // Skip non-existent, non-accessed, and not requested link
1365  // variables:
1366  if( ( ( ! *itr ) || ( ! ( *itr )->readEntries() ) ) &&
1367  ( ! ( autoIncludeLinks && linkType ) ) ) continue;
1368  // Extract the name of the container and the variable from the
1369  // branch's name:
1370  const ::TString brname = ( *itr )->GetName();
1371  const ::Size_t dotPos = brname.First( '.' );
1372  if( dotPos == ::kNPOS ) {
1373  // Ignore the unknown containers:
1374  continue;
1375  }
1376  const ::TString cname = brname( 0, dotPos + 1 );
1377  const ::TString vname = brname( dotPos + 1,
1378  brname.Length() - dotPos );
1379  // Access the current variable list:
1380  ::TString& vars = items[ cname ];
1381  // Add a dot if there are already variables defined:
1382  if( vars.Length() ) {
1383  vars.Append( '.' );
1384  }
1385  // Add this variable:
1386  vars.Append( vname );
1387  }
1388  }
1389 
1390  // Print the collected information:
1391  Info( "printSmartSlimmingBranchList", "ItemList to use:" );
1392  if( autoIncludeLinks ) {
1393  Info( "printSmartSlimmingBranchList", "(All link variables added)" );
1394  }
1395  std::map< ::TString, ::TString >::const_iterator itr = items.begin();
1396  std::map< ::TString, ::TString >::const_iterator end = items.end();
1397  for( ; itr != end; ++itr ) {
1398  if( itr->first.EndsWith( "Aux." ) ) {
1399  Info( "printSmartSlimmingBranchList", " %s%s",
1400  itr->first.Data(),
1401  ( itr->second.Length() ? itr->second.Data() : "-" ) );
1402  } else {
1403  Info( "printSmartSlimmingBranchList", " %s",
1404  itr->first.Data() );
1405  }
1406  }
1407 
1408  // Return gracefully:
1409  return;
1410  }
1411 
1412  void ReadStats::nextEvent(){
1413 
1414  // event counters
1415  ++m_nEventsProcessed;
1416  return;
1417  }
1418 
1419  ::Long64_t ReadStats::nEvents() const {
1420 
1421  return m_nEvents;
1422  }
1423 
1424  void ReadStats::setNEvents( ::Long64_t nevents ) {
1425 
1426  m_nEvents = nevents;
1427  return;
1428  }
1429 
1430  void ReadStats::readBranch( const std::string& prefix,
1431  SG::auxid_t auxid ){
1432 
1433  // Access the branch:
1434  BranchStats* stat = branch( prefix, auxid );
1435  // Increment its access counter:
1436  stat->setReadEntries( stat->readEntries() + 1 );
1437  return;
1438  }
1439 
1440  void ReadStats::readContainer( const std::string& name ){
1441 
1442  // Access the branch:
1443  BranchStats* stat = container( name );
1444  // Increment its access counter:
1445  stat->setReadEntries( stat->readEntries() + 1 );
1446  return;
1447  }
1448 
1449 } // namespace D3PDReader
xAOD::BranchStats::unzippedBytesRead
::Long64_t unzippedBytesRead() const
Get how many unzipped bytes were read from this branch in total.
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
xAOD::Utils::sizeToString
std::string sizeToString(::Long64_t bytes)
Function for printing data sizes in human-readable format.
Definition: Event/xAOD/xAODCore/Root/Utils.cxx:129
beamspotnt.var
var
Definition: bin/beamspotnt.py:1394
xAOD::name
name
Definition: TriggerMenuJson_v1.cxx:29
xAOD::Utils::speedToString
std::string speedToString(::Double_t bytespersec)
Function for printing data processing speeds in a human-readable format.
Definition: Event/xAOD/xAODCore/Root/Utils.cxx:151
checkxAOD.brName
brName
Definition: Tools/PyUtils/bin/checkxAOD.py:113
get_generator_info.result
result
Definition: get_generator_info.py:21
SG::AuxTypeRegistry::instance
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Definition: AuxTypeRegistry.cxx:49
SG::normalizedTypeinfoName
std::string normalizedTypeinfoName(const std::type_info &info)
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
Definition: normalizedTypeinfoName.cxx:120
SG::AuxTypeRegistry::getName
std::string getName(SG::auxid_t auxid) const
Return the name of an aux data item.
Definition: AuxTypeRegistry.cxx:277
tree
TChain * tree
Definition: tile_monitor.h:30
xAOD::ReadStats::Map_t
std::map< std::string, Vector_t > Map_t
Type of the internal object gathering information on aux branches.
Definition: ReadStats.h:129
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:12
ZDCMsg::Info
@ Info
Definition: ZDCMsg.h:20
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
ClassImp
ClassImp(xAOD::TFileChecker) namespace xAOD
Definition: TFileChecker.cxx:28
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
runLayerRecalibration.branches
list branches
Definition: runLayerRecalibration.py:98
SG::auxid_t
size_t auxid_t
Identifier for a particular aux data item.
Definition: AuxTypes.h:27
SG::AuxTypeRegistry::getType
const std::type_info * getType(SG::auxid_t auxid) const
Return the type of an aux data item.
Definition: AuxTypeRegistry.cxx:302
ReadStats.h
fillPileUpNoiseLumi.next
next
Definition: fillPileUpNoiseLumi.py:52
IsoCloseByCorrectionTest.containers
containers
Associate the close-by pflow objects and the calorimeter clusters.
Definition: IsoCloseByCorrectionTest.py:82
xAOD::BranchStats::readEntries
::Long64_t readEntries() const
Get how many entries were read from this branch.
ret
T ret(T t)
Definition: rootspy.cxx:260
covarianceTool.title
title
Definition: covarianceTool.py:542
Utils.h
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
xAOD::BranchStats
Class describing the access statistics of one (sub-)branch.
Definition: ReadStats.h:43
test_pyathena.parent
parent
Definition: test_pyathena.py:15
add
bool add(const std::string &hname, TKey *tobj)
Definition: fastadd.cxx:55
nEvents
int nEvents
Definition: fbtTestBasics.cxx:77
xAOD::BranchStats::BranchStats
BranchStats(const char *name="xAODBranch", const char *type="Int_t", ::Int_t nTreesAccessed=0, ::Long64_t nReadEntries=0, ::Long64_t nUnzippedBytes=0, ::Long64_t nZippedBytes=0)
Constructor specifying all parameters.
beamspotman.stat
stat
Definition: beamspotman.py:266
normalizedTypeinfoName.h
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
trigbs_pickEvents.num
num
Definition: trigbs_pickEvents.py:76
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
xAOD::Utils::timeToString
std::string timeToString(::Double_t secs)
Function creating a human-readable elapsed time printout.
Definition: Event/xAOD/xAODCore/Root/Utils.cxx:99
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:79
RTTAlgmain.branch
branch
Definition: RTTAlgmain.py:61
python.selector.AtlRunQuerySelectorLhcOlc.selector
selector
Definition: AtlRunQuerySelectorLhcOlc.py:611
CaloSwCorrections.time
def time(flags, cells_name, *args, **kw)
Definition: CaloSwCorrections.py:242
std::sort
void sort(typename std::reverse_iterator< DataModel_detail::iterator< DVL > > beg, typename std::reverse_iterator< DataModel_detail::iterator< DVL > > end, const Compare &comp)
Specialization of sort for DataVector/List.
Definition: DVL_algorithms.h:623
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
TH1
Definition: rootspy.cxx:268
AuxTypeRegistry.h
Handle mappings between names and auxid_t.
dqm_persistency::Print
void Print(const PParameter *param, TDirectory *topdir, Option_t *opt="")
Definition: dqm_persistency_impl.cxx:161
entries
double entries
Definition: listroot.cxx:49
L1Topo::Error
Error
The different types of error that can be flagged in the L1TopoRDO.
Definition: Error.h:16
LArG4GenerateShowerLib.nevents
nevents
Definition: LArG4GenerateShowerLib.py:19
xAOD::ReadStats
Class describing the access statistics of a collection of branches.
Definition: ReadStats.h:123
test_pyathena.counter
counter
Definition: test_pyathena.py:15
python.PyAthena.obj
obj
Definition: PyAthena.py:135