Skip to content

Add CpuTime metric for per-thread CPU time measurement - #72

Merged
bazhenov merged 2 commits into
bazhenov:mainfrom
TickTockBent:cpu-time-metric
Mar 5, 2026
Merged

Add CpuTime metric for per-thread CPU time measurement#72
bazhenov merged 2 commits into
bazhenov:mainfrom
TickTockBent:cpu-time-metric

Conversation

@TickTockBent

Copy link
Copy Markdown
Contributor

Summary

  • Adds CpuTime metric implementing the Metric trait, measuring only active CPU time for the current thread (excludes sleep, I/O, lock waits)
  • Unix: clock_gettime(CLOCK_THREAD_CPUTIME_ID) — nanosecond precision per-thread CPU clock
  • Windows: GetThreadTimes(GetCurrentThread()) — user + kernel time for current thread
  • No new dependencies — libc and windows crate features already present

This follows from the discussion in #57 where @bazhenov suggested implementing CpuTime as a separate metric after the pluggable Metric trait landed in #60:

"Now we can implement CpuTime as a separate metric to measure. I believe we have no obstacles to implementing your idea in tango code base."

Test plan

  • Unit test: check_cpu_time_metric — verifies non-zero CPU time for busy work
  • Integration test: cpu_time_excludes_sleep — verifies CPU time during thread::sleep is near-zero compared to a busy loop (separate binary, like rusage.rs)
  • cargo test -p tango-bench — all 16 tests pass
  • cargo clippy -p tango-bench — no new warnings

// ticktockbent

Implements CpuTime as a new Metric alongside WallClock. Unlike WallClock,
CpuTime excludes time spent sleeping, blocking on I/O, or waiting for
locks — it measures only active CPU consumption of the current thread.

Unix: clock_gettime(CLOCK_THREAD_CPUTIME_ID)
Windows: GetThreadTimes(GetCurrentThread())

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bazhenov

Copy link
Copy Markdown
Owner

Thanks a lot. Will look into this shortly.

@bazhenov bazhenov left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for your time and effort. I really like the implementation, it's a simple and easy to follow.

Comment thread tango-bench/tests/cpu_time.rs Outdated
Comment thread tango-bench/tests/cpu_time.rs Outdated
Comment thread tango-bench/src/lib.rs Outdated
Comment thread tango-bench/src/lib.rs Outdated
@bazhenov bazhenov self-assigned this Mar 2, 2026
  2. Windows overhead minimized — GetCurrentThread() called once, GetThreadTimes() is the only thing in the hot path, FILETIME math deferred to after the measurement
  3. Integration test deleted, replaced with two unit tests in lib.rs:
    - cpu_time_excludes_sleep — 50ms sleep should use < 1ms CPU time
    - cpu_time_tracks_wall_clock_during_busy_work — busy loop for 10ms wall-clock, assert CPU time within 1%
  4. Stricter assertion — uses bazhenov's suggested approach (wall-clock bounded loop + 1% tolerance)

  13 tests pass, clippy clean (only pre-existing too_many_arguments warning).
@TickTockBent

Copy link
Copy Markdown
Contributor Author

Thanks for the review! All 4 items addressed:

  1. Removed black_box from check_cpu_time_metric — the harness already black-boxes the return value, so just returning sum now.

  2. Minimized Windows measurement overheadGetCurrentThread() called once before the measurement. Only GetThreadTimes() remains in the hot path. FILETIME→nanos conversion deferred until after both samples are taken.

  3. Split and relocated tests — deleted tests/cpu_time.rs, replaced with two unit tests in lib.rs:

    • cpu_time_excludes_sleep — 50ms sleep, assert < 1ms CPU time
    • cpu_time_tracks_wall_clock_during_busy_work — busy loop for 10ms wall-clock, assert CPU time within 1%
  4. Stricter assertion — wall-clock bounded loop with 1% tolerance, as you suggested.

// ticktockbent

@bazhenov bazhenov left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Awesome, thanks a bunch for your contribution!

@bazhenov
bazhenov merged commit 9af1d0e into bazhenov:main Mar 5, 2026
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