Skip to content

H-6664: Python monorepo infrastructure (uv workspace + turbo integration) — experimental spike#8994

Draft
claude[bot] wants to merge 2 commits into
mainfrom
claude/h-6664-python-monorepo-spike
Draft

H-6664: Python monorepo infrastructure (uv workspace + turbo integration) — experimental spike#8994
claude[bot] wants to merge 2 commits into
mainfrom
claude/h-6664-python-monorepo-spike

Conversation

@claude

@claude claude Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Requested by Tim Diekmann · Slack thread

Warning

Experimental spike for H-6664 "Create Python monorepo infrastructure" (internal), opened so the approach can be picked apart before the real implementation. Totally fine to close this and start over.

🌟 What is the purpose of this PR?

Demonstrate proper Python monorepo infrastructure, borrowing internal-infra's uv-workspace pattern and wiring it into turborepo.

Before: Python packages are invisible to turbo and CI. There is no shared lint/type-check/test configuration and no lockfile policy — e.g. #8989 adds a uv package with no package.json (so turbo never sees it), no CI, and a gitignored uv.lock.

After: turbo run lint:ruff lint:basedpyright test:unit --filter '@local/python-example' runs ruff, basedpyright, and pytest for Python packages via uv — with shared config and one committed uv.lock at the repo root — and the existing Lint/Test CI pipelines pick Python packages up like any other workspace package.

How it works

  • uv workspace: the new root pyproject.toml is a virtual workspace root ([tool.uv] package = false) listing Python packages as members, with requires-python = ">=3.14". A single uv.lock is committed at the repo root (do not gitignore it). Shared tooling lives in one root dev dependency group: ruff, basedpyright, pytest, pytest-asyncio. Per org Semgrep policy (uv-missing-dependency-cooldown), [tool.uv] exclude-newer = "7 days" applies a dependency cooldown — releases younger than a week are ignored during resolution (recorded in uv.lock as exclude-newer-span = "P7D"; adding it changed no resolved versions).
  • Centralized tool config in the root pyproject.toml:
    • ruff: select = ["ALL"] with internal-infra's short, documented ignore list (COM812, D203, D213, FIX002, TD003) plus per-file ignores for tests; line-length = 100 (matches the Rust width used here); target-version = "py314".
    • basedpyright: typeCheckingMode = "all".
    • pytest: --import-mode=importlib, asyncio_mode = "auto".
  • The package.json shim (the key part): each Python package carries a package.json whose scripts wrap uv, e.g. "test:unit": "uv run --frozen --all-packages pytest". Turbo then treats the package like any other workspace member — task graph, caching, --filter, remote cache all work. Two subtleties:
    • --all-packages is required: uv run from a member directory only syncs that member's dependencies, so without it the root dev group tools would be missing from the shared venv (verified with a fresh .venv).
    • basedpyright is pointed at the root config via --project ../../.. because pyright, unlike ruff and pytest, does not search parent directories for configuration.
  • Example package at libs/@local/python-example: hatchling build backend, src layout, py.typed, fully typed module, passing pytest suite (incl. an async test to prove the pytest-asyncio wiring).

CI (mostly the zero-new-workflow path)

  • test.yml: zero changes needed. It discovers packages via turbo query on TASK_NAME == "test:unit"; verified locally that @local/python-example shows up in exactly that query. Runners get uv 0.11.18 via mise (install-tools), and uv run --frozen syncs the venv on first use.
  • lint.yml: small addition. It enumerates tools per package (lint:eslint, lint:tsc, clippy, …) rather than running a generic lint task, so it genuinely can't pick Python up unaided. Added lint:ruff / lint:basedpyright detection + run steps mirroring the existing ESLint/TSC pattern.
  • prune-repository action: now keeps the root pyproject.toml + uv.lock (they aren't part of turbo prune's output), so uv run --frozen works in the pruned per-package checkout.
  • check-license-in-workspaces now ignores .venv/ (uv creates it at the repo root).
  • turbo.json already listed pyproject.toml and *.lock in globalDependencies, so Python task caching invalidates correctly with no changes.

🔗 Related links

