Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:29:07

0001 #include "TFile.h"
0002 #include "TTree.h"
0003 #include "TBranch.h"
0004 #include "TClass.h"
0005 #include "TThread.h"
0006 #include "TVirtualStreamerInfo.h"
0007 
0008 #include "TList.h"
0009 #include "TMap.h"
0010 #include "TObjString.h"
0011 #include "TH1F.h"
0012 
0013 #include "FWCore/FWLite/interface/FWLiteEnabler.h"
0014 
0015 #include <memory>
0016 #include <cassert>
0017 #include <iostream>
0018 #include <thread>
0019 #include <atomic>
0020 
0021 std::atomic<bool> waitToStart{true};
0022 
0023 void printHelp(const char* iName, int iDefaultNThreads) {
0024   std::cout << iName << " [number of threads] [filename] [gDebug value]\n\n"
0025             << "[number of threads] number of threads to use in test\n"
0026             << "[filename] name of CMSSW file to read\n"
0027             << "[gDebug value] value of gDebug to pass to ROOT (gDebug=1 is useful)\n"
0028             << "If no arguments are given " << iDefaultNThreads
0029             << " threads will be used and a dummy file will be created." << std::endl;
0030 }
0031 
0032 const std::string kDefaultFileName("read_test_dummy.root");
0033 
0034 std::tuple<int, std::string, int> parseOptions(int argc, char** argv) {
0035   constexpr int kDefaultNThreads = 4;
0036   int kDefaultgDebug = gDebug;
0037   int nThreads = kDefaultNThreads;
0038   int newGDebug = kDefaultgDebug;
0039   std::string fileName(kDefaultFileName);
0040   if (argc >= 2) {
0041     if (strcmp("-h", argv[1]) == 0) {
0042       printHelp(argv[0], kDefaultNThreads);
0043       exit(0);
0044     }
0045 
0046     nThreads = atoi(argv[1]);
0047   }
0048   if (argc >= 3) {
0049     fileName = argv[2];
0050   }
0051   if (argc == 4) {
0052     newGDebug = atoi(argv[3]);
0053   }
0054 
0055   if (argc > 4) {
0056     printHelp(argv[0], kDefaultNThreads);
0057     exit(1);
0058   }
0059   return std::make_tuple(nThreads, fileName, newGDebug);
0060 }
0061 
0062 void createDummyFile() {
0063   auto theList = new TList();
0064 
0065   for (unsigned int i = 0; i < 10; ++i) {
0066     theList->Add(new TList());
0067     theList->Add(new TMap());
0068     theList->Add(new TObjString());
0069     theList->Add(new TH1F());
0070     theList->Add(new TH1D());
0071   }
0072 
0073   TFile f(kDefaultFileName.c_str(), "RECREATE", "test");
0074 
0075   auto listTree = new TTree("Events", "TheList");
0076   listTree->Branch("theList", "TList", &theList);
0077 
0078   for (unsigned int i = 0; i < 100; ++i) {
0079     listTree->Fill();
0080   }
0081   f.Write();
0082   f.Close();
0083 }
0084 
0085 int main(int argc, char** argv) {
0086   auto options = parseOptions(argc, argv);
0087 
0088   const int kNThreads = std::get<0>(options);
0089 
0090   auto const kFileName = std::get<1>(options);
0091 
0092   gDebug = std::get<2>(options);
0093 
0094   FWLiteEnabler::enable();
0095 
0096   //Tell Root we want to be multi-threaded
0097   TThread::Initialize();
0098   //When threading, also have to keep ROOT from logging all TObjects into a list
0099   TObject::SetObjectStat(false);
0100   //Have to avoid having Streamers modify themselves after they have been used
0101   TVirtualStreamerInfo::Optimize(false);
0102 
0103   if (kFileName == kDefaultFileName) {
0104     createDummyFile();
0105   }
0106 
0107   std::vector<std::shared_ptr<std::thread>> threads;
0108   threads.reserve(kNThreads);
0109 
0110   for (int i = 0; i < kNThreads; ++i) {
0111     threads.push_back(std::make_shared<std::thread>(std::thread([&kFileName]() {
0112       static thread_local TThread s_thread_guard;
0113       while (waitToStart)
0114         ;
0115       std::unique_ptr<TFile> f{TFile::Open(kFileName.c_str())};
0116       assert(f.get());
0117 
0118       TTree* eventTree = dynamic_cast<TTree*>(f.get()->Get("Events"));
0119       assert(eventTree);
0120 
0121       for (Long64_t i = 0, iEnd = eventTree->GetEntries(); i != iEnd; ++i) {
0122         eventTree->GetEntry(i, 1);
0123       }
0124 
0125       f.get()->Close();
0126     })));
0127   }
0128   waitToStart = false;
0129   for (auto& t : threads) {
0130     t->join();
0131   }
0132 
0133   return 0;
0134 }