Skip to content

[Root7] A path to reducing global object registration and management.#18083

Open
hageboeck wants to merge 10 commits intoroot-project:masterfrom
hageboeck:root7-memoryManagement
Open

[Root7] A path to reducing global object registration and management.#18083
hageboeck wants to merge 10 commits intoroot-project:masterfrom
hageboeck:root7-memoryManagement

Conversation

@hageboeck
Copy link
Copy Markdown
Member

@hageboeck hageboeck commented Mar 20, 2025

This is the start of a longer-term effort to transform ROOT into working with less globals, making ownership of objects clearer, and going more towards standard C++ behaviour instead of implicit ownership. One could call this the "ROOT 7 mode". In order to allow for early testing, this mode is introduced as an opt-in feature in ROOT 6.

What this PR brings

TROOT.h gets three new functions (names up for discussion):

   namespace ROOT::Experimental {
   void EnableObjectAutoRegistration();
   void DisableObjectAutoRegistration();
   bool ObjectAutoRegistrationEnabled();
   }

https://github.com/hageboeck/root/blob/040980428a842a3314c75bde1ba9e6ae208fe8b1/core/base/inc/TROOT.h#L100-L104

The naming and API is inspired by EnableImplicitMT() and its colleagues. These determine whether TObject-derived classes auto-register themselves to gDirectory when created. A well-known example is TH1 and all its derived classes, but what's covered by these functions will be extended further on the path to ROOT 7. Currently, this mode also covers RooFit objects, TGraph, and TEfficiency.
An extensive list of objects with auto registration and their state (maybe not fully complete) can be found below.

A lot of preparatory work was done to prepare ROOT to work both with auto registration on and off. A detailed list of this work can be found at the end. Currently, there is one commit that switches auto registration off across the entire CI to demonstrate that ROOT already today works in this mode. Once the PR is ready to merge, this commit will be removed to not break the workflows of ROOT's users who did not opt in. A single (or a few; TBD) builds with auto registration off will be added to the CI to keep test coverage for this feature.
TODO:

  • Remove the commit that globally switches auto registration off.

Difference to TH1::AddDirectoryStatus()

The ROOT 7 mode with auto registration off might look similar to TH1::AddDirectoryStatus(), but there are important differences:

  • DirectoryStatus is a static (global) bool while ObjectAutoRegistrationEnabled() is thread_local
  • DirectoryStatus only affects histogram-like objects (see table at the end). AutoRegistrationEnabled should eventually extend to more cases, e.g. RooFit objects, TEventList (planned), functions (planned).
  • DirectoryStatus affects the behaviour of TFile::Get. file->Get("name"); file->Get("name") returns the same object when directory status is true, and it reads a new object every time when it's false. I consider it best to not interfere here, because one can use TFile if such behaviour is desired, and RFile if not. AutoRegistrationEnabled() should only decide what happens to new objects, not objects read from a file.
  • DirectoryStatus cannot be set from the environment, and its default cannot be changed. It is a non-thread-safe runtime feature. AutoRegistrationEnabled() can be initialised from the environment (thread safe), and its state can be changed per thread, which might be vital for using it in MT frameworks.

Setting defaults

Some users or frameworks might be interested in operating in ROOT 7 mode already today, but they don't want to add calls to the above functions in each thread of their code. Especially for testing, they should be able to set a default without recompiling. Defaults can be set in a .rootrc:

Root.ObjectAutoRegistration: 0

and also using an environment variable:

ROOT_OBJECT_AUTO_REGISTRATION=0 ./executable --args

When any object queries ObjectAutoRegistrationEnabled(), a thread-safe initialisation is performed, taking defaults from the environment above. If no defaults are set, registration defaults to "on" in ROOT 6 and "off" in ROOT 7.

This, however, might lead to an "it worked on my machine" problem: Some users might have altered their environment, while others might have chosen the opposite. To make it obvious when a ROOT 6 runs in ROOT 7 preview mode, info messages such as the following are printed if the environment modifies the default:

$ ./executable --args
Info in <TROOT>: Object auto registration disabled using the environment variable ROOT_OBJECT_AUTO_REGISTRATION

(A similar message exists for rootrc)

List of classes covered (or intended to be covered) by "DisableObjectAutoRegistration"

Auto registration disabled with DisableObjectAutoRegistration() How could it be disabled before? Comments
TH1 and derived Yes TH1::AddDirectoryStatus()
TGraph2D Yes TH1::AddDirectoryStatus()
RooPlot Yes RooPlot::addDirectoryStatus()
TEfficiency Yes (New) Was inconsistent
TProfile2D Yes TH1::AddDirectoryStatus()
RooDataHist Already off Already off
RooDataSet Already off Already off
RooDirItem Already off Already off
RooFitResult Already off Already off
TEntryList Yes (in the future) Not possible To be done later
TEventList Yes (in the future) Not possible To be done later
TTree Probably no (to be decided) Unclear if it should be changed. It would be broken without being attached to a file
TBranch No It needs to know what its tree is
TChain, TNTuple No Same as for TTree
TFunction Probably yes, in the future. To be decided This is a registration not to gDirectory but to a global list of functions. Way forward to be decided.

