Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ntuple] Support the storage of collections using the TVirtualCollectionProxy interface #11525

Merged

Conversation

jalopezg-git
Copy link
Collaborator

@jalopezg-git jalopezg-git commented Oct 10, 2022

This pull request introduces RField support for user-defined classes that behave as collections of elements. These classes specify a "collection proxy" that provides access to the elements in the collection.
A legacy collection proxy is provided in the form of an instance of a class derived from TVirtualCollectionProxy. The collection proxy for a class is typically set during initialization, usually using TClass::CopyCollectionProxy() or similar.

In this pull request, we introduce support for legacy collection proxies derived from the TVirtualCollectionProxy class, although in later stages, RNTuple might provide this functionality through an interface different interface.

At a bare minimum, the user is required to provide an implementation for the following functions in TVirtualCollectionProxy:

  • HasPointers(), GetProperties(), GetValueClass(), GetType(), Sizeof(): for general information about the collection and its value type.
  • Sizeof(), At(), Clear(), and Insert(): for element access
  • PushProxy(), PopProxy(): for selecting the target object.

A usage example can be seen here.

Changes or fixes:

  • Added class RCollectionClassField, representing a field of a user-defined class that behaves as a collection that is compliant with the TVirtualCollectionProxy interface.
    Given that the RField<T> primary template definition (that used if no specialization matches) uses RClassField to store members of a class, we rely on an additional helper type (IsCollectionProxy<T>) to annotate that a particular class has an associated collection proxy (see example below).
// Alternatively, this can be specified via a member type in the user-defined class; see the documentation
template <>
struct IsCollectionProxy<ProxiedCollection> : std::true_type {};

auto model = RNTupleModel::Create();
auto fieldKlass = model->MakeField<MyClass>("fieldKlass"); // Regular class
auto fieldCollection = model->MakeField<ProxiedCollection>("fieldCollection"); // Class with associated collection proxy

This tag is not required when using the type-erased interface (i.e., RFieldBase::Create()), as the use of a collection proxy can be determined at run time via TClass.

  • RCollectionClassField::ReadGlobalImpl(): reduce the number of virtual calls to TVirtualCollectionProxy::Insert() by reading and inserting a block of elements at once. The size of the buffer that holds the elements is set by RCollectionClassField::kReadChunkSize (in bytes).
  • Provide implementation and tests for RPrintValueVisitor::VisitCollectionClassField()
  • Add unit tests for collections of fundamental types, compound types, vector of a collection proxy, and nested collection proxies.
  • Update doc/specifications.md

Checklist:

  • tested changes locally
  • updated the docs (if necessary)

This PR fixes #11523.

Initial skeleton for supporting classes with an associated collection
proxy.  Object of such type behave as a collection of elements
accessible through the `TVirtualCollectionProxy` interface.
Reduce the number of virtual calls to `TVirtualCollectionProxy::Insert()`
by reading and inserting a block of elements at once.
@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/soversion, ROOT-performance-centos8-multicore/cxx17, ROOT-ubuntu18.04/nortcxxmod, ROOT-ubuntu2004/python3, mac1015/cxx17, mac11/cxx14, windows10/cxx14
How to customize builds

@jalopezg-git
Copy link
Collaborator Author

FYI, @mnowakgit 🙂

@phsft-bot
Copy link
Collaborator

Build failed on ROOT-ubuntu2004/python3.
Running on root-ubuntu-2004-3.cern.ch:/home/sftnight/build/workspace/root-pullrequests-build
See console output.

Errors:

  • [2022-10-10T12:04:15.629Z] FAILED: tmva/sofie/test/CMakeFiles/SofieCompileModels_ROOT.util

@phsft-bot
Copy link
Collaborator

Build failed on mac1015/cxx17.
Running on macitois22.dyndns.cern.ch:/Users/sftnight/build/workspace/root-pullrequests-build
See console output.

Warnings:

  • [2022-10-10T13:22:28.445Z] /Volumes/HD2/build/workspace/root-pullrequests-build/root/tree/ntuple/v7/test/ntuple_types.cxx:440:9: warning: 'Insert' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
  • [2022-10-10T13:22:28.445Z] /Volumes/HD2/build/workspace/root-pullrequests-build/root/tree/ntuple/v7/test/ntuple_types.cxx:440:9: warning: 'Insert' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
  • [2022-10-10T13:22:28.446Z] /Volumes/HD2/build/workspace/root-pullrequests-build/root/tree/ntuple/v7/test/ntuple_types.cxx:440:9: warning: 'Insert' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]

@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/soversion, ROOT-performance-centos8-multicore/cxx17, ROOT-ubuntu18.04/nortcxxmod, ROOT-ubuntu2004/python3, mac1015/cxx17, mac11/cxx14, windows10/cxx14
How to customize builds

@phsft-bot
Copy link
Collaborator

Build failed on ROOT-ubuntu2004/python3.
Running on root-ubuntu-2004-1.cern.ch:/home/sftnight/build/workspace/root-pullrequests-build
See console output.

Errors:

  • [2022-10-10T14:59:47.973Z] FAILED: lib/modules.idx

Copy link
Contributor

@jblomer jblomer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is awesome!

Some minor comments inline; for the tests: let's also test: vector of collection proxies, collection proxy of vectors and collection proxy of collection proxies.

