mlco2 / mlco2/codecarbon

Empty powermetrics output yields NaN power, poisoning all downstream totals on Apple Silicon

Open Beginner friendly
#1,306 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.9k
Forks
323
Avg merge
1d 12h
Merged PRs (30d)
12

Description

When powermetrics produces no matching output, ApplePowermetrics.get_details() returns nan for CPU/GPU power. NaN is absorbing under addition, so a single such sample turns _total_energy, emissions and emissions_rate into nan for the remainder of the run. The CSV row and the API payload then contain NaN, which also makes the JSON invalid under the strict spec.

Reproduction

from codecarbon.core.powermetrics import ApplePowermetrics

pm = ApplePowermetrics(output_dir=tmpdir, log_file_name="empty.txt")
open(pm._log_file_path, "w").close()   # sudoers rule missing, or sampler emitted nothing
d = pm.get_details()
assert math.isnan(d["CPU Power"])      # passes today

Root cause

codecarbon/core/powermetrics.py:181 and :193 call np.mean([...]) on the result of re.findall. np.mean([]) returns nan and only emits a RuntimeWarning; it does not raise, so the except Exception at codecarbon/core/powermetrics.py:201 never fires and nothing is logged.

The value flows straight through AppleSiliconChip._get_power (codecarbon/external/hardware.py:504-515) into Power.from_watts, then through BaseHardware.measure_power_and_energy into the tracker accumulators.

The GPU branch is the likelier trigger: _log_values runs powermetrics with --samplers cpu_power only (codecarbon/core/powermetrics.py:145-153), and whether that sampler emits GPU Power: lines depends on the machine and macOS version. Where it does not, gpu_power_list is empty on every call.

Expected vs actual

Expected: no samples means 0 W with a visible warning, and the run still reports finite emissions.
Actual: no samples means nan, silently, and every total for the rest of the run is nan.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in codecarbon/core/powermetrics.py at ApplePowermetrics.get_details(), especially the parsing around lines 181 and 193, and trace the values into AppleSiliconChip._get_power in codecarbon/external/hardware.py. Reproduce the empty-log case, then verify that missing CPU or GPU samples produce finite zero power, a visible warning, and finite downstream emissions and JSON payloads.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, numpy, python
Domain
operating-systems
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.