Skip to content

perf(spanner): optimize query parameter encoding with direct type dispatch - #18359

Merged
olavloite merged 3 commits into
mainfrom
spanner-optimize-query-param-encoding
Oct 27, 2026
Merged

olavloite merged 3 commits into
mainfrom
spanner-optimize-query-param-encoding

Conversation

@olavloite

Copy link
Copy Markdown
Contributor

Replace the 15-branch isinstance cascade in _make_value_pb with a direct type-dispatch dictionary (_TYPE_ENCODERS) for built-in and SDK types, falling back to isinstance only for subclasses and mocks.

Also optimizes related helper functions:

  • Avoid duplicate Value allocations when validating bytes.
  • Check math.isfinite first in float encoding to speed up normal numbers.
  • Reuse value.as_tuple() in decimal precision and scale validation.
  • Use the protobuf NULL_VALUE enum instead of magic string literals.

@olavloite
olavloite requested a review from a team as a code owner September 13, 2026 16:17

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the serialization of Python types to Spanner protobuf values in _helpers.py by introducing a centralized _TYPE_ENCODERS mapping and optimizing type lookups, while retaining a fallback isinstance chain for subclass compatibility. It also updates unit tests to verify these new encoders and fallback paths. The review feedback points out potential TypeError issues in newer protobuf versions when passing raw bytes (such as base64-encoded values) directly to protobuf string_value fields, suggesting decoding them to UTF-8 strings first.

@olavloite
olavloite force-pushed the spanner-optimize-query-param-encoding branch from d589a5e to cb5af51 Compare September 13, 2026 16:46
@olavloite

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request refactors type encoding in _helpers.py by introducing a _TYPE_ENCODERS lookup dictionary and extracting type-specific encoder helpers to optimize performance. It also updates and expands the unit tests to cover subclass fallbacks and various data types. The review feedback suggests a performance optimization in _try_to_coerce_bytes to avoid unnecessarily instantiating a protobuf Value object during validation.

…patch

Replace the 15-branch `isinstance` cascade in `_make_value_pb` with a direct
type-dispatch dictionary (`_TYPE_ENCODERS`) for built-in and SDK types,
falling back to `isinstance` only for subclasses and mocks.

Also optimizes related helper functions:
- Avoid duplicate `Value` allocations when validating bytes.
- Check `math.isfinite` first in float encoding to speed up normal numbers.
- Reuse `value.as_tuple()` in decimal precision and scale validation.
- Use the protobuf `NULL_VALUE` enum instead of magic string literals.
@olavloite
olavloite force-pushed the spanner-optimize-query-param-encoding branch from cb5af51 to b5197da Compare September 13, 2026 16:56
@olavloite

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request refactors value encoding in the Google Cloud Spanner helper module by introducing a fast-path type encoder dictionary (_TYPE_ENCODERS) to optimize _make_value_pb performance, while retaining a fallback isinstance chain for subclasses and custom objects. It also refactors byte validation, improves numeric precision checks, and ensures base64-encoded protobuf messages are properly decoded to UTF-8 strings. Corresponding unit tests have been added and updated to verify these changes, including subclass fallback behavior. There are no review comments, and I have no feedback to provide.

olavloite added a commit that referenced this pull request Oct 8, 2026
Combines all non-draft, non-'do not merge' Spanner micro-optimization PRs:
- #18329: perf(spanner): optimize built-in metrics hot path and harden concurrency
- #18359: perf(spanner): optimize query parameter encoding with direct type dispatch
- #18379: perf(spanner): build ExecuteSqlRequest on the raw protobuf message
- #18408: perf(spanner): optimize request ID header generation and retry closures
- #18420: perf(spanner): prune lock and begin event allocations on single-use snapshots
- #18422: perf(spanner): avoid allocating empty RequestOptions on read and query paths
- #18602: perf(spanner): optimize single-chunk results and single-row lookups
- #18604: test(spanner): add tests for consuming PartialResultSet streams
@olavloite
olavloite merged commit f06497c into main Oct 27, 2026
56 checks passed
@olavloite
olavloite deleted the spanner-optimize-query-param-encoding branch October 27, 2026 09:11
parthea pushed a commit that referenced this pull request Nov 12, 2026
🤖 I have created a release *beep* *boop*
---


##
[3.72.0](google-cloud-spanner-v3.71.0...google-cloud-spanner-v3.72.0)
(2026-11-12)


### Features

* **dbapi:** wire timeout parameter through Connection to execute_sql
([#18484](#18484))
([98fc304](98fc304))
* declare Python3.15 support
([8775794](8775794))
* **spanner:** auth login support for Spanner Omni endpoints
([#18273](#18273))
([9e0548d](9e0548d))
* update API sources and regenerate
([#18797](#18797))
([be4d954](be4d954))


### Bug Fixes

* **google-cloud-spanner:** clear buffered DDL statements on rollback
and flush on autocommit
([#18636](#18636))
([15d6a2c](15d6a2c))
* **google-cloud-spanner:** do not replay DDL statements on transaction
retry
([#18625](#18625))
([78b9da2](78b9da2))
* **spanner:** correctly wrap async streaming calls in metrics
interceptor
([#18581](#18581))
([2d19b0a](2d19b0a))
* **spanner:** eliminate duplicate metrics capture and measure full
streaming latency
([#18605](#18605))
([a7678fd](a7678fd))
* **spanner:** record streaming operation completion when stream
finishes
([#18704](#18704))
([ddeae47](ddeae47))
* **spanner:** release transaction lock if inline begin fails
([#18409](#18409))
([dd24029](dd24029))
* **spanner:** stop deleting multiplexed sessions on rotation and close
([#18332](#18332))
([c38e960](c38e960))


### Performance Improvements

* **spanner:** add fast-path for multiplexed session acquisition
([#18317](#18317))
([9569b39](9569b39))
* **spanner:** avoid allocating empty RequestOptions on read and query
paths
([#18422](#18422))
([3743ff0](3743ff0))
* **spanner:** build ExecuteSqlRequest on the raw protobuf message
([#18379](#18379))
([6d91fec](6d91fec))
* **spanner:** eliminate redundant tracing span in run_in_transaction
([#18357](#18357))
([181e26a](181e26a))
* **spanner:** optimize built-in metrics hot path and harden concurrency
([#18329](#18329))
([f2a791f](f2a791f))
* **spanner:** optimize query option merging and prevent in-place
mutation
([#18358](#18358))
([8cb3c6a](8cb3c6a))
* **spanner:** optimize query parameter encoding with direct type
dispatch
([#18359](#18359))
([f06497c](f06497c))
* **spanner:** optimize query result decoding and type resolution
([#18330](#18330))
([ce72986](ce72986))
* **spanner:** optimize request ID header generation and retry closures
([#18408](#18408))
([ad03b95](ad03b95))
* **spanner:** optimize row popping in StreamedResultSet
([#18316](#18316))
([e66103d](e66103d))
* **spanner:** optimize single-chunk results and single-row lookups
([#18602](#18602))
([05b3775](05b3775))
* **spanner:** prune lock and begin event allocations on single-use
snapshots
([#18420](#18420))
([ab56473](ab56473))
* **spanner:** short-circuit trace_call when tracing is inactive
([#18356](#18356))
([58031be](58031be))
* **spanner:** support PartialResultSet.last with background stream
draining
([#18320](#18320))
([80efd63](80efd63))


### Documentation

* fix typos
([#18979](#18979))
([5c8baeb](5c8baeb))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
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