I/O for classes derived from TClonesArray

Dear root folk,

I use TClonesArray as a base class for my own derived class, MyTClonesArray. It has no additional data members, only member functions to slightly alter TClonesArray behavior.

In a 2005 post to this forum, [url]TClonesArray Philippe comments briefly that “the ROOT I/O framework does not (completely) support class inherting from TClonesArray.” I’m wondering whether that’s still the case, particularly with all the improvements to I/O in 5.28.

Specifically, I can imagine four ways to store an array, and am wondering what the performance differences would be for I/O:

class MyTClonesArray : public TClonesArray
{
  // ... assorted member functions, some overwriting TClonesArray virtual functions.
  // ... Also an overwrite of operator=, in case that matters.
  ClassDef(MyTClonesArray,1)
};

class ObjectToWrite : public TObject
{
  // Contrast the following four options:
  TClonesArray array1; // A conversion operator will be written; inconvenient.
  MyTClonesArray array2;
  TClonesArray* array3; //-> To be downcast to MyTClonesArray when appropriate; slightly inconvenient.
  MyTClonesArray* array4; //->

  // Other functions, members, ClassDef, etc.
};

Thanks!
Clayton

[quote]Philippe comments briefly that “the ROOT I/O framework does not (completely) support class inherting from TClonesArray.” I’m wondering whether that’s still the case, particularly with all the improvements to I/O in 5.28.[/quote]It is still the case.

I recommend that you use:class MyTClonesArray { TClonesArray fArray; // Inline function forwarding the interface from MyTClonesArray to fArray. // ... assorted member functions, some overwriting TClonesArray virtual functions. // ... Also an overwrite of operator=, in case that matters. ClassDef(MyTClonesArray,1) };

Cheers,
Philippe.

Hi Philippe,

Thanks for the response! I tried to make a test case to play with, but all I could extract from it pointed to similar io handling between TClonesArray and a derived class – can you clarify where the performance hit comes in or how to see it?

I inserted output in TClonesArray::Streamer, to track when it was called and whether BypassStreamer was set. My edited copy of TClonesArray.cxx is attached. I then ran two scripts that pretty well represent my application.

ReadWrite_1.C writes a tree with one branch, holding a MyWrapper class which contains a pointer to a TClonesArray.

ReadWrite_2.C replaces the TClonesArray with a MyTClonesArray, which derives from TClonesArray.

The output from both is identical, and indicates that TClonesArray::Streamer is called on both read and write, and kBypassStreamer is set in all cases.

Are both cases benefiting from TClonesArray io optimization, or should I be looking elsewhere to identify what has gotten worse?

Thanks very much,
Clayton
ReadWrite_2.C (1.71 KB)
ReadWrite_1.C (1.23 KB)
TClonesArray.cxx (33.9 KB)

Hi,

[quote]Are both cases benefiting from TClonesArray io optimization, or should I be looking elsewhere to identify what has gotten worse?[/quote]Indeed, the current code will sometimes do the ‘right’ things when handling a class derived from TClonesArray but not in all cases (for example TTree::Draw may or may not recognize it properly, the splitting in ‘some’ case of use of the derived class may not work).

Cheers,
Philippe.