🔍 What does this change?

  • New root pyproject.toml (uv workspace + shared ruff/basedpyright/pytest config) and committed root uv.lock
  • New example package libs/@local/python-example (pyproject.toml, package.json shim, LICENSE.md, typed module, tests)
  • turbo.json: new lint:ruff, lint:basedpyright, fix:ruff tasks
  • Root package.json: matching lint:ruff / lint:basedpyright / fix:ruff scripts, so yarn lint includes Python
  • .github/workflows/lint.yml: ruff/basedpyright detection + run steps
  • .github/actions/prune-repository/action.yml: keep pyproject.toml + uv.lock
  • libs/@local/repo-chores license check: ignore .venv/
  • yarn.lock: registers the new workspace

❓ Open questions for Bilal

  1. Python version floor — resolved: requires-python = ">=3.14" per Bilal, matching internal-infra (initially shipped as >=3.13). Note a workspace resolves on the intersection of all members, so FE-1162: Python optimisation script (Optuna) driving the Petrinaut CLI #8989's >=3.10 package could only join by raising its own floor.

  2. Placement/naming: libs/@local/python-example with dist name hash-python-example / module hash_python_example. Should Python packages live under a different convention (e.g. alongside @hashintel), and should the npm-scope name mirror the dist name?

  3. petrinaut-opt (FE-1162: Python optimisation script (Optuna) driving the Petrinaut CLI #8989): should it join the workspace (member entry + package.json shim + un-gitignore its lock into the root uv.lock) when cf-petrinaut-python lands?

  4. CI pruning — reproduced and documented; fix deliberately not shipped. With a temporary second workspace member (libs/@local/python-example-two, not committed) and the prune-repository action's steps run locally scoped to @local/python-example, the pruned tree lacks the sibling member and:

    • uv sync --all-packages --locked exits 1 — The lockfile at 'uv.lock' needs to be updated, but '--locked' was provided. (uv re-discovers the workspace from members and resolves 12 packages against a 13-package lock)
    • uv run --frozen --all-packages pytest exits 2 — error: Failed to determine installation plan / Caused by: Distribution not found at: file:///…/out/libs/@local/python-example-two

    i.e. the first additional Python package would break every pruned Python CI job. Per the Slack thread, the team is leaning toward removing turbo prune from CI entirely rather than patching prune.py, so no fix is included. Current prune usage, for that debate: the prune-repository action (custom prune.py wrapping turbo prune) is a CI-only checkout optimizationlint.yml (×1), test.yml (×2), bench.yml (×4), codspeed.yml (×1), deploy.yml (×1, sourcemaps job) — while the five docker image builds (hash-graph, hash-frontend, hash-api, hash-ai-worker-ts, hash-integration-worker) call turbo's native turbo prune --scope=… --docker directly in their Dockerfiles and never use prune.py, so dropping the CI action would not leave the docker builds' prune path unexercised — they never shared code with it. Separately: no uv download cache in CI yet; worth adding?

  5. Line length: picked 100 (Rust width); repo conventions are split (JS 80, SQL 120, ruff default 88).

🚫 Blocked by

Nothing — but this is a spike; the real implementation is Bilal's roadmap item.

Pre-Merge Checklist 🚀

🚢 Has this modified a publishable library?

This PR:

  • does not modify any publishable blocks or libraries, or modifications do not need publishing

📜 Does this require a change to the docs?

The changes in this PR:

  • are internal and do not require a docs change

🕸️ Does this require a change to the Turbo Graph?

The changes in this PR:

  • affected the execution graph, and the turbo.json's have been updated to reflect this

⚠️ Known issues

  • The multi-Python-package pruning issue reproduced in open question 4 — intentionally left unfixed pending the decision on removing turbo prune from CI.
  • uv run --frozen without --all-packages silently falls back to a ruff/pytest found on PATH if the tool isn't in the venv — the scripts always pass --all-packages to avoid this.

🛡 What tests cover this?

  • libs/@local/python-example/tests/test_greeting.py (3 tests, incl. async) — run by turbo run test:unit.

Verified locally (uv 0.11.18, turbo 2.6.3, yarn 4.16.0, CPython 3.14.6): uv lock, uv sync --all-packages --locked, uv run --frozen --all-packages ruff check ., … ruff format --check ., … basedpyright --project ../../.. . (strict mode confirmed to really analyze files via an intentional error), … pytest (3 passed), turbo run lint:ruff lint:basedpyright test:unit --filter '@local/python-example' (3/3 successful, and FULL TURBO cache hits on re-run), yarn constraints, yarn lint:license-in-workspaces, taplo/oxfmt/markdownlint on the changed files.

Not verified in this environment: the actual GitHub Actions runs (incl. mise-provisioned uv on runners) and the Rust sort-package-json check (mise run lint:package-json needs a cargo build) — watch the checks on this PR.

❓ How to test this?

  1. Checkout the branch, uv sync --all-packages
  2. turbo run lint:ruff lint:basedpyright test:unit --filter '@local/python-example'
  3. Confirm ruff, basedpyright, and pytest all execute via uv and pass (and hit the turbo cache on the second run)

…o integration)

