Skip to content

perf(cpp): enlarge the TsFile write stream page size to 64 KiB - #1087

Merged
ColinLeeo merged 7 commits into
developfrom
perf/write-stream-page-size
Nov 13, 2026
Merged

ColinLeeo merged 7 commits into
developfrom
perf/write-stream-page-size

Conversation

@ColinLeeo

Copy link
Copy Markdown
Contributor

Problem

TsFileIOWriter drains its pending bytes to the file one page at a time, so WRITE_STREAM_PAGE_SIZE (512 bytes, marked FIXME) is both the write() granularity and the per-flush allocation unit. A single chunk flush therefore issued dozens of tiny write() syscalls and allocated/freed a fresh page chain; in a sampled profile the write syscall alone was ~27% of the write path.

Change

Raise the page size to 64 KiB. A chunk's pending data now fits in one or two pages.

Benchmark

3.2M rows / 1000 devices / 4 columns, single thread, alternating dylib A/B:

page size write file size
512 B 0.595–0.617 s 47.39 MB
64 KiB 0.448–0.461 s 47.39 MB

~25% faster with identical output size.

Testing

Full C++ suite: 1454 tests passed. No file-format change.

Pending bytes are drained to the file one page at a time, so
WRITE_STREAM_PAGE_SIZE is both the write() granularity and the per-flush
allocation unit. At 512 bytes a single chunk flush issued dozens of tiny
write() syscalls and allocated a fresh page chain, which showed up as ~27%
of the write path in a sampled profile.

Raising it to 64 KiB keeps a chunk's data in one or two pages. On a
3.2M-row / 1000-device write the time drops from 0.60s to 0.45s (~25%)
with an identical output size.
The I/O writer drains pending bytes one 64 KiB stream page at a time, so
a chunk larger than one page is written as a chain of write() calls.

Write INT64 series of several sizes around the page boundary (one page,
just under, just over, and multiple pages) and read every value back.
This checks that the page chain is flushed in order and that a chunk
ending on a page boundary is not truncated.
@codecov-commenter

codecov-commenter commented Nov 12, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.57%. Comparing base (90c7862) to head (1c59272).
⚠️ Report is 2 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #1087      +/-   ##
===========================================
+ Coverage    66.51%   66.57%   +0.06%     
===========================================
  Files          778      782       +4     
  Lines        56577    56709     +132     
  Branches      9105     9134      +29     
===========================================
+ Hits         37633    37756     +123     
- Misses       17291    17295       +4     
- Partials      1653     1658       +5     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Review follow-up: the integration test claimed to cover a chunk ending
exactly on a page boundary, but the per-chunk metadata overhead means no
row count in it lands on a multiple of the page size, and
ByteStream::Consumer's exact-multiple branch had no test at all.

Add a Consumer test that drains byte streams of 0, one byte less than a
page, exactly one/two/three pages, and page multiples plus a partial tail,
asserting both the per-buffer lengths and the reassembled bytes.  Correct
the integration test's comment to say what it actually covers.
@ColinLeeo
ColinLeeo requested a balanced review from Copilot November 12, 2026 14:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

4 open issues
What changed in this PR

Improves TsFile write performance by increasing the TsFileIOWriter write-stream page size so flushes issue fewer write() syscalls and allocate fewer pages, while adding targeted tests for page-draining behavior.

Changes:

  • Increase WRITE_STREAM_PAGE_SIZE from 512 B to 64 KiB in TsFileIOWriter.
  • Add a ByteStream::Consumer test to cover exact page-multiple draining and partial tails.
  • Add an end-to-end writer/reader test intended to exercise multi-page chunk flushing.
File Description
cpp/​src/​file/​tsfile_io_writer.h Grow write-stream page size to 64 KiB and document rationale.
cpp/​test/​common/​allocator/​byte_stream_test.cc Add coverage for page-by-page draining, including exact-multiple boundaries.
cpp/​test/​writer/​tsfile_writer_test.cc Add a writer/reader test intended to validate correct flushing across multiple pages.

Review effort: Lite

Comment thread cpp/src/file/tsfile_io_writer.h Resolved
Comment thread cpp/test/writer/tsfile_writer_test.cc Resolved
Follow-up to review comments: declare WRITE_STREAM_PAGE_SIZE as
constexpr, keep the Consumer test inside namespace common, and assert
that the largest case still exceeds one write-stream page so the
multi-page drain cannot silently stop being exercised.
The test binds the constant to a reference (EXPECT_LT), which odr-uses
it; before C++17 a static constexpr data member then needs a definition,
and the Linux/LTO builds failed to link. Add the definition.
Parallel CTest processes can seed the name generator in the same clock
tick; one then removes the file another is opening (E_ALREADY_EXIST at
the fixture's open, observed as SEGFAULT / test failure on CI). Append
pid and a per-process counter, as the writer tests already do.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@ColinLeeo
ColinLeeo merged commit 2c22af7 into develop Nov 13, 2026
50 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants