Skip to content

feat(c-sdk): optional version/size fast-path and concurrent block reads - #564

Merged
somfornot merged 1 commit into
milvus-io:mainfrom
somfornot:perf/c-sdk-versioned-concurrent-read
Aug 27, 2026
Merged

feat(c-sdk): optional version/size fast-path and concurrent block reads#564
somfornot merged 1 commit into
milvus-io:mainfrom
somfornot:perf/c-sdk-versioned-concurrent-read

Conversation

@somfornot

Copy link
Copy Markdown
Collaborator

What

Two changes to the C SDK read path (talon_read_async), aimed at removing avoidable overhead when the caller already knows an object's identity.

1. Optional caller-supplied version + size (skip StatObject)

talon_read_async gains two new, independently-nullable parameters:

int talon_read_async(
    talon_client *client, const char *uri, uint64_t offset,
    uint8_t *dst, size_t dst_len,
    const char *version,          /* NULL = unknown */
    const uint64_t *object_size,  /* NULL = unknown */
    talon_callback callback, void *user_data, uint64_t *request_id_out);
  • Both non-NULL → fast path: the read uses the caller's version + size and skips the StatObject control round trip entirely. The caller owns keeping them current for the object generation being read.
  • Either NULL → the SDK resolves both with a StatObject first (the historical behavior); a lone supplied value is ignored, since a read cannot skip the stat without both halves.

object_size is a pointer specifically so "no valid size" (NULL) is distinct from "a genuinely empty object" (*object_size == 0, an unambiguous zero-byte read). EOF semantics are preserved: a size smaller than offset + dst_len yields a POSIX short read, and a size larger than the object surfaces as a read error rather than fabricated bytes.

2. Concurrent block fetches

A read spanning multiple blocks previously fetched them in a serial await loop. It now fans the per-block fetches out concurrently (a JoinSet over disjoint 'static sub-slices of the caller buffer), so a large read no longer pays one worker RTT per block in series.

Note

This is a breaking change to the C ABI of talon_read_async (two new parameters). Existing callers that want the previous behavior pass NULL, NULL. The in-repo header, smoke test, example, and MinIO e2e are all updated; the e2e adds a fast-path case that reuses the version + size from its stat.

Testing

  • cargo test -p talon-c: 13 unit tests pass, including new coverage for the fast path skipping the stat, version-without-size falling back to the stat, the empty-object (size == 0) fast path, and concurrent multi-block reassembly.
  • cargo clippy -p talon-c --all-targets clean; cargo fmt clean.
  • All C sources compile under -std=c11 -Wall -Wextra -Werror.

🤖 Generated with Claude Code

talon_read_async gains a version (const char*) and object_size
(const uint64_t*) parameter pair, each independently nullable. NULL means
the caller does not have that value. The read skips the StatObject control
round trip only when BOTH are non-NULL, using the caller-supplied version
and size; if either is NULL the SDK resolves both with a stat and ignores
any lone value, since a read cannot skip the stat without both halves.

Making object_size a pointer lets a caller that has a version but no valid
size say so (NULL) instead of guessing, and disambiguates a real empty
object (points to 0 -> zero-byte read, no stat) from "unknown" (NULL).
When used, *object_size bounds the read at EOF: smaller than the range is
a POSIX short read, larger surfaces as a clear worker error rather than
fabricated bytes.

The per-block fetches a multi-block read spans now run concurrently on the
runtime (JoinSet over disjoint 'static sub-slices of the caller buffer)
instead of a serial await loop, so a large read no longer pays one worker
RTT per block in series.

Header, smoke test, example, and the MinIO e2e are updated to the new
signature; the e2e also adds a fast-path case that reuses the version and
size from its stat.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@somfornot
somfornot merged commit dcfa3b8 into milvus-io:main Aug 27, 2026
21 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