Skip to content

Conversation

@jrick
Copy link
Member

@jrick jrick commented Dec 10, 2025

This special cases writes to bytes.Buffer, which is always the writer type written to by WriteMessageN. There are several optimizations that can be implemented by special casing this type:

First, pulling temporary short buffers from binary freelist can be skipped entirely, and instead the binary encoding of integers can be appended directly to its existing capacity. This avoids the synchronization cost to add and remove buffers from the free list, and for applications which only ever write wire messages with WriteMessageN, the allocation and ongoing garbage collection scanning cost to for these buffers can be completely skipped.

Second, special casing the buffer type in WriteVarString saves us from creating a temporary heap copy of a string, as the buffer's WriteString method can be used instead.

Third, special casing the buffer allows WriteMessageN to calculate the serialize size and grow its buffer so all remaining appends for writing block and transactions will not have to reallocate the buffer's backing allocation. This same optimization can be applied to other messages in the future.

@jrick jrick marked this pull request as draft December 10, 2025 15:59
@jrick

This comment was marked as outdated.

@jrick jrick force-pushed the optimize_write_buffer branch from 84a65f2 to 230fb69 Compare December 10, 2025 17:10
@jrick jrick marked this pull request as ready for review December 10, 2025 17:11
@jrick

This comment was marked as outdated.

@jrick

This comment was marked as outdated.

@jrick jrick force-pushed the optimize_write_buffer branch from 158b29e to a2cbcdf Compare December 10, 2025 21:10
@jrick
Copy link
Member Author

jrick commented Dec 10, 2025

Now rebased over #3584. Below is the performance improvement with both PRs, relative to master:

$ benchstat old.txt new.txt                                                   
goos: openbsd
goarch: amd64
pkg: github.com/decred/dcrd/wire
cpu: AMD Ryzen 7 5800X3D 8-Core Processor           
                │   old.txt   │               new.txt               │
                │   sec/op    │   sec/op     vs base                │
WriteMessageN-8   2.784µ ± 2%   1.652µ ± 1%  -40.67% (p=0.000 n=10)

                │  old.txt   │              new.txt               │
                │    B/op    │    B/op     vs base                │
WriteMessageN-8   592.0 ± 0%   328.0 ± 0%  -44.59% (p=0.000 n=10)

                │  old.txt   │              new.txt               │
                │ allocs/op  │ allocs/op   vs base                │
WriteMessageN-8   7.000 ± 0%   3.000 ± 0%  -57.14% (p=0.000 n=10)

@jrick jrick force-pushed the optimize_write_buffer branch 6 times, most recently from 2cda86f to a182543 Compare December 11, 2025 21:24
@jrick jrick force-pushed the optimize_write_buffer branch 3 times, most recently from b4a27d0 to 0ea4d52 Compare December 12, 2025 08:25
This special cases writes to bytes.Buffer, which is always the writer type
written to by WriteMessageN.  There are several optimizations that can be
implemented by special casing this type:

First, pulling temporary short buffers from binary freelist can be skipped
entirely, and instead the binary encoding of integers can be appended directly
to its existing capacity.  This avoids the synchronization cost to add and
remove buffers from the free list, and for applications which only ever write
wire messages with WriteMessageN, the allocation and ongoing garbage
collection scanning cost to for these buffers can be completely skipped.

Second, special casing the buffer type in WriteVarString saves us from
creating a temporary heap copy of a string, as the buffer's WriteString method
can be used instead.

Third, special casing the buffer allows WriteMessageN to calculate the
serialize size and grow its buffer so all remaining appends for writing block
and transactions will not have to reallocate the buffer's backing allocation.
This same optimization can be applied to other messages in the future.
@jrick jrick force-pushed the optimize_write_buffer branch from 0ea4d52 to 396b860 Compare December 12, 2025 14:12
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