mirror of
https://github.com/milvus-io/milvus.git
synced 2026-07-21 18:25:44 +00:00
issue: #50742 ## What this PR does Optimizes protobuf decoding on Milvus RPC read/write hot paths with a hand-written decoder in `pkg/util/fastpb`. The final change contains no gRPC connection-pool or connection-count changes. ## Fast decoder coverage The gRPC `releaseCodec.Unmarshal` path dispatches these top-level messages to fastpb: - `internalpb.RetrieveResults` - `milvuspb.InsertRequest` - `milvuspb.UpsertRequest` `schemapb.SearchResultData` is not a top-level codec-dispatched message. It is decoded directly from `SlicedBlob` at the search/reduce hot paths in: - `internal/proxy/search_reduce_util.go` - `internal/querynodev2/segments/result.go` - `internal/querynodev2/local_worker.go` - `internal/querynodev2/tasks/search_task_go_reduce.go` Nested hot messages such as `FieldData`, scalar/vector arrays, and IDs are decoded by the same package. Main optimizations: - varchar string arrays use one backing byte arena, reducing per-string allocations - packed float vectors use a single memcpy into self-owned memory - cold, complex, unknown, and mismatched fields delegate or merge through the official protobuf codec - no new external dependency or source-buffer aliasing ## Compatibility boundary The compatibility contract depends on the data path: - **Untrusted client ingress (`InsertRequest` and `UpsertRequest`)** validates proto3 strings as UTF-8 and is tested differentially against `proto.Unmarshal`, including malformed input behavior. - **Trusted internal result paths (`SearchResultData`, `RetrieveResults`, and direct `FieldData` decoding)** assume canonical Milvus/segcore protobuf output and intentionally skip UTF-8 validation for performance. Therefore these paths do not claim equivalence for arbitrary adversarial wire containing invalid UTF-8. Within that boundary, the decoder preserves the protobuf behaviors exercised by the differential tests: - proto2 groups fall back to the official codec - known fields with mismatched wire types fall back to the official codec - unknown and future fields are preserved through an official merge pass - repeated singular messages merge from the raw wire, including explicitly encoded proto3 default values - repeated message-valued oneof members merge correctly, while different variants remain last-wins - mixed packed and unpacked scalar encodings preserve wire order - descriptor field-set tripwires force decoder review when the protobuf schema changes The unsafe packed-float copy assumes the currently supported little-endian Milvus targets such as x86-64 and arm64. ## Benchmarks fastpb vs official `proto.Unmarshal`, using 1000-row payloads: | path | payload | speedup | allocations/op | |---|---|---:|---:| | search / query | varchar | about 2x | about 1000-2035 to about 10-17 | | search / query | float vector, dim 768 | about 6x | unchanged | | insert | varchar with UTF-8 validation | about 1.8x | 1019 to about 10 | ## Verification - unit and differential tests cover field descriptors, UTF-8 contracts, wire-type mismatches, proto2 groups, unknown fields, packed/unpacked ordering, oneof behavior, and repeated-message merge semantics - randomized canonical-message equivalence tests cover search, retrieve, insert, and upsert payloads - `go test ./util/fastpb ./util/resource` passes - `go vet ./util/fastpb ./util/resource` passes - current full CI and end-to-end status is tracked by the PR checks 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: xiaofanluan <xiaofan.luan@zilliz.com> Signed-off-by: xiaofanluan <xf@hjjaq.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: xiaofanluan <xf@hjjaq.com>