Efficiency issue when reading a persistent branch from file


Please read tips for efficient and successful posting and posting code

ROOT Version: 6.34.04
Platform: AlmaLinux 9
Compiler: gcc 11.3.0


I have a problem related to the correct handling of a persistency class.

My persistency top class is:

class TRawMergedEvent : public TObject
{
 public:
  TRawMergedEvent();
  ~TRawMergedEvent();
  void Clear(Option_t* = "");
 public:
  // Some data access methods...
 private:
  TRawEvent* fTRawEvent;
  TMMRawEvent* fTMMRawEvent;
  ClassDef(TRawMergedEvent,1);
};

The two sub-classes, TRawEvent and TMMRawEvent both contain a TClonesArray*, e.g.:

class TRawEvent : public TObject
{
...
private:
  ...
  UChar_t fNADCBoards;
  TClonesArray* fADCBoards;
  ClassDef(TRawEvent,3);
};

To read these data I use this kind of code:

  TRawMergedEvent* mergedRawEv = new TRawMergedEvent();
  inputChain->SetBranchAddress("RawMergedEvent",&mergedRawEv);
  for(Int_t iev=0;iev<inputChain->GetEntries();iev++){
    inputChain->GetEntry(iev);
    ...some event analysis code...
    mergedRawEv->Clear("C");
  }

The problem with this code is that when I read a new event, the two TRawEvent* and TMMRawEvent* classes are deleted but the TClonesArray* classes inside them are not, and this creates a huge memory leak.

A simple solution is probably to explicitly add the deletion of the TClonesArray* classes inside the delete methods of TRawEvent* and TMMRawEvent*, is this the correct thing to do?

Even if this deletion solves the memory leak problem, I would greatly prefer to find a way to avoid the deletion of all the content of TRawMergedEvent (the top class) so that, possibly after some clean-up procedure, it can be reused for all events, thus improving the code efficiency.

I gave a look to the reference manual and in the TTree documentation I found an “Important note” which points to some way of disabling the deletion of TObject* class within a branch by using the “->” tag but I was not able to fully understand the explanation.

Can someone give me a hand with this issue?

Thank you

Emanuele

Hi Emanuele,

To prevent the memory leaks, I’d suggest using unique pointers, e.g. std::unique_ptr<TRawEvent> and std::unique_ptr<TClonesArray>, instead of raw pointers.

If you want to reuse the objects, you could not use pointers at all, e.g. TRawEvent fTRawEvent; instead of TRawEvent fTRawEvent (and similar for the other pointers).

Cheers,
Jakob

One more suggestion: if you can change the classes, try moving from TClonesArray to std::vector. It is most likely not slower than the TClonesArray and you pave the road for RNTuple adoption.

See: ROOT Manual → Functional parts → I/O of custom classes → Restrictions on types ROOT I/O can handle

Warning: Be sure that you do not allocate any space for embedded pointer objects in the default (or the I/O) constructor. This space will be lost (memory leak) while reading in the object.