Speeding up TTreeFormula::EvalInstance

Hi all,

Well, after the last discussion with Philippe I learned a lot about TTreeFormula and I finally succeeded in building in the TTreeFormula class in my code. There I process a big number of events and create a big number of histograms from it. So the code works in principle but is rather slow. I tought that would be because of the large number of events and hists but when looking deeper into that I realized that ~80% of the processing time goes into the TTreeFormula::EvalInstance-method(s). Now the question is is there a way to speed up this method?

I had a look to the source code of this method and it seems to me that the whole expression is parsed again and again for each call of EvalInstance(). So is there a way to invoke something like Compile() like it is in TFormula?

Another approach to speed up my code lies in the structure of my cuts. The final cuts are combined from a set of “base cuts”. Something like:

TCut basecut1(...);
TCut basecut2(...);
...
TCut finalcut1 = basecut1 && basecut2;
TCut finalcut2 = (basecut1 && basecut2) || basecut3;
...

where the finalcutx are the cuts going to TTreeFormulas. So in fact bascutx is evaluated n-times for one event. Is there a simple way in root to tell TTreeFormula to evaluate the basecuts only once? Sure I could do this for my own but I was very surprised :open_mouth: in the past about the masses of features already present in root so I thought I aks before implementing my own hack :slight_smile:

Thanks a lot,

Mathias

[quote]Now the question is is there a way to speed up this method? [/quote]EvalInstance is pretty much optimized. It does NOT reparse the string each time. There are a few things we could still (including evulating the lastest optimization that was made to TFormula; however you can emulated some of this type of gain by optimization your expression).

TCut basecut1(...); TCut basecut2(...); ... TCut finalcut1 = basecut1 && basecut2; TCut finalcut2 = (basecut1 && basecut2) || basecut3;
If you do not already do that you should call:myformula->SetQuickLoad(kTRUE);which will insure that the branch are loaded once per event.
In addition, you might want to simply optimize by hand by doing:

TCut basecut1(...); TCut basecut2(...); ... finalcut1 = form1->EvalInstance() && form2->EvalInstance(); finalcut2 = (finalcut1) || form3->EvalInstance(); or

[code]

Cheers,
Philippe.

Hi Philippe,

Thats what I meant with “implementing my own hack” :slight_smile:

myformula->SetQuickLoad(kTRUE);

Ok, that speeds up my calculations by something like 10%, tanks for the hint. Now I’m asking myself why this is not set true by default?

Cheers, Mathias

A little bit of historical reason and also ‘safety’. One usage pattern we support is the case where somebody is using TTreeFormula directly (like you are) but is also both modifying the object and calling EvalInstance again on the same entry (and expect the EvalInstance to use the value on file).

Cheers,
Philippe.