Skip to content

Commit 0204587

Browse files
committed
start adapting slicing
1 parent 948ac94 commit 0204587

2 files changed

Lines changed: 22 additions & 42 deletions

File tree

Framework/Core/include/Framework/ASoA.h

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ void missingFilterDeclaration(int hash, int ai);
5858
void notBoundTable(const char* tableName);
5959
void* extractCCDBPayload(char* payload, size_t size, TClass const* cl, const char* what);
6060

61+
static constexpr char asciiToLower(char c);
62+
6163
template <typename... C>
6264
auto createFieldsFromColumns(framework::pack<C...>)
6365
{
@@ -1316,8 +1318,8 @@ static constexpr auto hasColumnForKey(framework::pack<C...>, std::string_view ke
13161318
return std::ranges::equal(
13171319
str1, str2,
13181320
[](char c1, char c2) {
1319-
return std::tolower(static_cast<unsigned char>(c1)) ==
1320-
std::tolower(static_cast<unsigned char>(c2));
1321+
return asciiToLower(static_cast<unsigned char>(c1)) ==
1322+
asciiToLower(static_cast<unsigned char>(c2));
13211323
});
13221324
};
13231325
return (caseInsensitiveCompare(C::inherited_t::mLabel, key) || ...);
@@ -1418,12 +1420,7 @@ struct PreslicePolicySorted : public PreslicePolicyBase {
14181420
void updateSliceInfo(SliceInfoPtr&& si);
14191421

14201422
SliceInfoPtr sliceInfo;
1421-
std::shared_ptr<arrow::Table> getSliceFor(int value, std::shared_ptr<arrow::Table> const& input, uint64_t& offset) const;
1422-
// One-slot cache for the empty (0-row) slice, so that empty groups do not
1423-
// slice every column only to produce 0 rows (the common case for sparse
1424-
// grouping, e.g. candidates per collision). Keyed by the input table, which
1425-
// changes with every dataframe.
1426-
mutable std::pair<arrow::Table const*, std::shared_ptr<arrow::Table>> emptySlice{nullptr, nullptr};
1423+
o2::soa::ArrowTableRef getSliceFor(int value, o2::soa::ArrowTableRef const& input) const;
14271424
};
14281425

14291426
struct PreslicePolicyGeneral : public PreslicePolicyBase {
@@ -1447,14 +1444,14 @@ struct PresliceBase : public Policy {
14471444
{
14481445
}
14491446

1450-
std::shared_ptr<arrow::Table> getSliceFor(int value, std::shared_ptr<arrow::Table> const& input, uint64_t& offset) const
1447+
o2::soa::ArrowTableRef getSliceFor(int value, o2::soa::ArrowTableRef const& input) const
14511448
{
14521449
if constexpr (OPT) {
14531450
if (Policy::isMissing()) {
14541451
return nullptr;
14551452
}
14561453
}
1457-
return Policy::getSliceFor(value, input, offset);
1454+
return Policy::getSliceFor(value, input);
14581455
}
14591456

14601457
std::span<const int64_t> getSliceFor(int value) const
@@ -1524,8 +1521,7 @@ auto doSliceBy(T const* table, o2::framework::PresliceBase<C, Policy, OPT> const
15241521
missingOptionalPreslice(getLabelFromType<std::decay_t<T>>().data(), container.bindingKey.key.c_str());
15251522
}
15261523
}
1527-
uint64_t offset = 0;
1528-
auto out = container.getSliceFor(value, table->asArrowTable(), offset);
1524+
auto out = container.getSliceFor(value, table->asArrowTableRef());
15291525
auto t = typename T::self_t({out}, offset);
15301526
if (t.tableSize() != 0) {
15311527
table->copyIndexBindings(t);
@@ -1537,7 +1533,7 @@ auto doSliceBy(T const* table, o2::framework::PresliceBase<C, Policy, OPT> const
15371533
template <soa::is_filtered_table T>
15381534
auto doSliceByHelper(T const* table, std::span<const int64_t> const& selection)
15391535
{
1540-
auto t = soa::Filtered<typename T::base_t>({table->asArrowTable()}, selection);
1536+
auto t = soa::Filtered<typename T::base_t>({table->asArrowTableRef()}, selection);
15411537
if (t.tableSize() != 0) {
15421538
table->copyIndexBindings(t);
15431539
t.bindInternalIndicesTo(table);
@@ -1550,7 +1546,7 @@ template <soa::is_table T>
15501546
requires(!soa::is_filtered_table<T>)
15511547
auto doSliceByHelper(T const* table, std::span<const int64_t> const& selection)
15521548
{
1553-
auto t = soa::Filtered<T>({table->asArrowTable()}, selection);
1549+
auto t = soa::Filtered<T>({table->asArrowTableRef()}, selection);
15541550
if (t.tableSize() != 0) {
15551551
table->copyIndexBindings(t);
15561552
t.bindInternalIndicesTo(table);
@@ -1574,17 +1570,17 @@ auto doSliceBy(T const* table, o2::framework::PresliceBase<C, Policy, OPT> const
15741570
SelectionVector sliceSelection(std::span<int64_t const> const& mSelectedRows, int64_t nrows, uint64_t offset);
15751571

15761572
template <soa::is_filtered_table T>
1577-
auto prepareFilteredSlice(T const* table, std::shared_ptr<arrow::Table> slice, uint64_t offset)
1573+
auto prepareFilteredSlice(T const* table, o2::soa::ArrowTableRef slice)
15781574
{
1579-
if (offset >= static_cast<uint64_t>(table->tableSize())) {
1575+
if (slice.range.offset >= static_cast<uint64_t>(table->tableSize())) {
15801576
Filtered<typename T::base_t> fresult{{{slice}}, SelectionVector{}, 0};
15811577
if (fresult.tableSize() != 0) {
15821578
table->copyIndexBindings(fresult);
15831579
}
15841580
return fresult;
15851581
}
1586-
auto slicedSelection = sliceSelection(table->getSelectedRows(), slice->num_rows(), offset);
1587-
Filtered<typename T::base_t> fresult{{{slice}}, std::move(slicedSelection), offset};
1582+
auto slicedSelection = sliceSelection(table->getSelectedRows(), slice->num_rows(), slice.range.offset);
1583+
Filtered<typename T::base_t> fresult{{{slice}}, std::move(slicedSelection)};
15881584
if (fresult.tableSize() != 0) {
15891585
table->copyIndexBindings(fresult);
15901586
}
@@ -1600,9 +1596,8 @@ auto doFilteredSliceBy(T const* table, o2::framework::PresliceBase<C, framework:
16001596
missingOptionalPreslice(getLabelFromType<T>().data(), container.bindingKey.key.c_str());
16011597
}
16021598
}
1603-
uint64_t offset = 0;
1604-
auto slice = container.getSliceFor(value, table->asArrowTable(), offset);
1605-
return prepareFilteredSlice(table, slice, offset);
1599+
auto slice = container.getSliceFor(value, table->asArrowTable());
1600+
return prepareFilteredSlice(table, slice);
16061601
}
16071602

16081603
std::function<framework::ConcreteDataMatcher(framework::ConcreteDataMatcher&&)> originReplacement(header::DataOrigin newOrigin);
@@ -1613,10 +1608,7 @@ auto doSliceByCached(T const* table, framework::expressions::BindingNode const&
16131608
auto localCache = cache.ptr->getCacheFor({"", originReplacement(cache.ptr->newOrigin)(o2::soa::getMatcherFromTypeForKey<T>(node.name)),
16141609
node.name});
16151610
auto [offset, count] = localCache.getSliceFor(value);
1616-
// Empty group: reuse a cached empty (0-row) table instead of slicing every column.
1617-
auto slice = count == 0 ? cache.ptr->getEmptySliceFor(table->asArrowTable())
1618-
: table->asArrowTable()->Slice(static_cast<uint64_t>(offset), count);
1619-
auto t = typename T::self_t({slice}, static_cast<uint64_t>(offset));
1611+
auto t = typename T::self_t({table->asArrowTableRef().slice(static_cast<uint64_t>(offset), count)});
16201612
if (t.tableSize() != 0) {
16211613
table->copyIndexBindings(t);
16221614
}
@@ -1629,10 +1621,7 @@ auto doFilteredSliceByCached(T const* table, framework::expressions::BindingNode
16291621
auto localCache = cache.ptr->getCacheFor({"", originReplacement(cache.ptr->newOrigin)(o2::soa::getMatcherFromTypeForKey<T>(node.name)),
16301622
node.name});
16311623
auto [offset, count] = localCache.getSliceFor(value);
1632-
// Empty group: reuse a cached empty (0-row) table instead of slicing every column.
1633-
auto slice = count == 0 ? cache.ptr->getEmptySliceFor(table->asArrowTable())
1634-
: table->asArrowTable()->Slice(static_cast<uint64_t>(offset), count);
1635-
return prepareFilteredSlice(table, slice, offset);
1624+
return prepareFilteredSlice(table, table->asArrowTableRef().slice(static_cast<uint64_t>(offset), count));
16361625
}
16371626

16381627
template <soa::is_table T>
@@ -1641,14 +1630,14 @@ auto doSliceByCachedUnsorted(T const* table, framework::expressions::BindingNode
16411630
auto localCache = cache.ptr->getCacheUnsortedFor({"", originReplacement(cache.ptr->newOrigin)(o2::soa::getMatcherFromTypeForKey<T>(node.name)),
16421631
node.name});
16431632
if constexpr (soa::is_filtered_table<T>) {
1644-
auto t = typename T::self_t({table->asArrowTable()}, localCache.getSliceFor(value));
1633+
auto t = typename T::self_t({table->asArrowTableRef()}, localCache.getSliceFor(value));
16451634
if (t.tableSize() != 0) {
16461635
t.intersectWithSelection(table->getSelectedRows());
16471636
table->copyIndexBindings(t);
16481637
}
16491638
return t;
16501639
} else {
1651-
auto t = Filtered<T>({table->asArrowTable()}, localCache.getSliceFor(value));
1640+
auto t = Filtered<T>({table->asArrowTableRef()}, localCache.getSliceFor(value));
16521641
if (t.tableSize() != 0) {
16531642
table->copyIndexBindings(t);
16541643
}

Framework/Core/src/ASoA.cxx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -348,19 +348,10 @@ void PreslicePolicyGeneral::updateSliceInfo(SliceInfoUnsortedPtr&& si)
348348
sliceInfo = si;
349349
}
350350

351-
std::shared_ptr<arrow::Table> PreslicePolicySorted::getSliceFor(int value, std::shared_ptr<arrow::Table> const& input, uint64_t& offset) const
351+
o2::soa::ArrowTableRef PreslicePolicySorted::getSliceFor(int value, o2::soa::ArrowTableRef const& input) const
352352
{
353353
auto [offset_, count] = this->sliceInfo.getSliceFor(value);
354-
offset = static_cast<int64_t>(offset_);
355-
if (count == 0) {
356-
// Empty group: avoid slicing every column only to discard it. Cache one
357-
// empty (0-row) table per input table and reuse it (see GroupSlicer).
358-
if (emptySlice.first != input.get()) {
359-
emptySlice = {input.get(), input->Slice(0, 0)};
360-
}
361-
return emptySlice.second;
362-
}
363-
return input->Slice(offset_, count);
354+
return input.slice({offset_, count});
364355
}
365356

366357
std::span<const int64_t> PreslicePolicyGeneral::getSliceFor(int value) const

0 commit comments

Comments
 (0)