Skip to content

Python version of phase_stats.py calculation - #1787

Merged
ArneTR merged 15 commits into
mainfrom
phase-stats-speedup
Jul 31, 2026
Merged

Python version of phase_stats.py calculation#1787
ArneTR merged 15 commits into
mainfrom
phase-stats-speedup

Conversation

@ArneTR

@ArneTR ArneTR commented Jul 22, 2026

Copy link
Copy Markdown
Member

This PR speeds up the processing for the phase stats by moving calculation out of the DB hotpath.

Analysis

We first assumed the bottle neck was the SQL queries, which became quite complex, or the big database with the big index (In our live DB of ~ 100 GB of raw measurement values)

However the slow down was the network connects. We make a separate SQL query per metric and phase. This can sum up to 6 x 30 calls easily. With setup and teardown each network call takes about 1 second.

Now we only do one big query to fetch all the values resulting in a 100x speedup

Summary

  • Replaced repeated per-phase, per-metric SQL aggregation with one time-ordered run query and in-memory Python calculations.
  • Added PostgreSQL-compatible percentile interpolation, boundary samples, weighted averages, derivatives, and sampling-rate metrics.
  • Updated carbon-intensity provider detection and handling by naming convention and unit.
  • Added SCI metric derivation for phase-stat rebuild and replay tools.
  • Renamed the carbon-intensity-level Electricity Maps provider and configuration key.
  • Added MAX_POSTGRES_BIGINT for PostgreSQL-compatible integer handling.
  • Reduced database connection overhead and improved processing speed.

@ArneTR

ArneTR commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Phase statistics now fetch all run measurements once and compute per-phase results in memory. The pipeline handles percentile interpolation, phase boundaries, derivatives, sampling rates, energy, power, carbon, custom metrics, and SCI state. Carbon-intensity provider detection and configuration names use the updated metric naming convention. Phase-stat rebuilding derives SCI custom metric names from each run’s usage_scenario.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the primary change: replacing the phase_stats.py calculation with a Python implementation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
tools/phase_stats.py (1)

28-28: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: trailing space in status message / prefer logging.

print('Fetched data for ', args.run_id) emits "Fetched data for <id>" (double space from the comma separator). Minor cosmetic nit; consider an f-string or the project's logger for consistency.

♻️ Optional tweak
-    print('Fetched data for ', args.run_id)
+    print(f'Fetched data for {args.run_id}')

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: faa34ad5-df0f-4d1c-848d-42f244669fae

📥 Commits

Reviewing files that changed from the base of the PR and between b728830 and cd966e7.

📒 Files selected for processing (2)
  • lib/phase_stats.py
  • tools/phase_stats.py

Comment thread lib/phase_stats.py Outdated
Comment thread lib/phase_stats.py Outdated
@ArneTR

ArneTR commented Jul 22, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ArneTR
ArneTR requested a review from ribalba July 23, 2026 12:07
@ArneTR

ArneTR commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@ribalba PR now ready for review. Since it is in the crucial calculation part please give it an extra pair of eyes

@ArneTR

ArneTR commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Eco CI Output - Old Energy Estimation

Eco CI Output [RUN-ID: 30005732884]:

Label🖥 avg. CPU utilization [%]🔋 Total Energy [Wh]🔌 avg. Power [Watts]Duration [Seconds]
Measurement #130.14811.86804.231590.40
Total Run30.151.86804.231590.40
Additional overhead from Eco CIN/A0.00494.324.10

🌳 CO2 Data:
City: CONSTANT, Lat: , Lon:
IP:
CO₂ from energy is: 0.431519550 g
CO₂ from manufacturing (embodied carbon) is: 0.453763080 g
Carbon Intensity for this location: 231 gCO₂eq/kWh
SCI: 0.885283 gCO₂eq / pipeline run emitted


Total cost of whole PR so far:

[skip ci]

