Writing a small columnar query engine and hit a string-copy trap in the filter operator. The fix turned out to be
measurable so I thought I'd share.
Naive version: output chunk built cell-by-cell.
for (idx_t i = 0; i < input.size(); i++) {
if (!matches[i]) continue;
for (idx_t c = 0; c < num_cols; c++)
result.SetValue(c, out, input.GetValue(c, i));
out++;
}
GetValue/SetValue go through a tagged Value type, and for VARCHAR they each allocate a fresh std::string. 1Mrows with a few VARCHAR columns means millions of allocations on a single filter pass.
Vectorized version: build a
uint32_t sel[] of matching row indices, then per column copy with the typed pointer.auto *s = src.GetData<int64_t>();
auto *d = dst.GetData<int64_t>();
for (idx_t i = 0; i < n; i++) d[i] = s[sel[i]];
Trivial for numeric types. For VARCHAR it's trickier:
string_t is a 16-byte type, inline for short strings, apointer to a heap-allocated payload for longer ones. Copying the 16 bytes is cheap. The problem is that the
long-string pointer aims at the source vector's string heap. Let src go out of scope and dst's strings point at freed
memory.
The string heap (
VectorStringBuffer) is already owned via shared_ptr<VectorBuffer>. Fix is a setter that makes dstadopt src's heap:
auto *s = src.GetData<string_t>();
auto *d = dst.GetData<string_t>();
for (idx_t i = 0; i < n; i++) d[i] = s[sel[i]];
dst.SetAuxiliaryPtr(src.GetAuxiliaryPtr()); // dst keeps src's heap alive
No string copies. Refcount bumps once per vector, not once per cell.
A
WHERE ... GROUP BY region query on 1M rows went from 894 ms to ~150 ms. Roughly 100 ms of that was this changealone; the rest was unrelated parallelism on another pass.
Question for the sub: is there a standard name for this pattern? "Copy handles that reference an upstream buffer,
retain the buffer as long as any handle lives." Arrow solves the same problem internally.
shared_ptr<Buffer>adoption feels manual. Curious what the idiomatic C++ answer is.
Repo if anyone wants the full context: https://github.com/SouravRoy-ETL/slothdb
https://redd.it/1sqj7ze
@r_cpp