Skip to content

Improve decode hot paths and collection handling#85

Open
greenm01 wants to merge 5 commits into
jangko:masterfrom
greenm01:perf-core
Open

Improve decode hot paths and collection handling#85
greenm01 wants to merge 5 commits into
jangko:masterfrom
greenm01:perf-core

Conversation

@greenm01
Copy link
Copy Markdown

Summary

  • Optimize decode hot paths (map dispatch, skip_msg, tuple/seq handling, list/ring decode)
  • Reduce allocations in skip_msg and JSON map key decoding
  • Improve collection packing for IntSet and list/ring types

Benchmarks

Nim 2.2.6, -d:release, 1,000,000 iters, median of 3 runs.

Array encoding

case upstream master perf-core
unpack sample 205.4 ns/op 200.8 ns/op
skip sample 285.3 ns/op 281.9 ns/op
unpack large 1810.5 ns/op 1777.6 ns/op
skip large 2096.9 ns/op 2107.8 ns/op
toAny large 3606.5 ns/op 3704.8 ns/op
toJson large 3945.9 ns/op 4132.6 ns/op

Map encoding

case upstream master perf-core
unpack sample 436.4 ns/op 438.5 ns/op
skip sample 477.1 ns/op 456.8 ns/op
unpack large 4028.5 ns/op 3917.1 ns/op
skip large 3798.9 ns/op 3818.5 ns/op
toAny large 7728.0 ns/op 7667.1 ns/op
toJson large 9562.3 ns/op 9215.4 ns/op

Notes: wins are modest overall; the most consistent gains show up in map decode/skip on the larger payload.

@greenm01
Copy link
Copy Markdown
Author

Bench setup: built with Nim 2.2.6, . Ran array encoding (default) and map encoding () with 1,000,000 iterations, took median of 3 runs for the table in the PR body. Same machine/toolchain for baseline vs perf-core.

@greenm01
Copy link
Copy Markdown
Author

Bench setup: bench/bench_decode.nim built with Nim 2.2.6, -d:release. Ran array encoding (default) and map encoding (-d:msgpack_obj_to_map) with 1,000,000 iterations, took median of 3 runs for the table in the PR body. Same machine/toolchain for baseline vs perf-core.

Comment thread src/msgpack4nim.nim
s.pack_array(count)
s.write(ss.data)
mixin pack_type
when compiles(val.len):
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Please use something like this to detect if it's an array like or not:

func is_array_like[N: int, T](x: array[N, T]): bool {.compileTime.} = true
func is_array_like[T](x: seq[T]): bool {.compileTime.} = true
func is_array_like(x: auto): bool {.compileTime.} = false

when is_array_like(distinctBase(val)):
   ...

@jangko
Copy link
Copy Markdown
Owner

jangko commented Jan 27, 2026

please rebase

… payloads don’t blow the call stack and we reduce call overhead.
… now read directly as strings (no temporary JsonNode), skip_msg is iterative to avoid recursion overhead, and IntSet packing now uses its cardinality so it can write directly without buffering.
…r string/bin/ext payloads instead of allocating discard strings, and let the generic skip_msg do the same when the underlying stream supports setPosition. See src/msgpack4nim.nim. Switched sequence unpack to setLen so existing capacity can be reused. See src/msgpack4nim.nim.
…o temporary MsgStream buffer).

- Lists/rings unpack by appending directly instead of staging a seq + reversing, and each element now uses a fresh ref to avoid aliasing.
…ctness while avoiding the VM recursion issue from the aborted compile‑time field count idea. The tuple paths now skip the extra count loop, and object map dispatch now covers multi‑identifier field declarations.

Changes
- Use tupleLen in tuple pack/unpack array branches to avoid counting fields at runtime in src/msgpack4nim.nim.
- Fix unpack_field_by_name to handle a, b: T style field declarations so map‑dispatch doesn’t miss fields in src/msgpack4nim.nim.
- Use a len‑fast path in pack_items_imp when val.len is available, avoiding the temporary buffer in src/msgpack4nim.nim.
- Pre‑size and fill anyArray for openArray/varargs to avoid repeated add growth in src/msgpack4nim/msgpack2any.nim.
@greenm01
Copy link
Copy Markdown
Author

greenm01 commented Feb 7, 2026

Rebased onto latest master.

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.

2 participants