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