diff --git a/misc/memstat/src/TMemStat.cxx b/misc/memstat/src/TMemStat.cxx index 2b1b7c16eb3666fa146c65c46381491582067692..279bd9337f8d7d0eaaa95f5dc3363661af538722 100644 --- a/misc/memstat/src/TMemStat.cxx +++ b/misc/memstat/src/TMemStat.cxx @@ -75,6 +75,9 @@ // If this argument is omitted, Show will take the most recent file // generated by TMemStat. // +// You can restrict the address range to be analyzed via TMemStatShow::SetAddressRange +// You can restrict the entry range to be analyzed via TMemStatShow::SetEntryRange +// //___________________________________________________________________________ #include "TROOT.h" diff --git a/tree/treeviewer/inc/TMemStatShow.h b/tree/treeviewer/inc/TMemStatShow.h index 91c0d561d9f742b20d2ebdf0e53749117846207c..aaf3965a56021d93ab91d8060cfeda2c6f6b105b 100644 --- a/tree/treeviewer/inc/TMemStatShow.h +++ b/tree/treeviewer/inc/TMemStatShow.h @@ -28,12 +28,20 @@ class TMemStatShow : public TObject { +protected: + static Long64_t fgAddressFirst; //first address to process + static Long64_t fgAddressN; //number of addresses in bytes to process + static Long64_t fgEntryFirst; //first entry to process + static Long64_t fgEntryN; //number of entries to process + public: TMemStatShow() {;} virtual ~TMemStatShow() {;} static void EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected); static void FillBTString(Int_t bin, Int_t mode, TString &btstring); + static void SetAddressRange(Long64_t nbytes=0, Long64_t first=0); + static void SetEntryRange(Long64_t nentries=0, Long64_t first=0); static void Show(Double_t update=0.1, Int_t nbigleaks=20, const char* fname="*"); ClassDef(TMemStatShow,0) //class to visualize the results of TMemStat diff --git a/tree/treeviewer/src/TMemStatShow.cxx b/tree/treeviewer/src/TMemStatShow.cxx index 065a2d352377f129d6469e4d9c97c8c29b3abf9a..5f336be19692d6a8795b502dbeaf89ab1d5de84d 100644 --- a/tree/treeviewer/src/TMemStatShow.cxx +++ b/tree/treeviewer/src/TMemStatShow.cxx @@ -77,6 +77,9 @@ // If this argument is omitted, Show will take the most recent file // generated by TMemStat. // +// You can restrict the address range to be analyzed via TMemStatShow::SetAddressRange +// You can restrict the entry range to be analyzed via TMemStatShow::SetEntryRange +// //Author: Rene Brun 7 July 2010 //___________________________________________________________________________ @@ -93,6 +96,7 @@ #include "TGClient.h" #include "TGToolTip.h" #include "TRootCanvas.h" +MemInfo_t minfo; TTree *gT; //TMemStat Tree TH1D *gHalloc; //histogram with allocations @@ -107,10 +111,46 @@ Double_t *gV2; //pointer to V1 array of TTree::Draw Double_t *gV3; //pointer to V1 array of TTree::Draw Double_t *gV4; //pointer to V1 array of TTree::Draw - TCanvas *gC1; //pointer to anvas shoing allocs/deallocs vs time + TCanvas *gC1; //pointer to canvas showing allocs/deallocs vs time TCanvas *gC2; //pointer to canvas with leaks in decreasing order TCanvas *gC3; //pointer to canvas showing the main leaks + Long64_t TMemStatShow::fgEntryFirst = 0; + Long64_t TMemStatShow::fgEntryN = 0; + Long64_t TMemStatShow::fgAddressFirst = 0; + Long64_t TMemStatShow::fgAddressN = 0; + +//___________________________________________________________________________ +void TMemStatShow::SetAddressRange(Long64_t nbytes, Long64_t first) +{ + //specify a memory address range to process (static function). + // This function can be used to restrict the range of memory addresses + // to be analyzed. For example whem TmemStat is run on a 64 bits machine and + // the results visualized on a 32 bits machine, it might be necessary to + // restrict the analysis range to the addresses below 2 Gigabytes, eg + // TMemStatShow::SetMemoryRange(500000000,0); //analyse only the first 500 MBytes + // -first : first address to process (default is 0) + // -nbytes : number of addresses in bytes to process starting at first + // if 0 (default), then all addresses are processed + + fgAddressFirst = first; + fgAddressN = nbytes; +} + +//___________________________________________________________________________ +void TMemStatShow::SetEntryRange(Long64_t nentries, Long64_t first) +{ + //specify a range of entries to process (static function) + // -first : first entry to process (default is 0) + // -nentries : number of entries to process starting at first + // if 0 (default), then all entries are processed + // call this function when the amount of data collected in the Tree is large + // and therefore making the analysis slow. + + fgEntryFirst = first; + fgEntryN = nentries; +} + //___________________________________________________________________________ void TMemStatShow::Show(double update, int nbigleaks, const char* fname) { @@ -124,6 +164,7 @@ void TMemStatShow::Show(double update, int nbigleaks, const char* fname) // the histogram hbigleaks will contain the nbigleaks largest leaks // if fname=="*" (default), the most recent file memstat*.root will be taken. + TString s; if (!fname || strlen(fname) <5 || strstr(fname,"*")) { //take the most recent file memstat*.root @@ -147,15 +188,31 @@ void TMemStatShow::Show(double update, int nbigleaks, const char* fname) update = 0.01; } if (update < 0.001) printf("Warning update parameter is very small, processing may be slow\n"); + + //autorestrict the amount of data to analyze + gSystem->GetMemInfo(&minfo); + Int_t nfree = minfo.fMemTotal - minfo.fMemUsed; //in Mbytes + printf("TMemStat::Show info: you are running on a machine with %d free MBytes of memory\n",nfree); + Long64_t nfreebytes = 100000*Long64_t(nfree); //use only 10% of the memory available + if (fgAddressN <=0) fgAddressN = nfreebytes; + printf("TMemStatShow::Show will analyze only the first %lld bytes in its first pass\n",nfreebytes); + //initialize statics gTip = 0; gBtidlist = 0; Long64_t nentries = gT->GetEntries(); + if (fgEntryN > 0 && nentries > fgEntryN) nentries = fgEntryN; gT->SetEstimate(nentries+10); - Long64_t nsel = gT->Draw("pos:nbytes:time:btid","","goff"); - + Long64_t nsel; + if (fgAddressN <= 0) { + nsel = gT->Draw("pos:nbytes:time:btid","pos>0","goff",nentries,fgEntryFirst); + } else { + nsel = gT->Draw("pos:nbytes:time:btid", + TString::Format("pos>%g && pos<%g",Double_t(fgAddressFirst),Double_t(fgAddressFirst+fgAddressN)), + "goff",nentries,fgEntryFirst); + } //now we compute the best binning for the histogram Int_t nbytes; Double_t pos; @@ -163,38 +220,47 @@ void TMemStatShow::Show(double update, int nbigleaks, const char* fname) gV2 = gT->GetV2(); gV3 = gT->GetV3(); gV4 = gT->GetV4(); - Long64_t imean = (Long64_t)TMath::Mean(nsel,gV1); - Long64_t irms = (Long64_t)TMath::RMS(nsel,gV1); - //Long64_t bw = 10000; + Long64_t ivmin = (Long64_t)TMath::MinElement(nsel,gV1); + Long64_t ivmax = (Long64_t)TMath::MaxElement(nsel,gV1); Long64_t bw = 1000; - imean = imean - imean%bw; - irms = irms -irms%bw; - Int_t nbins = Int_t(4*irms/bw); - Long64_t ivmin = imean -bw*nbins/2; - Long64_t ivmax = ivmin+bw*nbins; - if (ivmax > 2000000000 && ivmin <2000000000) { - //the data set has been likely generated on a 32 bits machine + Double_t dvv = (Double_t(ivmax) - Double_t(ivmin))/Double_t(bw); + Long64_t nbins = Long64_t(dvv); + ivmin = ivmin -ivmin%bw; + ivmax = ivmin+bw*nbins; + Long64_t nvm = Long64_t(ivmax-ivmin+1); + printf("==>The data Tree contains %lld entries with addresses in range[%lld,%lld]\n",nsel,ivmin,ivmax); + Long64_t ne = (1000000*nfree-nvm*12)/32; + if (ne < 0) return; + if (ne < nentries) { + //we take only the first side of the allocations //we are mostly interested by the small allocations, so we select - //only values below 2 GBytes - printf("memory locations above 2GBytes will be ignored\n"); - nsel = gT->Draw("pos:nbytes:time:btid","pos <2e9","goff"); + //only values in the first gigabyte + nsel = gT->Draw("pos:nbytes:time:btid", + TString::Format("pos>=%g && pos<%g",Double_t(ivmin),Double_t(ivmax)),"goff",ne,fgEntryFirst); gV1 = gT->GetV1(); gV2 = gT->GetV2(); gV3 = gT->GetV3(); gV4 = gT->GetV4(); - imean = (Long64_t)TMath::Mean(nsel,gV1); - irms = (Long64_t)TMath::RMS(nsel,gV1); + ivmin = (Long64_t)TMath::MinElement(nsel,gV1); + ivmax = (Long64_t)TMath::MaxElement(nsel,gV1); bw = 10000; - imean = imean - imean%bw; - irms = irms -irms%bw; - nbins = Int_t(4*irms/bw); - ivmin = imean -bw*nbins/2; + dvv = (Double_t(ivmax) - Double_t(ivmin))/Double_t(bw); + nbins = Long64_t(dvv+0.5); + ivmin = ivmin -ivmin%bw; ivmax = ivmin+bw*nbins; + printf("==>Address range or/and Entry range is too large\n"); + printf("==>restricting the analysis range to [%lld,%lld] and %lld entries\n",ivmin,ivmax,ne); + printf("==>you can restrict the address range with TMemStatShow::SetAddressRange\n"); + printf("==>you can restrict the entries range with TMemStatShow::SetEntryRange\n"); } update *= 0.0001*gV3[nsel-1]; //convert time per cent in seconds - Long64_t nvm = Long64_t(ivmax-ivmin+1); + nvm = Long64_t(ivmax-ivmin); Long64_t *nbold = new Long64_t[nvm]; Int_t *ientry = new Int_t[nvm]; + if (!nbold || !ientry) { + printf("you do not have enough memory to run, %lld bytes needed\n",12*nvm); + return; + } memset(nbold,0,nvm*8); memset(ientry,0,nvm*4); Double_t dv = (ivmax-ivmin)/nbins; @@ -256,7 +322,7 @@ void TMemStatShow::Show(double update, int nbigleaks, const char* fname) rest = nbytes-nb*dv-dbin; if (rest > 0) h->AddBinContent(bin+nb+1,100*rest/dv); //we save nbytes at pos. This info will be used when we free this slot - if (nbold[ipos] > 0) printf("reallocating %d bytes (was %lld) at %lld, entry=%d\n",nbytes,nbold[ipos],ipos,i); + //if (nbold[ipos] > 0) printf("reallocating %d bytes (was %lld) at %lld, entry=%d\n",nbytes,nbold[ipos],ipos,i); if (nbold[ipos] == 0) { nleaks++; //save the Tree entry number where we made this allocation @@ -309,6 +375,7 @@ void TMemStatShow::Show(double update, int nbigleaks, const char* fname) } } h->SetEntries(nsel); + if (nleaks < 0) nleaks=0; Int_t nlmax = nleaks; nleaks += 1000; Int_t *lindex = new Int_t[nleaks]; @@ -324,7 +391,6 @@ void TMemStatShow::Show(double update, int nbigleaks, const char* fname) if (nleaks > nlmax) break; } } - TMath::Sort(nleaks,ileaks,lindex); gHentry = new TH1I("fHentry","leak entry index",nleaks,0,nleaks); gHleaks = new TH1I("fHleaks","leaks;leak number;nbytes in leak",nleaks,0,nleaks);