Skip to content

[skip-ci][ntuple] add SoA design document - #23202

Open
jblomer wants to merge 5 commits into
root-project:masterfrom
jblomer:ntuple-soa-doc
Open

jblomer wants to merge 5 commits into
root-project:masterfrom
jblomer:ntuple-soa-doc

Conversation

@jblomer

@jblomer jblomer commented Aug 31, 2026 •

Copy link
Copy Markdown
Contributor

Part of #19230

This should be merged once the first complete version of the code is ready. Submitted as a preview PR.

@jblomer jblomer self-assigned this Aug 31, 2026
@jblomer
jblomer requested a review from silverweed as a code owner August 31, 2026 13:16
@jblomer
jblomer marked this pull request as draft August 31, 2026 13:16
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

Test Results

    23 files      23 suites   3d 12h 29m 3s ⏱️
 3 860 tests  3 855 ✅ 0 💤 5 ❌
78 655 runs  78 649 ✅ 1 💤 5 ❌

For more details on these failures, see this check.

Results for commit 8333a10.

@jblomer jblomer changed the title [ski-ci][ntuple] add SoA design document [skip-ci][ntuple] add SoA design document Sep 1, 2026
@jblomer jblomer closed this Sep 1, 2026
@jblomer jblomer reopened this Sep 1, 2026
Comment thread tree/ntuple/doc/README.md
Comment thread tree/ntuple/doc/SoA.md Outdated
Comment thread tree/ntuple/doc/SoA.md Outdated
Comment thread tree/ntuple/doc/SoA.md
Comment thread tree/ntuple/doc/SoA.md Outdated
Comment thread tree/ntuple/doc/SoA.md Outdated
Comment thread tree/ntuple/doc/SoA.md Outdated
Comment thread tree/ntuple/doc/SoA.md Outdated
Comment thread tree/ntuple/doc/SoA.md Outdated
Comment thread tree/ntuple/doc/SoA.md Outdated
Comment thread tree/ntuple/doc/SoA.md
@jblomer
jblomer force-pushed the ntuple-soa-doc branch 2 times, most recently from 2fc5b05 to 95d209d Compare September 3, 2026 09:39
Comment thread tree/ntuple/doc/SoA.md Outdated
@jblomer
jblomer marked this pull request as ready for review October 10, 2026 22:56
Without dictionaries, RNTuple can still read data with an emulated schema derived from the RNTuple fields.
Type emulation reads classes as untyped records, collections as `std::vector`s, and custom enums as integers.
Type emulation works for all fields except streamer fields.
Emulated types cannot be used for writing, but they can be used for merging.

@pcanal pcanal Oct 16, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I guess this technically means that Emulated types can not be used to create field (but can be used for writing when merging). (Related questions, since the slow merging can append entries to existing RNTuple, can a clever user find a way to leverage that code to also write into an existing RNTuple?)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The merger does not close the output ntuple during merging, so it's not really appending to an existing one...

Comment thread tree/ntuple/doc/SoA.md Outdated
@@ -0,0 +1,111 @@
# SoA I/O in RNTuple

RNTuple has a mechanism to represent a collection of a class, i.e. an "array of struct" (AoS),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

represent

Would read back or connect be more accurate?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed to read and write

Comment thread tree/ntuple/doc/SoA.md
The data type of that data member in the SoA class must be either `RVec<T>` or
a SoA type that has `T` as an underlying record type (nested SoA type).
The SoA type must have no additional persistent data members.
- The SoA type and its underlying record type must have the same class version number.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is that a fundamental limitation? In particular this means that un-versioned class/struct are not eligible to be SOA. Should it be made more pro-eminent that the class need be versioned (either via a ClassDef (intrusive) or via a dictionary generation annotation (non intrusive to the underlying record type)?

@jblomer jblomer Oct 17, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's not a fundamental limitation, it is a limitation that we just impose for sanity. With this limitation, yes, I would like to not make SoA types available as unversioned class.

Comment thread tree/ntuple/doc/SoA.md
The SoA type must have no additional persistent data members.
- The SoA type and its underlying record type must have the same class version number.

These conditions are checked at runtime when an `RSoAField` is created.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Related to the question about version. Does it also check that the class is versioned or just that the class version match (2 un-versioned classes might have matching version by happenstance ... in which case upon reading back they may not have the same assigned version number).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We may be susceptible to this. The goal is enforcing versioned classes: #23749

Comment thread tree/ntuple/doc/SoA.md Outdated
Comment thread tree/ntuple/doc/SoA.md
- For every persistent member of type `T` in the underlying record type,
there must be a member with the same name in the SoA type.
The data type of that data member in the SoA class must be either `RVec<T>` or
a SoA type that has `T` as an underlying record type (nested SoA type).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
a SoA type that has `T` as an underlying record type (nested SoA type).
a SoA type that has `T` as an underlying record type (nested SoA type).
- For all the (persisted) instances of the SoA all the persistent data members much have the same number of elements.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, however that's not a restriction on the type. A few lines further down we have the line

Equal vector lengths are ensured by construction when reading from disk and checked when writing to disk.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It is an invariant of the class. The next section is different in a bit in nature. I.e. When I am reading it, I see this section as "this is what the class must have" while the later section is "and here is how we enforce those requirements"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Makes sense. I added a bullet point along these lines.

Comment thread tree/ntuple/doc/SoA.md
Comment on lines +103 to +105
For added members, reading will set the corresponding vector(s) to the collection length
and default-initialize the vector elements.
This is different to added members of normal classes, for which reading is a no-op.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This implies that the default-initialize is executed at each entry read. Is that correct? (i.e. at each entry we do the moral equivalent of vec.clear(); vec.resize(n);)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, that is correct.

Comment thread tree/ntuple/doc/SoA.md Outdated

@pcanal pcanal left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM.

This branch has not been deployed

No deployments
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.

5 participants