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.
};
[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)
};
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?
[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).