TODOs:

  • Add tests for implicit / explicit registration of TH1s
  • Deprecate TH1::AddDirectory() as suggested in Replace TH1::AddDirectory by TDirectory::TContext #21523 ?
    • In Doxygen, it is already marked as deprecated, but a C++ deprecation should probably happen a bit later on the way to ROOT 7.
    • Merge the PRs below to make ROOT ready for running both with and without auto registration.

Preparatory work

The following PRs were part of this branch, and have been split off over time to separate the introduction of this feature from preparing ROOT to work both with auto registration off and on:

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 21, 2025

Test Results

    22 files      22 suites   3d 7h 37m 40s ⏱️
 3 833 tests  3 831 ✅  1 💤 1 ❌
75 672 runs  75 653 ✅ 18 💤 1 ❌

For more details on these failures, see this check.

Results for commit cdbb2be.

♻️ This comment has been updated with latest results.

@pcanal pcanal dismissed a stale review March 23, 2025 15:29

Please tell us why you approve this request.

@hageboeck hageboeck force-pushed the root7-memoryManagement branch from 4d29c60 to 1224a4b Compare September 5, 2025 15:50
@hageboeck hageboeck force-pushed the root7-memoryManagement branch from b894456 to 167c0cc Compare November 3, 2025 10:35
@hageboeck hageboeck added the clean build Ask CI to do non-incremental build on PR label Nov 3, 2025
@hageboeck hageboeck force-pushed the root7-memoryManagement branch from 342a3cb to 0ca4f8a Compare November 5, 2025 17:34
@hageboeck hageboeck force-pushed the root7-memoryManagement branch from 0ca4f8a to 68de9c4 Compare January 14, 2026 13:23
@hageboeck hageboeck force-pushed the root7-memoryManagement branch from 68de9c4 to 9c5ce87 Compare January 21, 2026 12:53
@hageboeck hageboeck force-pushed the root7-memoryManagement branch from 9c5ce87 to b79032e Compare February 10, 2026 17:35
@hageboeck hageboeck force-pushed the root7-memoryManagement branch 2 times, most recently from 74a6279 to 8d9511a Compare February 12, 2026 16:52
@hageboeck hageboeck force-pushed the root7-memoryManagement branch 2 times, most recently from 0b52df2 to c9f787b Compare March 6, 2026 16:13
@hageboeck hageboeck force-pushed the root7-memoryManagement branch 4 times, most recently from 3878984 to 0587de2 Compare March 20, 2026 15:51
@hageboeck hageboeck force-pushed the root7-memoryManagement branch 5 times, most recently from ea71574 to d64008f Compare March 24, 2026 16:23
@hageboeck hageboeck force-pushed the root7-memoryManagement branch 5 times, most recently from b3832cb to 69aac58 Compare March 27, 2026 10:24
@hageboeck hageboeck changed the title [Root7] A path to reducing global memory management. [Root7] A path to reducing global object registration and management. Mar 27, 2026
@hageboeck hageboeck marked this pull request as ready for review March 27, 2026 14:03
@hageboeck hageboeck force-pushed the root7-memoryManagement branch from 69aac58 to 04c468b Compare March 27, 2026 14:13
The ROOT 7 ownership settings don't affect TH1::AddDirectoryStatus, so
objects read from a TFile associate themselves with that file. In light
of adding the ROOT 7 mode "auto registration off", the doxygen was
improved a bit.
- Don't rely on implicit registration to directories.
- Make the test insensitive to any defaults by always adding the
  histogram to the file.
- Make ruff happier.
- When the object auto registration is switched to ROOT 7 mode, the
corresponding notification needs to be masked from output diffs and/or
the RootTestDriver checks.
- Ruff formatting
- Add Enable/DisableObjectAutoRegistration() in ROOT::Experimental.
- Add a function to test if registration is on or off.
- Allow for setting defaults using
  - The environment variable ROOT_OBJECT_AUTO_REGISTRATION
  - The rootrc variable Root.ObjectAutoRegistration
…ph2D.

In locations where TH1::AddDirectoryStatus is queried, also query
ObjectAutoRegistrationEnabled(). This extends the ROOT 7 testing mode to
TH1 and derived classes, TGraph2D and TEfficiency.
This is supposed to test auto registration off across all platforms.
Once approved, this commit will be removed, and a dedicated build will
be used to keep testing this functionality until the release of ROOT 7.
@hageboeck hageboeck force-pushed the root7-memoryManagement branch from 04c468b to cdbb2be Compare March 27, 2026 15:52
@couet couet removed their request for review March 27, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clean build Ask CI to do non-incremental build on PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants