Writing histograms is slow when multiple histograms are defined with the same name

Dear Experts!
In the beginning of my code, several output root files are created and each is then filled with histograms with identical names accross files. This is because the files describe systematic variations of the same computation. Closing the files takes a long time. The first takes the longest then the second one is a bit faster and so on, the last one is really fast. I think this has to do with ROOT’s internal bookkeeping of the histograms, but I don’t know how I could mitigate the issue.
Any ideas?
Here is a minimum working example:

#include <iostream>
#include <vector>
#include <map>

#include <TROOT.h>
#include <TH1.h>
#include <TH1D.h>
#include <TFile.h>
#include <TBenchmark.h>

class OutputHandler{
    public:
        TFile *outFile;
        std::map<std::string, TH1D* > h_controlHists;

        OutputHandler(const char*);
        void close();
};

OutputHandler::OutputHandler(const char* fName){

    outFile = new TFile(fName, "RECREATE");
    TH1::SetDefaultSumw2();

    for (int i=0; i<10; i++){
        TDirectory* tempTDirPtr = outFile->mkdir(("dir_" + std::to_string(i)).c_str());
        tempTDirPtr -> cd();

        for (int j=0; j<1000; j++){
            std::string hName = "name_" + std::to_string(i) + "_" + std::to_string(j);
            h_controlHists[hName] = new TH1D(hName.c_str(), "", 10, 0, 10);
            h_controlHists[hName]->Fill(3.0,5);
        }
    }
}

void OutputHandler::close(){
    TBenchmark time;

    time.Start("time2");
	outFile->Write();
    time.Stop("time2");
	std::cout<<"Write: Real time = "<<time.GetRealTime("time2")<<" s"<<std::endl;

    // outFile->GetList()->Clear();
	gROOT->GetListOfFiles()->Remove(outFile);
	time.Start("time3");
	outFile->Close();
    time.Stop("time3");
	std::cout<<"Close: Real time = "<<time.GetRealTime("time3")<<" s"<<std::endl;
   
}

int main(int argc, char** argv)
{

	TBenchmark time;
	time.Start("time");

    OutputHandler a("test1.root"), b("test2.root"), c("test3.root");
    a.close();
    b.close();
    c.close();
	
	time.Stop("time");
	float cputime = time.GetCpuTime("time");
	float realtime = time.GetRealTime("time");
	std::cout<<"CPU time = "<<cputime<<" s, Real time = "<<realtime<<" s"<<std::endl;
	
    return 0;
}

Which version of ROOT do you use? The problem is likely fixed in v6.28/06 or older.

If you already use a recent version, a work-around is:

outFile = new TFile(fName, "RECREATE");
gROOT->GetListOfFiles()->Remove(outFile);

I am using 6.28/06.
Edit: previously I said that your line results in no histograms written.
That was my mistake. It seems to solve the issue. Thank you! :slight_smile:

Good. I was about to say that it worked perfectly for me.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.