Open ferdymercury opened 3 years ago
(except for the first iteration):
There is some one time initialization. To avoid this, run Printf
(or Emit
) in your startup/initialization phase.
Right now, ESysConstants::kItimerResolution is not assignable at runtime
For this change, it might make more sense to use a compile time configuration.
Just coming back to the issue. It is not clear to me whether we can close it as clarified or if some feature is still needed. @ferdymercury could you chime in?
It might be 'nice to have' a ESysConstants::kItimerResolution
that is configurable at compile time, or alternatively to divide by two the resolution used in 6.32 in ROOT for this, considering that 20 years have passed since that original setting and computers are now much faster. But to be honest, this is not a blocker for my application, so feel free to close it, or put lowest priority. (Unlike https://github.com/root-project/root/pull/8546, which is still high-priority for me, hehehe).
Explain what you would like to see improved
After scratching my head for several hours/days, I found out the reason for a weird behavior I was seing in my ROOT-based C++ application for a DAQ system.
Long story short: the DAQ acquires data in several chunks, and each chunk readout takes 50 ms. After each readout, a
TThread::Printf()
is called. This makes each iteration take much more than 50ms, sometimes 100ms, sometimes 60ms, etc. (I observe a similar timing behaviour if I callEmit("...")
to communicate with another thread, instead ofPrintf
.)I created a minimal reproducer:
If I run this standalone example, I get as expected times in steps of 50 ms approx:
(A similar result is obtained if I use the
std::cout
statement instead of theTThread::Printf
.)Now the problem. If I run this same loop in an application with a GUI window and a
TThread
(full reproducer code is below), then I get quite weird results. The first step takes 107 ms ! And the later steps take 60 ms instead of 50 ms.(In contrast, if I use
std::cout
instead ofPrintf
, every step is perfectly 50 ms).I found out that on line https://github.com/root-project/root/blob/a89eb12f83228833842813c4b690a2033778316b/core/thread/src/TThread.cxx#L1043, there is a timer being created, with a timeout of 20 ms, https://github.com/root-project/root/blob/a89eb12f83228833842813c4b690a2033778316b/core/thread/inc/TThread.h#L208
If I remove the
+ 10
ms and recompile ROOT, I get better results, (except for the first iteration):Optional: share how it could be improved
It would be nice if there was a static method to tune the resolution of the
TThreadTimer
as well as theTSystem::kITimerResolution
for applications requiring high performance, so that there is no 10ms (or 100ms at the beginning) delay due to aPrintf()
(or anEmit()
for the signal-slot mechanism to communicate between threads).Right now,
ESysConstants::kItimerResolution
is not assignable at runtime, andTThreadTimer
timeout is not configurable by the user, thus the only solution is a fork and recompile.To Reproduce
Setup
Additional context
If you run the full example, you might find a deadlock at the end, just press CTRL+C to exit. The lock is maybe due to
TList
data race, see https://github.com/root-project/root/issues/8365#issuecomment-871005764 See also https://root-forum.cern.ch/t/performance-effects-in-a-root-based-data-acquisition/45519