Skip to content

perf: mark the writer noalias in the writing helpers - #51

Merged
lalinsky merged 1 commit into
mainfrom
encode-noalias
Oct 13, 2026
Merged

lalinsky merged 1 commit into
mainfrom
encode-noalias

Conversation

@lalinsky

Copy link
Copy Markdown
Owner

Stacked on #50.

The writer's buffer is a []u8, and a byte store may alias anything, including the Writer struct itself. So after every write into the buffer, the compiler has to reload end, buffer.ptr and buffer.len before the next write. A run of small writes becomes a chain of dependent loads and stores through memory.

noalias on writeByte, writeAll, packHeaderAndInt and packStringLiteral tells it that the buffer stores leave the writer alone. These are leaves that never hand the writer to other code, so the promise is easy to keep. Functions that pass the writer on, such as packAny, which can call a user's msgpackWrite, are left alone.

Cycles per encode, same setup as #50:

case before after
order (struct with 8 fields, 4 nested items) 343 257 -25%
ints (array of 1000 mixed-size u32) 8864 8939 flat

The instruction count barely moves (804 → 786 for order); the saving is the dependency chain. The int array is one call per element, so there's no run of writes for it to help.

Tests pass on 0.16 and 0.17, and in ReleaseFast.

@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 55 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: cc8519e2-6fd8-4b4d-833a-4eb53eb504a8
📥 Commits

Reviewing files that changed from the base of the PR and between d1fd498 and 9ee8387.

📒 Files selected for processing (10)
  • CHANGELOG.md
  • src/array.zig
  • src/binary.zig
  • src/bool.zig
  • src/int.zig
  • src/map.zig
  • src/msgpack.zig
  • src/null.zig
  • src/string.zig
  • src/utils.zig
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@lalinsky
lalinsky added this pull request to stack #52 October 13, 2026 08:40
Base automatically changed from encode-perf to main October 13, 2026 08:46
The writer's buffer is a []u8, and a byte store may alias anything,
including the writer struct itself. So after every byte written into the
buffer, the compiler has to reload end, buffer.ptr and buffer.len before
the next write, and a run of small writes becomes a chain of dependent
loads and stores through memory.

noalias on writeByte, writeAll, packHeaderAndInt and packStringLiteral
tells it that the stores into the buffer leave the writer alone. These
are leaves that never hand the writer to other code, so the promise is
easy to keep. The functions that do pass the writer on, such as packAny,
which can call a user's msgpackWrite, are left as they are.

Cycles per encode, ReleaseFast, perf stat:

    case     before   after
    order      343     257   -25%   struct with 8 fields, 4 nested items
    ints      8864    8939   flat   array of 1000 mixed-size u32

The instruction count barely moves (804 -> 786 for order); the saving is
in the dependency chain. The int array is one call per element, so there
is no run of writes for it to help.
@lalinsky
lalinsky merged commit 74700c6 into main Oct 13, 2026
4 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.

1 participant