← 输入框|github.com|刷新
Skip to content

perf: Key registry proto caches on version_id so a refresh does not rebuild objects - #7073

Open
chandlerok wants to merge 2 commits into
feast-dev:masterfrom
chandlerok:perf/online-response-arrow-and-registry-cache
Open

chandlerok wants to merge 2 commits into
feast-dev:masterfrom
chandlerok:perf/online-response-arrow-and-registry-cache

Conversation

@chandlerok

@chandlerok chandlerok commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

The registry_proto_cache decorators in proto_registry_utils keyed on id(registry_proto) as well as version_id. A registry refresh parses a new proto object, so every refresh missed the cache and rebuilt every object from proto even when the registry had not changed. With 14 feature services that rebuild is about 35 ms per refresh, most of it typeguard checks in Field.__init__. Measured locally with a file registry, refresh plus list_feature_services(allow_cache=True):

per refresh
before 34.9 ms
after 0.1 ms

Changes:

  • Key the three cache decorators on version_id alone. A registry without a version_id falls back to object identity, which is today's behavior.
  • Cache get_feature_service per version with the existing registry_proto_cache_name decorator. get_online_features calls it on every request and it rebuilt the FeatureService from proto each time, about 2 ms per call.
  • Stamp SqlRegistry.proto() and SnowflakeRegistry.proto() with a version_id. Neither set one, so for those registries the caches would have kept falling back to object identity and missing on every refresh. The value is the sha1 of the deterministic serialization, stable across refreshes and different after any apply or delete. On a 421 KB proto the hash costs 0.2 ms. The file, S3, GCS, Azure, and HDFS stores already stamp a uuid on each write.

Profiled effect on get_online_features with a file registry, 100 entities, 4 feature views: a warm read has no from_proto or typeguard frames left on the registry side. The first read after a refresh costs 14.2 ms against 19.6 ms with the old object-identity key, and the same 5 ms saving now applies to SQL-registry deployments once per cache refresh.

No behavior change for callers. Cached objects were already shared between calls on the same proto object.

Which issue(s) this PR fixes:

Refs #7072 (proposal 3)

Checks

  • I've made sure the tests are passing.
  • My commits are signed off (git commit -s)
  • My PR title follows conventional commits format

Testing Strategy

  • Unit tests
  • Integration tests
  • Manual tests
  • Testing is not required for this change

Unit tests cover a re-parsed proto with the same version_id hitting the cache, a new version_id missing it, registries without a version_id staying per-object, get_feature_service returning the cached object, and a SQL registry whose version_id is stable across proto() calls and refreshes and changes after an apply. sdk/python/tests/unit/infra/registry passes locally (164 tests; three modules skip collection for missing optional dependencies).

…ebuild objects

The registry_proto_cache decorators keyed on id(registry_proto) as well as
version_id. Every registry refresh parses a new proto object, so each refresh
missed the cache and rebuilt every object from proto even when the registry had
not changed. For a registry with 14 feature services that rebuild costs about
35 ms, most of it typeguard checks in Field.__init__.

Key on version_id alone, falling back to the object identity only when a
registry does not set a version_id. Also cache get_feature_service per
version, which get_online_features calls on every request.

Refs feast-dev#7072

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Chandler King <chandler.king@findheadway.com>
@codecov-commenter

codecov-commenter commented Oct 26, 2026 •

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 88.88889% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 51.00%. Comparing base (1e5e90c) to head (a74e783).

Files with missing lines Patch % Lines
...ython/feast/infra/registry/proto_registry_utils.py 80.00% 1 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #7073      +/-   ##
==========================================
+ Coverage   50.97%   51.00%   +0.03%     
==========================================
  Files         455      455              
  Lines       56994    57001       +7     
  Branches     8321     8321              
==========================================
+ Hits        29055    29076      +21     
+ Misses      25954    25940      -14     
  Partials     1985     1985              
Flag Coverage Δ
go-feature-server 30.58% <ø> (+0.20%) ⬆️
python-unit 52.47% <88.88%> (+0.01%) ⬆️
Files with missing lines Coverage Δ
sdk/python/feast/infra/registry/snowflake.py 39.25% <100.00%> (+0.21%) ⬆️
sdk/python/feast/infra/registry/sql.py 61.43% <100.00%> (+0.38%) ⬆️
...ython/feast/infra/registry/proto_registry_utils.py 75.49% <80.00%> (+0.29%) ⬆️

... and 3 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1e5e90c...a74e783. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…sion_id

SqlRegistry.proto() and SnowflakeRegistry.proto() never set version_id, so the
version-keyed caches fell back to object identity and every cache refresh
still rebuilt every object from proto. Set version_id to the sha1 of the
deterministic serialization, which is stable across refreshes and changes on
any apply or delete. On a 421 KB registry proto the hash costs 0.2 ms.

Refs feast-dev#7072

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Chandler King <chandler.king@findheadway.com>
@chandlerok

Copy link
Copy Markdown
Contributor Author

@ntkathole this follows on from #6870 and #7072. Two small commits: version-keyed registry caches, and a version_id on the SQL and Snowflake registry protos so those registries get the same cache hits. Numbers and profile are in the description.

1 similar comment
@chandlerok

Copy link
Copy Markdown
Contributor Author

@ntkathole this follows on from #6870 and #7072. Two small commits: version-keyed registry caches, and a version_id on the SQL and Snowflake registry protos so those registries get the same cache hits. Numbers and profile are in the description.

This branch has not been deployed

No deployments
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