Skip to content

Per-row cost of a batch preview: ~52 µs/row inside the library on a realistic ingest shape (measured) #504

Open

Description

@EricAndrechek

Per-row cost of a batch preview on a realistic ingest shape: most of it is inside the library. Measured end to end by a downstream consumer (measured by the reporter).

Setup:

  • Graviton4, 8 cores; go v1.0.2 with the production library build 20261004.052404.
  • One 100-row NDJSON batch per call, into an 8-column table.
  • A row filter, JSONCompactEachRow export, WithDocFlags(0).
where cost
inside the library, per call about 0.9 ms
inside the library, per row about 52 µs
per row, end to end at concurrency 32 about 75 µs
Go-side decode of the result, per row about 3.5 µs
cgo overhead and GC negligible
a hand-written validator for the same shape, per row about 22 µs (the reporter's own baseline)

Reading: the binding's own share (decode, cgo, GC) is small. The per-row time is spent inside the library's preview path.

Next: the artifact producer is profiling the preview path, to find where the per-row time goes. That covers the parse, the defaults, the constraint and filter evaluation, the export, and the per-call setup behind the ~0.9 ms. Findings and any fix will be posted here. A fix would be a library change, so all four bindings benefit together.

Related: #456 (Go Rows scaling across goroutines, closed) and #480 (one shared handle's scaling).

🤖 Generated with Claude Code

Activity

  1. EricAndrechek commented on Oct 6, 2026

    @EricAndrechek
    MemberAuthor

    Per-row costs on production library build 20261006.170903 (measured by the artifact producer, on public table shapes, Graviton4, 8 cores):

    • A shared schema at 8 concurrent callers costs about 22.3 µs/row, against 34.0 µs/row on 20261004.052404; one schema per thread costs 24.2 µs/row. This repository's own scaling re-measure is on One shared handle should scale across threads like N separate handles #480.
    • A row-dependent DEFAULT f(other_column) adds about 98 µs/row, because its expression is analysed once per row. A library fix is in progress, and the cost stays until a build ships it. A DEFAULT that reads no other column does not pay it. This is now documented in docs/reference/bindings-v1.md §3.
    • Most of the remaining per-row CPU is allocation and bookkeeping in the library's batch path, which runs a batch as one-row pipelines. Changing that is also in progress, as is rendering the v1 document more directly.
    • input_format_allow_errors_ratio had no measurable effect on valid bodies.

    We'll post the build that removes each cost here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions