Skip to content

Add fast nanosecond-resolution per-thread CPU timer#9811

Open
mszabo-wikia wants to merge 1 commit into
facebook:masterfrom
mszabo-wikia:add-fb-perf-gettime
Open

Add fast nanosecond-resolution per-thread CPU timer#9811
mszabo-wikia wants to merge 1 commit into
facebook:masterfrom
mszabo-wikia:add-fb-perf-gettime

Conversation

@mszabo-wikia

Copy link
Copy Markdown
Contributor

The HHVM JIT is heavily instrumented via scoped WorkloadStats structs that call Timer::GetThreadCPUTimeNanos to obtain the CPU timer of the current thread. This then calls fb_perf_get_thread_cputime_ns in internal Meta builds but falls back to folly::chrono::clock_gettime_ns in our OSS build which just wraps clock_gettime.

It seems there was an abortive attempt in 2013 to upstream a kernel patch for a fast VDSO implementation of clock_gettime_ns, after which fb_perf_get_thread_cputime_ns was added to provide a similarly performant nanosecond-resolution timer for the current thread's CPU time using the perf_events API.[2] This never made its way into OSS.

We observed the Folly shim to be responsible for 30-40% of CPU usage during JIT compilation while executing warmup code. After rolling out a change disabling it, we saw a double-digit P99 reduction across background jobs latencies and a ~30% increase in deployment speed. So, try to implement (with some AI assistance) an API-compatible fb_perf_get_thread_cputime_ns implementation backed by perf_events that can be used by HHVM OSS.

On my machine, this is 67x faster than the folly shim:

vagrant@hhvm-jammy-vm:~/hhvm$ _build/hphp/util/test/hphp_util_bench --bm_mode=adaptive
E20260618 19:12:04.745777 15497 BenchmarkAdaptive.cpp:549] Did not converge:
  folly_clock_gettime_ns: p33.30=132.3ns to 0.13%, 1025 samples, 1s
    [unstable] 1st=132.76 [132.54, 133.15] 2nd=132.07 [131.97, 132.12]
============================================================================
[...]p/util/test/perf-cputime-ns-bench.cpp     relative  time/iter   iters/s
============================================================================
folly_clock_gettime_ns                                    132.26ns     7.56M
perf_get_thread_cputime_ns                      6760.1%     1.96ns   511.12M

[1] https://lore.kernel.org/all/5226FAE1.5070201@fb.com/
[2] 28e6bf1

The HHVM JIT is heavily instrumented via scoped `WorkloadStats` structs
that call `Timer::GetThreadCPUTimeNanos` to obtain the CPU timer of
the current thread. This then calls `fb_perf_get_thread_cputime_ns`
in internal Meta builds but falls back to `folly::chrono::clock_gettime_ns`
in our OSS build which just wraps `clock_gettime`.

It seems there was an abortive attempt in 2013 to upstream a kernel patch
for a fast VDSO implementation of `clock_gettime_ns`, after which
`fb_perf_get_thread_cputime_ns` was added to provide a similarly performant
nanosecond-resolution timer for the current thread's CPU time using the `perf_events` API.[2]
This never made its way into OSS.

We observed the Folly shim to be responsible for 30-40% of CPU usage during
JIT compilation while executing warmup code. After rolling out a change
disabling it, we saw a double-digit P99 reduction across background jobs
latencies and a ~30% increase in deployment speed.
So, try to implement (with some AI assistance) an API-compatible `fb_perf_get_thread_cputime_ns`
implementation backed by `perf_events` that can be used by HHVM OSS.

On my machine, this is 67x faster than the folly shim:
```
vagrant@hhvm-jammy-vm:~/hhvm$ _build/hphp/util/test/hphp_util_bench --bm_mode=adaptive
E20260618 19:12:04.745777 15497 BenchmarkAdaptive.cpp:549] Did not converge:
  folly_clock_gettime_ns: p33.30=132.3ns to 0.13%, 1025 samples, 1s
    [unstable] 1st=132.76 [132.54, 133.15] 2nd=132.07 [131.97, 132.12]
============================================================================
[...]p/util/test/perf-cputime-ns-bench.cpp     relative  time/iter   iters/s
============================================================================
folly_clock_gettime_ns                                    132.26ns     7.56M
perf_get_thread_cputime_ns                      6760.1%     1.96ns   511.12M
```

[1] https://lore.kernel.org/all/5226FAE1.5070201@fb.com/
[2] facebook@28e6bf1
@meta-cla meta-cla Bot added the CLA Signed label Jul 10, 2026
@meta-codesync

meta-codesync Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

This pull request has been imported. If you are a Meta employee, you can view this in D111476887. (Because this pull request was imported automatically, there will not be any future comments.)

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant