00001
00005 #include "PerfTools/EdmEvent/interface/EdmEventSize.h"
00006 #include <valarray>
00007 #include <functional>
00008 #include <algorithm>
00009 #include <boost/bind.hpp>
00010 #include <ostream>
00011 #include <limits>
00012 #include <assert.h>
00013
00014 #include "TROOT.h"
00015 #include "TFile.h"
00016 #include "TTree.h"
00017 #include "TStyle.h"
00018 #include "TObjArray.h"
00019 #include "TBranch.h"
00020 #include "TH1.h"
00021 #include "TCanvas.h"
00022 #include "Riostream.h"
00023
00024
00025
00026 #include "RVersion.h"
00027 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,15,0)
00028 #include "TBufferFile.h"
00029 typedef TBufferFile PerfRootBuffer;
00030 #else
00031 #include "TBuffer.h"
00032 typedef TBuffer PerfRootBuffer;
00033 #endif
00034
00035 namespace {
00036
00037 typedef std::valarray<size_t> size_type;
00038
00039 size_type getBasketSize( TBranch *);
00040
00041 size_type getBasketSize( TObjArray * branches) {
00042 size_type result(size_t(0),2);
00043 size_t n = branches->GetEntries();
00044 for( size_t i = 0; i < n; ++ i ) {
00045 TBranch * b = dynamic_cast<TBranch*>( branches->At( i ) );
00046 assert( b != 0 );
00047 result += getBasketSize(b);
00048 }
00049 return result;
00050 }
00051
00052 size_type getBasketSize( TBranch * b) {
00053 size_type result(size_t(0),2);
00054 if ( b != 0 ) {
00055 if ( b->GetZipBytes() > 0 ) {
00056 result[0] = b->GetTotBytes(); result[1] = b->GetZipBytes();
00057 } else {
00058 result[0] = b->GetTotalSize(); result[1] = b->GetTotalSize();
00059 }
00060 result += getBasketSize( b->GetListOfBranches() );
00061 }
00062 return result;
00063 }
00064
00065
00066 size_type getTotalSize( TBranch * br) {
00067 PerfRootBuffer buf( TBuffer::kWrite, 10000 );
00068 TBranch::Class()->WriteBuffer( buf, br );
00069 size_type size = getBasketSize(br);
00070 if ( br->GetZipBytes() > 0 )
00071 size[0] += buf.Length();
00072 return size;
00073 }
00074 }
00075
00076 namespace perftools {
00077
00078 EdmEventSize::EdmEventSize() :
00079 m_nEvents(0) {}
00080
00081 EdmEventSize::EdmEventSize(std::string const & fileName, std::string const & treeName ) :
00082 m_nEvents(0) {
00083 parseFile(fileName);
00084 }
00085
00086 void EdmEventSize::parseFile(std::string const & fileName, std::string const & treeName) {
00087 m_fileName = fileName;
00088 m_branches.clear();
00089
00090 TFile * file = TFile::Open( fileName.c_str() );
00091 if( file==0 || ( !(*file).IsOpen() ) )
00092 throw Error( "unable to open data file " + fileName, 7002);
00093
00094 TObject * o = file->Get(treeName.c_str() );
00095 if ( o == 0 )
00096 throw Error("no object \"" + treeName + "\" found in file: " + fileName, 7003);
00097
00098 TTree * events = dynamic_cast<TTree*> (o);
00099 if ( events == 0 )
00100 throw Error("object \"" + treeName + "\" is not a TTree in file: " + fileName, 7004);
00101
00102 m_nEvents = events->GetEntries();
00103 if ( m_nEvents == 0 )
00104 throw Error("tree \"" + treeName + "\" in file " + fileName + " contains no Events", 7005);
00105
00106
00107 TObjArray * branches = events->GetListOfBranches();
00108 if ( branches == 0 )
00109 throw Error("tree \"" + treeName+ "\" in file " + fileName + " contains no branches", 7006);
00110
00111 const size_t n = branches->GetEntries();
00112 m_branches.reserve(n);
00113 for( size_t i = 0; i < n; ++i ) {
00114 TBranch * b = dynamic_cast<TBranch*>( branches->At( i ) );
00115 if (b==0) continue;
00116 std::string const name( b->GetName() );
00117 if ( name == "EventAux" ) continue;
00118 size_type s = getTotalSize(b);
00119 m_branches.push_back( BranchRecord(name, double(s[0])/double(m_nEvents), double(s[1])/double(m_nEvents)) );
00120 }
00121 std::sort(m_branches.begin(),m_branches.end(),
00122 boost::bind(std::greater<double>(),
00123 boost::bind(&BranchRecord::compr_size,_1),
00124 boost::bind(&BranchRecord::compr_size,_2))
00125 );
00126
00127 }
00128
00129 void EdmEventSize::sortAlpha() {
00130 std::sort(m_branches.begin(),m_branches.end(),
00131 boost::bind(std::less<std::string>(),
00132 boost::bind(&BranchRecord::name,_1),
00133 boost::bind(&BranchRecord::name,_2))
00134 );
00135
00136 }
00137
00138 namespace detail {
00139
00140 void shorterName(EdmEventSize::BranchRecord & br) {
00141 size_t b = br.fullName.find('_');
00142 size_t e = br.fullName.rfind('_');
00143 if (b==e) br.name=br.fullName;
00144 else {
00145
00146 br.name = br.fullName.substr(b+1,e-b-1);
00147
00148 e = br.name.rfind('_');
00149 if (e!=std::string::npos) br.name.replace(e,1,":");
00150
00151 br.name.append(" ("+br.fullName.substr(0,b)+")");
00152 }
00153 }
00154
00155 }
00156
00157 void EdmEventSize::formatNames() {
00158 std::for_each(m_branches.begin(),m_branches.end(),
00159 &detail::shorterName);
00160 }
00161
00162
00163
00164 namespace detail {
00165
00166 void dump(ostream& co, EdmEventSize::BranchRecord const & br) {
00167 co << br.name << " " << br.compr_size << " " << br.uncompr_size << "\n";
00168 }
00169 }
00170
00171
00172 void EdmEventSize::dump(std::ostream & co, bool header) const {
00173 if (header)
00174 co << "File " << m_fileName << " Events " << m_nEvents << "\n";
00175 std::for_each(m_branches.begin(),m_branches.end(),
00176 boost::bind(detail::dump,boost::ref(co),_1));
00177 }
00178
00179 namespace detail {
00180
00181 struct Hist {
00182
00183 explicit Hist(int itop) :
00184 top(itop),
00185 uncompressed( "uncompressed", "branch sizes", top, -0.5, - 0.5 + top ),
00186 compressed( "compressed", "branch sizes", top, -0.5, - 0.5 + top ),
00187 cxAxis(compressed.GetXaxis()),
00188 uxAxis(uncompressed.GetXaxis()),
00189 x(0) {}
00190
00191 void fill(EdmEventSize::BranchRecord const & br) {
00192 if ( x < top ) {
00193 cxAxis->SetBinLabel( x + 1, br.name.c_str() );
00194 uxAxis->SetBinLabel( x + 1, br.name.c_str() );
00195 compressed.Fill( x, br.compr_size );
00196 uncompressed.Fill( x, br.uncompr_size );
00197 x++;
00198 }
00199 }
00200
00201 void finalize() {
00202 double mn = std::numeric_limits<double>::max();
00203 for( int i = 1; i <= top; ++i ) {
00204 double cm = compressed.GetMinimum( i ), um = uncompressed.GetMinimum( i );
00205 if ( cm > 0 && cm < mn ) mn = cm;
00206 if ( um > 0 && um < mn ) mn = um;
00207 }
00208 mn *= 0.8;
00209 double mx = max( compressed.GetMaximum(), uncompressed.GetMaximum() );
00210 mx *= 1.2;
00211 uncompressed.SetMinimum( mn );
00212 uncompressed.SetMaximum( mx );
00213 compressed.SetMinimum( mn );
00214
00215 cxAxis->SetLabelOffset( -0.32 );
00216 cxAxis->LabelsOption( "v" );
00217 cxAxis->SetLabelSize( 0.03 );
00218 uxAxis->SetLabelOffset( -0.32 );
00219 uxAxis->LabelsOption( "v" );
00220 uxAxis->SetLabelSize( 0.03 );
00221 compressed.GetYaxis()->SetTitle( "Bytes" );
00222 compressed.SetFillColor( kBlue );
00223 compressed.SetLineWidth( 2 );
00224 uncompressed.GetYaxis()->SetTitle( "Bytes" );
00225 uncompressed.SetFillColor( kRed );
00226 uncompressed.SetLineWidth( 2 );
00227
00228 }
00229
00230 int top;
00231 TH1F uncompressed;
00232 TH1F compressed;
00233 TAxis * cxAxis;
00234 TAxis * uxAxis;
00235
00236 int x;
00237 };
00238
00239 }
00240
00241 void EdmEventSize::produceHistos(std::string const & plot, std::string const & file, int top) const {
00242 if (top==0) top = m_branches.size();
00243 detail::Hist h(top);
00244 std::for_each(m_branches.begin(),m_branches.end(),
00245 boost::bind(&detail::Hist::fill,boost::ref(h),_1));
00246 h.finalize();
00247 if( !plot.empty() ) {
00248 gROOT->SetStyle( "Plain" );
00249 gStyle->SetOptStat( kFALSE );
00250 gStyle->SetOptLogy();
00251 TCanvas c;
00252 h.uncompressed.Draw();
00253 h.compressed.Draw( "same" );
00254 c.SaveAs( plot.c_str() );
00255 }
00256 if ( !file.empty() ) {
00257 TFile f( file.c_str(), "RECREATE" );
00258 h.compressed.Write();
00259 h.uncompressed.Write();
00260 f.Close();
00261 }
00262
00263 }
00264
00265 }