* main:
  (fix): Custom metrics now allows valid floats and even negative numbers also
  (ci): Added Eco-CI measurement after setup
  (test-fix): Downgrading python version as 3.15 did not exist yet
  Upgraded Python version in CI/CD
  (feat): Making GitHub Action two step to debug setup vs. run better
  Bump actions/setup-python from 6 to 7 in /.github/actions/gmt-pytest (#1786)
  Bump fastapi from 0.139.0 to 0.139.2 (#1780)
  (feat): All config files are now in a config folder instead of clobbering the root dir and docker dir (#1793)
  Updated Cloud Energy
  Bump pandas from 3.0.3 to 3.0.5 (#1790)
  Bump aiohttp from 3.14.2 to 3.14.3 (#1792)
  Bump cachetools from 7.1.4 to 7.1.5 (#1791)
  (fix): 0 Values in CPU Utilization Provider for linux do not lead to Floating Point Exception anymore

@ribalba ribalba left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks ok. Few minor things

Comment thread lib/phase_stats.py Outdated
Comment thread lib/phase_stats.py Outdated
Comment thread lib/phase_stats.py
ArneTR added 6 commits July 31, 2026 12:23
* main:
  Test speedup (#1782)
  Bump fastapi from 0.140.13 to 0.141.1 (#1805)
  Bump uvicorn from 0.51.0 to 0.52.0 (#1804)
  CLAUDE.md shall be auto updated by Agent
  Carbondb backfill and copy over rework (#1802)
  (hotfix): Email jobs are now handled separately and not as bulk
  (rework): Making some more columns NOT NULL where we enforce values to make indexes cleaner and simplify mental overhead for data strucutres
  CLAUDE.md added as symlink of AGENTS.md to make CLAUDE Code also read it by default
  (test-fix): Race condition with outdated commit-hash variable
  Bump fastapi from 0.139.2 to 0.140.13 (#1799)
  Bump tqdm from 4.69.0 to 4.70.0 (#1798)
  Bump cachetools from 7.1.5 to 7.1.6 (#1794)
  Time to filter should wait for backfill_geo to insert location data, which runs typically on a 10 minute interval
  Reapply "(Update): Playwright v1.62.0" - Release has been pulled and is not available anymore
  Revert "(Update): Playwright v1.62.0" - Release has been pulled and is not available anymore
  (Update): Playwright v1.62.0
  (fix): Pandas Dataframe must guard against non int data since customers can supply arbitrary regexes
  Revert "(fix): Custom metrics now allows valid floats and even negative numbers also"
@ArneTR

ArneTR commented Jul 31, 2026

Copy link
Copy Markdown
Member Author

Merged in main to use now speedier tests. Then will merge in

@ArneTR

ArneTR commented Jul 31, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/phase_stats.py (1)

293-302: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Unresolved: KeyError when a metric has zero recorded values.

metrics comes from measurement_metrics (all metrics registered for the run), but metric_time_series is only populated from measurement_values rows. A metric with zero recorded values is absent from metric_time_series, so metric_time_series[measurement_metric_id][0] at line 294 raises KeyError and aborts the entire run's phase-stat build. The added comment ("can fail if metric does not exist. This should never be. Thus we simply crash") restates the same assumption a prior review already showed can be false — a provider can register a metric row and still record zero values (fast phase, provider failure after registration, etc.). The previous per-(phase, metric) SQL simply returned no rows in that case; this is a regression from crash-safe to crash-prone.

🛡️ Proposed fix
-            times = metric_time_series[measurement_metric_id][0] # can fail if metric does not exist. This should never be. Thus we simply crash
-            values = metric_time_series[measurement_metric_id][1] # can fail if metric does not exist. This should never be. Thus we simply crash
+            times, values = metric_time_series.get(measurement_metric_id, ([], []))

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fa0d998c-d4dd-42c5-830e-4f0ba9fbcfb7

📥 Commits

Reviewing files that changed from the base of the PR and between 2f37f9f and 6233aaf.

📒 Files selected for processing (6)
  • config.yml.example
  • frontend/js/helpers/config.js.example
  • lib/phase_stats.py
  • metric_providers/carbon/intensitylevel/electricitymaps/machine/provider.py
  • tools/phase_stats.py
  • tools/rebuild_phase_stats.py

Comment thread lib/phase_stats.py
Comment thread tools/phase_stats.py
@github-actions

Copy link
Copy Markdown

Eco CI Output [RUN-ID: 30625199342]:

Label🖥 avg. CPU utilization [%]🔋 Total Energy [Wh]🔌 avg. Power [Watts]Duration [Seconds]
Setup2.997760.16422.32254.88
Run26.09580.36594.16316.30
Total Run15.790.53003.34571.18
Additional overhead from Eco CIN/A0.00183.621.79

🌳 CO2 Data:
City: CONSTANT, Lat: , Lon:
IP:
CO₂ from energy is: 0.122436468 g
CO₂ from manufacturing (embodied carbon) is: 0.162965541 g
Carbon Intensity for this location: 231 gCO₂eq/kWh
SCI: 0.285402 gCO₂eq / pipeline run emitted


Total cost of whole PR so far:

@ArneTR
ArneTR merged commit 4987fcc into main Jul 31, 2026
2 checks passed
@ArneTR
ArneTR deleted the phase-stats-speedup branch July 31, 2026 11:06
ArneTR added a commit that referenced this pull request Aug 1, 2026
* main:
  (tests): Moving Daily GitHub Actions Job also to Blacksmith
  (feat): Better stdout passing through in cluster errors
  Python version of phase_stats.py calculation (#1787)
  Test speedup (#1782)
  Bump fastapi from 0.140.13 to 0.141.1 (#1805)
  Bump uvicorn from 0.51.0 to 0.52.0 (#1804)
  CLAUDE.md shall be auto updated by Agent
  Carbondb backfill and copy over rework (#1802)
  (hotfix): Email jobs are now handled separately and not as bulk
  (rework): Making some more columns NOT NULL where we enforce values to make indexes cleaner and simplify mental overhead for data strucutres
  CLAUDE.md added as symlink of AGENTS.md to make CLAUDE Code also read it by default
  (test-fix): Race condition with outdated commit-hash variable
  Bump fastapi from 0.139.2 to 0.140.13 (#1799)
  Bump tqdm from 4.69.0 to 4.70.0 (#1798)
ArneTR added a commit that referenced this pull request Aug 5, 2026
* main: (711 commits)
  (fix): Chmod should not execute
  Bump cachetools from 7.1.6 to 7.1.7 (#1811)
  (rework): Jobs.py does not take CLI arguments anymore (#1812)
  Bump uvicorn from 0.52.0 to 0.52.1 (#1810)
  Fix repo URL generation to handle GitLab, Bitbucket, SSH, and local repos in the UI (#1783)
  (hotfix): Removing Docker Gunicorn Cache to work with Blacksmith. Fix maybe not final depending on performance
  Bump redis from 8.0.1 to 8.1.0 (#1807)
  Bump pytest-xdist from 3.6.1 to 3.8.0 (#1808)
  (rework): Removing non functional id primary key on measurement_values and introducing actual used compund primary key that enables easier sort
  (test-fix): Using new Electriciy Maps Token after their Sandbox deprecation
  (tests): Moving Daily GitHub Actions Job also to Blacksmith
  (feat): Better stdout passing through in cluster errors
  Python version of phase_stats.py calculation (#1787)
  Test speedup (#1782)
  Bump fastapi from 0.140.13 to 0.141.1 (#1805)
  Bump uvicorn from 0.51.0 to 0.52.0 (#1804)
  CLAUDE.md shall be auto updated by Agent
  Carbondb backfill and copy over rework (#1802)
  (hotfix): Email jobs are now handled separately and not as bulk
  (rework): Making some more columns NOT NULL where we enforce values to make indexes cleaner and simplify mental overhead for data strucutres
  ...
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