- root pyproject.toml: uv workspace with shared ruff/basedpyright/pytest
  config and a single dev dependency group; committed root uv.lock
- libs/@local/python-example: minimal example package (hatchling, typed,
  tested) whose package.json scripts wrap uv so turbo runs lint:ruff,
  lint:basedpyright and test:unit like any other workspace package
- turbo.json: lint:ruff, lint:basedpyright and fix:ruff tasks
- lint.yml: detect and run ruff/basedpyright per package, mirroring the
  existing ESLint/TSC steps; test.yml picks up test:unit automatically
- prune-repository action: keep root pyproject.toml and uv.lock
- check-license-in-workspaces: ignore .venv
@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hash Ready Ready Preview, Comment Jul 9, 2026 5:04pm
hashdotdesign-tokens Ready Ready Preview, Comment Jul 9, 2026 5:04pm
petrinaut Ready Ready Preview, Comment Jul 9, 2026 5:04pm

@github-actions github-actions Bot added area/deps Relates to third-party dependencies (area) area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > backend Owned by the @backend team area/tests New or updated tests type/legal Owned by the @legal team labels Jul 9, 2026
Comment thread pyproject.toml
Comment on lines +16 to +18
[tool.uv]
package = false

@semgrep-code-hashintel semgrep-code-hashintel Bot Jul 9, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This pyproject.toml configures uv but does not set a dependency cooldown. Newly published packages can be malicious or unstable. Add exclude-newer = "7 days" under [tool.uv] to wait 7 days before resolving newly published package versions. Added in: 0.9.17 Reference: https://docs.astral.sh/uv/concepts/resolution/#dependency-cooldowns

🍰 Fixed in commit d55400d 🍰

Comment thread pyproject.toml Fixed
@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 59.67%. Comparing base (8010ac5) to head (d55400d).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8994      +/-   ##
==========================================
- Coverage   59.68%   59.67%   -0.01%     
==========================================
  Files        1371     1370       -1     
  Lines      134930   134915      -15     
  Branches     6067     6064       -3     
==========================================
- Hits        80532    80514      -18     
- Misses      53467    53471       +4     
+ Partials      931      930       -1     
Flag Coverage Δ
apps.hash-ai-worker-ts 1.39% <ø> (ø)
apps.hash-api 6.39% <ø> (ø)
blockprotocol.type-system 40.84% <ø> (ø)
local.claude-hooks 0.00% <ø> (ø)
local.harpc-client 51.49% <ø> (ø)
local.hash-backend-utils 1.90% <ø> (-0.91%) ⬇️
local.hash-graph-sdk 10.02% <ø> (ø)
local.hash-isomorphic-utils 0.18% <ø> (ø)
rust.antsi 0.00% <ø> (ø)
rust.error-stack 90.89% <ø> (ø)
rust.harpc-codec 84.70% <ø> (ø)
rust.harpc-net 96.19% <ø> (ø)
rust.harpc-tower 67.03% <ø> (ø)
rust.harpc-types 0.00% <ø> (ø)
rust.harpc-wire-protocol 92.23% <ø> (ø)
rust.hash-codec 72.76% <ø> (ø)
rust.hash-graph-api 7.41% <ø> (ø)
rust.hash-graph-authorization 62.59% <ø> (ø)
rust.hash-graph-embeddings 91.88% <ø> (ø)
rust.hash-graph-postgres-store 29.02% <ø> (ø)
rust.hash-graph-store 38.20% <ø> (ø)
rust.hash-graph-temporal-versioning 47.95% <ø> (ø)
rust.hash-graph-types 0.00% <ø> (ø)
rust.hash-graph-validation 83.43% <ø> (ø)
rust.hashql-ast 89.63% <ø> (ø)
rust.hashql-compiletest 28.39% <ø> (ø)
rust.hashql-core 78.95% <ø> (ø)
rust.hashql-diagnostics 72.51% <ø> (ø)
rust.hashql-eval 79.47% <ø> (ø)
rust.hashql-hir 89.09% <ø> (ø)
rust.hashql-mir 88.05% <ø> (ø)
rust.hashql-syntax-jexpr 94.04% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 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.

