diff --git a/core/metacling/src/TCling.cxx b/core/metacling/src/TCling.cxx index 11d18416694a15..c921c33ebbd30e 100644 --- a/core/metacling/src/TCling.cxx +++ b/core/metacling/src/TCling.cxx @@ -2169,8 +2169,10 @@ void TCling::RegisterModule(const char* modulename, } } if (scopes.empty() || DC) { - // We know the scope; let's look for the enum. - size_t posEnumName = fwdDeclsLine.find("\"))) ", 32); + // We know the scope; let's look for the enum. For that, look + // for the *last* closing parentheses of an attribute because + // there can be multiple. + size_t posEnumName = fwdDeclsLine.rfind("\"))) "); R__ASSERT(posEnumName != std::string::npos && "Inconsistent enum fwd decl!"); posEnumName += 5; // skip "\"))) " while (isspace(fwdDeclsLine[posEnumName])) diff --git a/documentation/doxygen/makehtmlfooter.sh b/documentation/doxygen/makehtmlfooter.sh index 7a15d13de48a72..0c634cdcef7dd3 100755 --- a/documentation/doxygen/makehtmlfooter.sh +++ b/documentation/doxygen/makehtmlfooter.sh @@ -10,14 +10,14 @@ echo ' ' echo '' echo '' echo '' echo '' echo '' echo '' diff --git a/roofit/histfactory/src/MakeModelAndMeasurementsFast.cxx b/roofit/histfactory/src/MakeModelAndMeasurementsFast.cxx index d5dc81680ea72d..fae615cdbb61cf 100644 --- a/roofit/histfactory/src/MakeModelAndMeasurementsFast.cxx +++ b/roofit/histfactory/src/MakeModelAndMeasurementsFast.cxx @@ -192,22 +192,22 @@ RooWorkspace* RooStats::HistFactory::MakeModelAndMeasurementFast( RooStats::Hist RooWorkspace* ws_single = factory.MakeSingleChannelModel( measurement, channel ); channel_workspaces.emplace_back(ws_single); - // Make the output - std::string ChannelFileName = measurement.GetOutputFilePrefix() + "_" - + ch_name + "_" + rowTitle + "_model.root"; - ws_single->writeToFile( ChannelFileName.c_str() ); - - // Now, write the measurement to the file - // Make a new measurement for only this channel - RooStats::HistFactory::Measurement meas_chan( measurement ); - meas_chan.GetChannels().clear(); - meas_chan.GetChannels().push_back( channel ); - cxcoutIHF << "Opening File to hold channel: " << ChannelFileName << std::endl; - TFile* chanFile = TFile::Open( ChannelFileName.c_str(), "UPDATE" ); - cxcoutIHF << "About to write channel measurement to file" << std::endl; - meas_chan.writeToFile( chanFile ); - cxcoutPHF << "Successfully wrote channel to file" << std::endl; - chanFile->Close(); + { + // Make the output + std::string ChannelFileName = measurement.GetOutputFilePrefix() + "_" + + ch_name + "_" + rowTitle + "_model.root"; + cxcoutIHF << "Opening File to hold channel: " << ChannelFileName << std::endl; + std::unique_ptr chanFile{TFile::Open( ChannelFileName.c_str(), "RECREATE" )}; + chanFile->WriteTObject(ws_single); + // Now, write the measurement to the file + // Make a new measurement for only this channel + RooStats::HistFactory::Measurement meas_chan( measurement ); + meas_chan.GetChannels().clear(); + meas_chan.GetChannels().push_back( channel ); + cxcoutIHF << "About to write channel measurement to file" << std::endl; + meas_chan.writeToFile( chanFile.get() ); + cxcoutPHF << "Successfully wrote channel to file" << std::endl; + } // Get the Paramater of Interest as a RooRealVar RooRealVar* poi = dynamic_cast( ws_single->var( (measurement.GetPOI()).c_str() ) ); @@ -245,19 +245,20 @@ RooWorkspace* RooStats::HistFactory::MakeModelAndMeasurementFast( RooStats::Hist // Get the Parameter of interest as a RooRealVar RooRealVar* poi = dynamic_cast( ws->var( (measurement.GetPOI()).c_str() ) ); - - std::string CombinedFileName = measurement.GetOutputFilePrefix() + "_combined_" - + rowTitle + "_model.root"; - cxcoutPHF << "Writing combined workspace to file: " << CombinedFileName << std::endl; - ws->writeToFile( CombinedFileName.c_str() ); - cxcoutPHF << "Writing combined measurement to file: " << CombinedFileName << std::endl; - TFile* combFile = TFile::Open( CombinedFileName.c_str(), "UPDATE" ); - if( combFile == NULL ) { - cxcoutEHF << "Error: Failed to open file " << CombinedFileName << std::endl; - throw hf_exc(); + + { + std::string CombinedFileName = measurement.GetOutputFilePrefix() + "_combined_" + + rowTitle + "_model.root"; + cxcoutPHF << "Writing combined workspace to file: " << CombinedFileName << std::endl; + std::unique_ptr combFile{TFile::Open( CombinedFileName.c_str(), "RECREATE" )}; + if( combFile == nullptr ) { + cxcoutEHF << "Error: Failed to open file " << CombinedFileName << std::endl; + throw hf_exc(); + } + combFile->WriteTObject(ws); + cxcoutPHF << "Writing combined measurement to file: " << CombinedFileName << std::endl; + measurement.writeToFile( combFile.get() ); } - measurement.writeToFile( combFile ); - combFile->Close(); // Fit the combined model if(! measurement.GetExportOnly()){ diff --git a/tree/tree/inc/TTree.h b/tree/tree/inc/TTree.h index 184ad1fc75f18f..82e372abf5ce59 100644 --- a/tree/tree/inc/TTree.h +++ b/tree/tree/inc/TTree.h @@ -430,6 +430,7 @@ class TTree : public TNamed, public TAttLine, public TAttFill, public TAttMarker virtual Long64_t Draw(const char* varexp, const char* selection, Option_t* option = "", Long64_t nentries = kMaxEntries, Long64_t firstentry = 0); // *MENU* virtual void DropBaskets(); virtual void DropBuffers(Int_t nbytes); + Bool_t EnableCache(); virtual Int_t Fill(); virtual TBranch *FindBranch(const char* name); virtual TLeaf *FindLeaf(const char* name); diff --git a/tree/tree/src/TTree.cxx b/tree/tree/src/TTree.cxx index 54b4b77841fe00..eb9201bad0adea 100644 --- a/tree/tree/src/TTree.cxx +++ b/tree/tree/src/TTree.cxx @@ -2671,6 +2671,29 @@ TStreamerInfo* TTree::BuildStreamerInfo(TClass* cl, void* pointer /* = 0 */, Boo return sinfo; } +//////////////////////////////////////////////////////////////////////////////// +/// Enable the TTreeCache unless explicitly disabled for this TTree by +/// a prior call to `SetCacheSize(0)`. +/// If the environment variable `ROOT_TTREECACHE_SIZE` or the rootrc config +/// `TTreeCache.Size` has been set to zero, this call will over-ride them with +/// a value of 1.0 (i.e. use a cache size to hold 1 cluster) +/// +/// Return true if there is a cache attached to the `TTree` (either pre-exisiting +/// or created as part of this call) +Bool_t TTree::EnableCache() +{ + TFile* file = GetCurrentFile(); + if (!file) + return kFALSE; + // Check for an existing cache + TTreeCache* pf = GetReadCache(file); + if (pf) + return kTRUE; + if (fCacheUserSet && fCacheSize == 0) + return kFALSE; + return (0 == SetCacheSizeAux(kTRUE, -1)); +} + //////////////////////////////////////////////////////////////////////////////// /// Called by TTree::Fill() when file has reached its maximum fgMaxTreeSize. /// Create a new file. If the original file is named "myfile.root", @@ -5368,6 +5391,26 @@ Int_t TTree::GetBranchStyle() Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ ) { + auto calculateCacheSize = [=](Double_t cacheFactor) + { + Long64_t cacheSize = 0; + if (fAutoFlush < 0) { + cacheSize = Long64_t(-cacheFactor * fAutoFlush); + } else if (fAutoFlush == 0) { + const auto medianClusterSize = GetMedianClusterSize(); + if (medianClusterSize > 0) + cacheSize = Long64_t(cacheFactor * 1.5 * medianClusterSize * GetZipBytes() / (fEntries + 1)); + else + cacheSize = Long64_t(cacheFactor * 1.5 * 30000000); // use the default value of fAutoFlush + } else { + cacheSize = Long64_t(cacheFactor * 1.5 * fAutoFlush * GetZipBytes() / (fEntries + 1)); + } + if (cacheSize >= (INT_MAX / 4)) { + cacheSize = INT_MAX / 4; + } + return cacheSize; + }; + const char *stcs; Double_t cacheFactor = 0.0; if (!(stcs = gSystem->Getenv("ROOT_TTREECACHE_SIZE")) || !*stcs) { @@ -5381,40 +5424,14 @@ Long64_t TTree::GetCacheAutoSize(Bool_t withDefault /* = kFALSE */ ) cacheFactor = 0.0; } - Long64_t cacheSize = 0; - - if (fAutoFlush < 0) { - cacheSize = Long64_t(-cacheFactor * fAutoFlush); - } else if (fAutoFlush == 0) { - const auto medianClusterSize = GetMedianClusterSize(); - if (medianClusterSize > 0) - cacheSize = Long64_t(cacheFactor * 1.5 * medianClusterSize * GetZipBytes() / (fEntries + 1)); - else - cacheSize = Long64_t(cacheFactor * 1.5 * 30000000); // use the default value of fAutoFlush - } else { - cacheSize = Long64_t(cacheFactor * 1.5 * fAutoFlush * GetZipBytes() / (fEntries + 1)); - } - - if (cacheSize >= (INT_MAX / 4)) { - cacheSize = INT_MAX / 4; - } + Long64_t cacheSize = calculateCacheSize(cacheFactor); if (cacheSize < 0) { cacheSize = 0; } if (cacheSize == 0 && withDefault) { - if (fAutoFlush < 0) { - cacheSize = -fAutoFlush; - } else if (fAutoFlush == 0) { - const auto medianClusterSize = GetMedianClusterSize(); - if (medianClusterSize > 0) - cacheSize = Long64_t(1.5 * medianClusterSize * GetZipBytes() / (fEntries + 1)); - else - cacheSize = Long64_t(cacheFactor * 1.5 * 30000000); // use the default value of fAutoFlush - } else { - cacheSize = Long64_t(1.5 * fAutoFlush * GetZipBytes() / (fEntries + 1)); - } + cacheSize = calculateCacheSize(1.0); } return cacheSize; @@ -9506,34 +9523,13 @@ void TTree::Streamer(TBuffer& b) // current set of ranges. fMaxClusterRange = fNClusterRange; } - if (GetCacheAutoSize() != 0) { - // a cache will be automatically created. - // No need for TTreePlayer::Process to enable the cache - fCacheSize = 0; - } else if (fAutoFlush < 0) { - // If there is no autoflush set, let's keep the cache completely - // disable by default for now. - fCacheSize = fAutoFlush; - } else if (fAutoFlush != 0) { - // Estimate the cluster size. - // This will allow TTree::Process to enable the cache. - Long64_t zipBytes = GetZipBytes(); - Long64_t totBytes = GetTotBytes(); - if (zipBytes != 0) { - fCacheSize = fAutoFlush*(zipBytes/fEntries); - } else if (totBytes != 0) { - fCacheSize = fAutoFlush*(totBytes/fEntries); - } else { - fCacheSize = 30000000; - } - if (fCacheSize >= (INT_MAX / 4)) { - fCacheSize = INT_MAX / 4; - } else if (fCacheSize == 0) { - fCacheSize = 30000000; - } - } else { - fCacheSize = 0; - } + + // Throughs calls to `GetCacheAutoSize` or `EnableCache` (for example + // by TTreePlayer::Process, the cache size will be automatically + // determined unless the user explicitly call `SetCacheSize` + fCacheSize = 0; + fCacheUserSet = kFALSE; + ResetBit(kMustCleanup); return; } diff --git a/tree/tree/src/TTreeCache.cxx b/tree/tree/src/TTreeCache.cxx index a895734724d890..ba32134e0e25de 100644 --- a/tree/tree/src/TTreeCache.cxx +++ b/tree/tree/src/TTreeCache.cxx @@ -1332,18 +1332,25 @@ Bool_t TTreeCache::FillBuffer() Long64_t maxReadEntry = minEntry; // If we are stopped before the end of the 2nd pass, this marker will where we need to start next time. Int_t nReadPrefRequest = 0; auto perfStats = GetTree()->GetPerfStats(); + + struct collectionInfo { + Int_t fClusterStart{-1}; // First basket belonging to the current cluster + Int_t fCurrent{-1}; // Currently visited basket + Bool_t fLoadedOnce{kFALSE}; + + void Rewind() { fCurrent = (fClusterStart >= 0) ? fClusterStart : 0; } + }; + std::vector cursor(fNbranches); + + // Main loop to fill the cache, inside each loop we will loop over + // all the cached branch and collect the baskets within the 'current' + // range/cluster. If there is still space in the cache after that, we + // will do another iteration to add one more cluster to the cache. + // i.e. essentially loop over the clusters. do { prevNtot = ntotCurrentBuf; Long64_t lowestMaxEntry = fEntryMax; // The lowest maximum entry in the TTreeCache for each branch for each pass. - struct collectionInfo { - Int_t fClusterStart{-1}; // First basket belonging to the current cluster - Int_t fCurrent{0}; // Currently visited basket - Bool_t fLoadedOnce{kFALSE}; - - void Rewind() { fCurrent = (fClusterStart >= 0) ? fClusterStart : 0; } - }; - std::vector cursor(fNbranches); Bool_t reachedEnd = kFALSE; Bool_t skippedFirst = kFALSE; Bool_t oncePerBranch = kFALSE; @@ -1414,6 +1421,10 @@ Bool_t TTreeCache::FillBuffer() if (pass == kRewind) cursor[i].Rewind(); + else if (cursor[i].fCurrent == -1) { + auto start = TMath::BinarySearch(b->GetWriteBasket() + 1, entries, minEntry); + cursor[i].fCurrent = (start < 0) ? 0 : start; + } for (auto &j = cursor[i].fCurrent; j < nb; j++) { // This basket has already been read, skip it diff --git a/tree/treeplayer/src/TTreePlayer.cxx b/tree/treeplayer/src/TTreePlayer.cxx index dfb86cac9cbba0..6c2bb9a0c20109 100644 --- a/tree/treeplayer/src/TTreePlayer.cxx +++ b/tree/treeplayer/src/TTreePlayer.cxx @@ -2252,12 +2252,14 @@ Long64_t TTreePlayer::Process(TSelector *selector,Option_t *option, Long64_t nen //set the file cache TTreeCache *tpf = 0; TFile *curfile = fTree->GetCurrentFile(); - if (curfile && fTree->GetCacheSize() > 0) { + if (curfile) { tpf = (TTreeCache*)curfile->GetCacheRead(fTree); if (tpf) tpf->SetEntryRange(firstentry,firstentry+nentries); else { - fTree->SetCacheSize(fTree->GetCacheSize()); + // Create the TTreeCache with the default size unless the + // user explicitly disabled it. + fTree->EnableCache(); tpf = (TTreeCache*)curfile->GetCacheRead(fTree); if (tpf) tpf->SetEntryRange(firstentry,firstentry+nentries); }