tree/ntuple/v7/inc/ROOT/RNTupleView.hxx Outdated Show resolved Hide resolved
tree/ntuple/v7/inc/ROOT/RFieldVisitor.hxx Show resolved Hide resolved
tree/ntuple/v7/inc/ROOT/RField.hxx Outdated Show resolved Hide resolved
tree/ntuple/v7/inc/ROOT/RField.hxx Outdated Show resolved Hide resolved
tree/ntuple/v7/src/RField.cxx Show resolved Hide resolved
tree/ntuple/v7/inc/ROOT/RField.hxx Outdated Show resolved Hide resolved
tree/ntuple/v7/inc/ROOT/RField.hxx Show resolved Hide resolved
tree/ntuple/v7/src/RField.cxx Outdated Show resolved Hide resolved
tree/ntuple/v7/src/RField.cxx Outdated Show resolved Hide resolved
…emplate arg

Do not rely on the use of an additional "tag" argument to disambiguate
between the `RField` primary template definition that derives from
`RClassField` and the specialization for classes using a collection
proxy.

Instead, this commit introduces the `IsCollectionProxy<T>` template that
can be specialized to mark a specific class as a proxied collection.
@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/soversion, ROOT-performance-centos8-multicore/cxx17, ROOT-ubuntu18.04/nortcxxmod, ROOT-ubuntu2004/python3, mac1015/cxx17, mac11/cxx14, windows10/cxx14
How to customize builds

jalopezg-git and others added 5 commits October 17, 2022 17:00
Test the usage of collection proxies yielding elements of a fundamental
C++ type.
Test the usage of collection proxies whose value type is a compound type
with nested collections.
Co-authored-by: Jakob Blomer <jblomer@cern.ch>
@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/soversion, ROOT-performance-centos8-multicore/cxx17, ROOT-ubuntu18.04/nortcxxmod, ROOT-ubuntu2004/python3, mac1015/cxx17, mac11/cxx14, windows10/cxx14
How to customize builds

@phsft-bot
Copy link
Collaborator

Build failed on mac1015/cxx17.
Running on macitois21.dyndns.cern.ch:/Users/sftnight/build/workspace/root-pullrequests-build
See console output.

Failing tests:

…roxy

Co-authored-by: Philippe Canal <pcanal@fnal.gov>
@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/soversion, ROOT-performance-centos8-multicore/cxx17, ROOT-ubuntu18.04/nortcxxmod, ROOT-ubuntu2004/python3, mac1015/cxx17, mac11/cxx14, windows10/cxx14
How to customize builds

Copy link
Contributor

@jblomer jblomer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many thanks for the update! Not entirely through yet but some comments are ready for discussion.

tree/ntuple/v7/src/RField.cxx Show resolved Hide resolved
tree/ntuple/v7/test/CustomStruct.hxx Show resolved Hide resolved
tree/ntuple/v7/test/SimpleCollectionProxy.hxx Show resolved Hide resolved
@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/soversion, ROOT-performance-centos8-multicore/cxx17, ROOT-ubuntu18.04/nortcxxmod, ROOT-ubuntu2004/python3, mac1015/cxx17, mac11/cxx14, windows10/cxx14
How to customize builds

@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/soversion, ROOT-performance-centos8-multicore/cxx17, ROOT-ubuntu18.04/nortcxxmod, ROOT-ubuntu2004/python3, mac1015/cxx17, mac11/cxx14, windows10/cxx14
How to customize builds

@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/soversion, ROOT-performance-centos8-multicore/cxx17, ROOT-ubuntu18.04/nortcxxmod, ROOT-ubuntu2004/python3, mac1015/cxx17, mac11/cxx14, windows10/cxx14
How to customize builds

@phsft-bot
Copy link
Collaborator

Build failed on mac1015/cxx17.
Running on macitois21.dyndns.cern.ch:/Users/sftnight/build/workspace/root-pullrequests-build
See console output.

Failing tests:

`RClassField` and `RCollectionClassField` (used for regular user-defined
classes / classes with an associated collection proxy, respectively) should
throw if used unappropriately, i.e. if `RClassField` is instantiated to
handle a class that has a collection proxy set or viceversa.
@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/soversion, ROOT-performance-centos8-multicore/cxx17, ROOT-ubuntu18.04/nortcxxmod, ROOT-ubuntu2004/python3, mac1015/cxx17, mac11/cxx14, windows10/cxx14
How to customize builds

Copy link
Contributor

@jblomer jblomer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! From my side, that's good to go. It would probably be a good idea to still address Philippe's comment on `fProxy->Clear();.

tree/ntuple/v7/src/RField.cxx Outdated Show resolved Hide resolved
Instead of manually destroying collection items in `ReadGlobalImpl()`,
rely on `TVirtualCollectionProxy::Clear()`.

Rationale (a PR comment by jblomer):
The `DestroyValue` and `GenerateValue` calls should be symmetric. So if
the collection proxy takes care of cleaning memory, it should also be in
charge of (default)-constructing new elements on resize. I think that is
the case here. The `GenerateValue` call is only used on the internal buffer.
The collection then copies the elements from the internal buffer into its
own memory, IIUC.

Co-authored-by: Philippe Canal <pcanal@fnal.gov>
Co-authored-by: Jakob Blomer <jblomer@cern.ch>
@phsft-bot
Copy link
Collaborator

Starting build on ROOT-debian10-i386/soversion, ROOT-performance-centos8-multicore/cxx17, ROOT-ubuntu18.04/nortcxxmod, ROOT-ubuntu2004/python3, mac1015/cxx17, mac11/cxx14, windows10/cxx14
How to customize builds

@jalopezg-git jalopezg-git merged commit 072f91d into root-project:master Nov 10, 2022
@jalopezg-git jalopezg-git deleted the ntuple-tvirtualcollectionproxy branch November 10, 2022 20:24
Copy link
Member

@pcanal pcanal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[ntuple] Support the storage of collections that use legacy TVirtualCollectionProxy
4 participants