@codspeed-hq

codspeed-hq Bot commented Jul 9, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 15.38%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 2 regressed benchmarks
✅ 96 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
bit_matrix/dense/iter_row[64] 140.8 ns 170 ns -17.16%
bit_matrix/dense/iter_row[200] 185.8 ns 215 ns -13.57%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing claude/h-6664-python-monorepo-spike (d55400d) with main (6a22f5c)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (9be768a) during the generation of this report, so 6a22f5c was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

- requires-python >=3.14 across the workspace (matching internal-infra)
  and ruff target-version py314
- [tool.uv] exclude-newer = "7 days" per the uv-missing-dependency-cooldown
  Semgrep policy; re-locked (no resolved versions changed)
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Benchmark results

@rust/hash-graph-benches – Integrations

policy_resolution_large

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2002 $$27.3 \mathrm{ms} \pm 181 \mathrm{μs}\left({\color{gray}-3.393 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$3.48 \mathrm{ms} \pm 24.3 \mathrm{μs}\left({\color{gray}2.70 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 1002 $$12.1 \mathrm{ms} \pm 87.4 \mathrm{μs}\left({\color{lightgreen}-11.239 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 3314 $$42.1 \mathrm{ms} \pm 466 \mathrm{μs}\left({\color{lightgreen}-5.357 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$14.5 \mathrm{ms} \pm 140 \mathrm{μs}\left({\color{gray}-2.571 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 1527 $$23.3 \mathrm{ms} \pm 226 \mathrm{μs}\left({\color{lightgreen}-8.148 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 2078 $$27.9 \mathrm{ms} \pm 203 \mathrm{μs}\left({\color{lightgreen}-5.033 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.74 \mathrm{ms} \pm 22.4 \mathrm{μs}\left({\color{gray}-0.545 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 1033 $$13.2 \mathrm{ms} \pm 120 \mathrm{μs}\left({\color{lightgreen}-9.123 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_medium

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 102 $$3.69 \mathrm{ms} \pm 18.0 \mathrm{μs}\left({\color{lightgreen}-5.705 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.92 \mathrm{ms} \pm 17.3 \mathrm{μs}\left({\color{gray}-4.354 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 52 $$3.28 \mathrm{ms} \pm 18.9 \mathrm{μs}\left({\color{gray}-1.648 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 269 $$5.08 \mathrm{ms} \pm 29.1 \mathrm{μs}\left({\color{lightgreen}-5.197 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$3.43 \mathrm{ms} \pm 19.0 \mathrm{μs}\left({\color{gray}-4.539 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 108 $$4.03 \mathrm{ms} \pm 26.9 \mathrm{μs}\left({\color{gray}-4.271 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 133 $$4.34 \mathrm{ms} \pm 40.2 \mathrm{μs}\left({\color{gray}-3.525 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$3.38 \mathrm{ms} \pm 19.7 \mathrm{μs}\left({\color{lightgreen}-5.419 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 63 $$4.04 \mathrm{ms} \pm 34.5 \mathrm{μs}\left({\color{gray}-3.581 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_none

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 2 $$2.60 \mathrm{ms} \pm 16.3 \mathrm{μs}\left({\color{gray}-1.458 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.44 \mathrm{ms} \pm 12.2 \mathrm{μs}\left({\color{gray}-2.889 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 2 $$2.57 \mathrm{ms} \pm 13.2 \mathrm{μs}\left({\color{gray}-2.299 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 8 $$2.87 \mathrm{ms} \pm 19.0 \mathrm{μs}\left({\color{gray}-0.264 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.65 \mathrm{ms} \pm 14.3 \mathrm{μs}\left({\color{gray}0.923 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 3 $$2.85 \mathrm{ms} \pm 16.2 \mathrm{μs}\left({\color{gray}1.24 \mathrm{\%}}\right) $$ Flame Graph

policy_resolution_small

Function Value Mean Flame graphs
resolve_policies_for_actor user: empty, selectivity: high, policies: 52 $$2.98 \mathrm{ms} \pm 18.0 \mathrm{μs}\left({\color{gray}-4.704 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: low, policies: 1 $$2.69 \mathrm{ms} \pm 17.4 \mathrm{μs}\left({\color{gray}-3.139 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: empty, selectivity: medium, policies: 26 $$2.94 \mathrm{ms} \pm 18.8 \mathrm{μs}\left({\color{gray}-4.405 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: high, policies: 94 $$3.36 \mathrm{ms} \pm 20.9 \mathrm{μs}\left({\color{gray}-2.327 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: low, policies: 1 $$2.94 \mathrm{ms} \pm 17.2 \mathrm{μs}\left({\color{gray}-2.927 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: seeded, selectivity: medium, policies: 27 $$3.21 \mathrm{ms} \pm 16.0 \mathrm{μs}\left({\color{lightgreen}-5.265 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: high, policies: 66 $$3.29 \mathrm{ms} \pm 18.3 \mathrm{μs}\left({\color{gray}-2.397 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: low, policies: 1 $$2.89 \mathrm{ms} \pm 17.4 \mathrm{μs}\left({\color{gray}-2.485 \mathrm{\%}}\right) $$ Flame Graph
resolve_policies_for_actor user: system, selectivity: medium, policies: 29 $$3.24 \mathrm{ms} \pm 21.0 \mathrm{μs}\left({\color{gray}-2.278 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_complete

Function Value Mean Flame graphs
entity_by_id;one_depth 1 entities $$40.4 \mathrm{ms} \pm 206 \mathrm{μs}\left({\color{gray}-4.908 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 10 entities $$31.1 \mathrm{ms} \pm 161 \mathrm{μs}\left({\color{lightgreen}-6.653 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 25 entities $$34.1 \mathrm{ms} \pm 236 \mathrm{μs}\left({\color{lightgreen}-5.708 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 5 entities $$30.4 \mathrm{ms} \pm 244 \mathrm{μs}\left({\color{lightgreen}-28.257 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;one_depth 50 entities $$40.0 \mathrm{ms} \pm 232 \mathrm{μs}\left({\color{gray}-4.688 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 1 entities $$47.4 \mathrm{ms} \pm 230 \mathrm{μs}\left({\color{gray}-2.692 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 10 entities $$38.5 \mathrm{ms} \pm 197 \mathrm{μs}\left({\color{gray}-2.576 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 25 entities $$89.2 \mathrm{ms} \pm 656 \mathrm{μs}\left({\color{gray}-3.328 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 5 entities $$31.7 \mathrm{ms} \pm 193 \mathrm{μs}\left({\color{gray}-2.096 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;two_depth 50 entities $$253 \mathrm{ms} \pm 949 \mathrm{μs}\left({\color{gray}-2.612 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 1 entities $$10.1 \mathrm{ms} \pm 71.6 \mathrm{μs}\left({\color{gray}-2.199 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 10 entities $$10.2 \mathrm{ms} \pm 55.6 \mathrm{μs}\left({\color{gray}-0.713 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 25 entities $$10.1 \mathrm{ms} \pm 52.8 \mathrm{μs}\left({\color{gray}-2.293 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 5 entities $$10.0 \mathrm{ms} \pm 52.8 \mathrm{μs}\left({\color{gray}-1.121 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id;zero_depth 50 entities $$10.1 \mathrm{ms} \pm 50.3 \mathrm{μs}\left({\color{lightgreen}-5.700 \mathrm{\%}}\right) $$ Flame Graph

read_scaling_linkless

Function Value Mean Flame graphs
entity_by_id 1 entities $$10.3 \mathrm{ms} \pm 68.1 \mathrm{μs}\left({\color{gray}-3.113 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10 entities $$10.2 \mathrm{ms} \pm 62.7 \mathrm{μs}\left({\color{gray}-3.881 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 100 entities $$10.2 \mathrm{ms} \pm 57.3 \mathrm{μs}\left({\color{gray}-2.984 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 1000 entities $$10.3 \mathrm{ms} \pm 71.6 \mathrm{μs}\left({\color{gray}-2.885 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id 10000 entities $$10.5 \mathrm{ms} \pm 67.5 \mathrm{μs}\left({\color{gray}-3.669 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity

Function Value Mean Flame graphs
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/block/v/1 $$10.5 \mathrm{ms} \pm 59.2 \mathrm{μs}\left({\color{lightgreen}-5.751 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/book/v/1 $$10.7 \mathrm{ms} \pm 66.6 \mathrm{μs}\left({\color{gray}-2.175 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/building/v/1 $$10.5 \mathrm{ms} \pm 59.9 \mathrm{μs}\left({\color{lightgreen}-6.813 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/organization/v/1 $$10.7 \mathrm{ms} \pm 74.3 \mathrm{μs}\left({\color{gray}-3.991 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/page/v/2 $$10.7 \mathrm{ms} \pm 67.0 \mathrm{μs}\left({\color{gray}-4.567 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/person/v/1 $$10.6 \mathrm{ms} \pm 62.3 \mathrm{μs}\left({\color{gray}-4.162 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/playlist/v/1 $$10.6 \mathrm{ms} \pm 79.9 \mathrm{μs}\left({\color{lightgreen}-6.800 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/song/v/1 $$10.7 \mathrm{ms} \pm 67.9 \mathrm{μs}\left({\color{gray}-3.584 \mathrm{\%}}\right) $$ Flame Graph
entity_by_id entity type ID: https://blockprotocol.org/@alice/types/entity-type/uk-address/v/1 $$10.7 \mathrm{ms} \pm 82.5 \mathrm{μs}\left({\color{gray}-2.083 \mathrm{\%}}\right) $$ Flame Graph

representative_read_entity_type

Function Value Mean Flame graphs
get_entity_type_by_id Account ID: bf5a9ef5-dc3b-43cf-a291-6210c0321eba $$8.40 \mathrm{ms} \pm 46.8 \mathrm{μs}\left({\color{gray}-0.531 \mathrm{\%}}\right) $$ Flame Graph

representative_read_multiple_entities

Function Value Mean Flame graphs
entity_by_property traversal_paths=0 0 $$56.6 \mathrm{ms} \pm 421 \mathrm{μs}\left({\color{lightgreen}-9.860 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$107 \mathrm{ms} \pm 549 \mathrm{μs}\left({\color{lightgreen}-7.979 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$61.2 \mathrm{ms} \pm 451 \mathrm{μs}\left({\color{lightgreen}-9.983 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$69.8 \mathrm{ms} \pm 464 \mathrm{μs}\left({\color{lightgreen}-9.841 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$79.0 \mathrm{ms} \pm 448 \mathrm{μs}\left({\color{lightgreen}-8.340 \mathrm{\%}}\right) $$
entity_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$86.4 \mathrm{ms} \pm 582 \mathrm{μs}\left({\color{lightgreen}-7.683 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=0 0 $$43.0 \mathrm{ms} \pm 262 \mathrm{μs}\left({\color{lightgreen}-10.028 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=255 1,resolve_depths=inherit:1;values:255;properties:255;links:127;link_dests:126;type:true $$72.7 \mathrm{ms} \pm 409 \mathrm{μs}\left({\color{gray}-3.701 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:0;link_dests:0;type:false $$49.4 \mathrm{ms} \pm 307 \mathrm{μs}\left({\color{lightgreen}-7.802 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:0;links:1;link_dests:0;type:true $$58.9 \mathrm{ms} \pm 392 \mathrm{μs}\left({\color{lightgreen}-5.706 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:0;properties:2;links:1;link_dests:0;type:true $$61.0 \mathrm{ms} \pm 386 \mathrm{μs}\left({\color{lightgreen}-5.636 \mathrm{\%}}\right) $$
link_by_source_by_property traversal_paths=2 1,resolve_depths=inherit:0;values:2;properties:2;links:1;link_dests:0;type:true $$61.8 \mathrm{ms} \pm 415 \mathrm{μs}\left({\color{gray}-4.520 \mathrm{\%}}\right) $$

scenarios

Function Value Mean Flame graphs
full_test query-limited $$113 \mathrm{ms} \pm 629 \mathrm{μs}\left({\color{lightgreen}-12.381 \mathrm{\%}}\right) $$ Flame Graph
full_test query-unlimited $$126 \mathrm{ms} \pm 595 \mathrm{μs}\left({\color{lightgreen}-10.954 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-limited $$18.0 \mathrm{ms} \pm 121 \mathrm{μs}\left({\color{gray}-4.718 \mathrm{\%}}\right) $$ Flame Graph
linked_queries query-unlimited $$548 \mathrm{ms} \pm 1.42 \mathrm{ms}\left({\color{gray}3.85 \mathrm{\%}}\right) $$ Flame Graph

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

Labels

area/deps Relates to third-party dependencies (area) area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) area/tests New or updated tests type/eng > backend Owned by the @backend team type/legal Owned by the @legal team

Development

Successfully merging this pull request may close these issues.

3 participants