ATLAS Offline Software
Loading...
Searching...
No Matches
ReadStats.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 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):
24
27
28namespace {
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( std::move( brName ) );
235 }
236 }
237
238 return result;
239 }
240
241} // private namespace
242
243namespace 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
Handle mappings between names and auxid_t.
std::vector< size_t > vec
ClassImp(xAOD::Experimental::RFileChecker) namespace xAOD
const std::type_info * getType(SG::auxid_t auxid) const
Return the type of an aux data item.
std::string getName(SG::auxid_t auxid) const
Return the name of an aux data item.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Class describing the access statistics of one (sub-)branch.
Definition ReadStats.h:43
::Long64_t unzippedBytesRead() const
Get how many unzipped bytes were read from this branch in total.
::Long64_t readEntries() const
Get how many entries were read from this branch.
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.
Class describing the access statistics of a collection of branches.
Definition ReadStats.h:123
std::map< std::string, Vector_t > Map_t
Type of the internal object gathering information on aux branches.
Definition ReadStats.h:129
bool add(const std::string &hname, TKey *tobj)
Definition fastadd.cxx:55
double entries
Definition listroot.cxx:49
time(flags, cells_name, *args, **kw)
Error
The different types of error that can be flagged in the L1TopoRDO.
Definition Error.h:16
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...
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27
@ Info
Definition ZDCMsg.h:20
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
TChain * tree