Skip to content

runtime: consider CNTVCT_EL0 to implement cputicks on ARM64 #67937

Open
@rhysh

Description

@rhysh

To get the current time in seconds, the runtime implements runtime.nanotime as a call to the OS (the vdso on GOOS=linux, libc on GOOS=darwin).

Profiling and tracing benefit from efficient access to a clock, but don't require a particular scale or offset. (We're in the habit of rescaling it after the fact, by comparing against another clock.) On GOARCH=amd64, the runtime implements runtime.cputicks as RDTSCP (or RDTSC plus memory fences). It's a bit faster to only read the timer, than to read the timer and then do scaling math.

But on GOARCH=arm64, for GOOS=linux, darwin, and several others, we implement runtime.cputicks as a call to runtime.nanotime. It looks like AArch64's CNTVCT_EL0 register [1] might have what we need for cputicks (monotonic, also monotonic across cores, static frequency). The Linux vdso [2] appears to use it (plus ISB), or the self-synchronizing version CNTVCTSS_EL0.

There's also CNTVCT for GOARCH=arm [3].

Initial benchmarking on an Apple M1 (darwin) and on Raspberry Pi models 5 and 3B (linux) show that reading CNTVCT_EL0 is bit faster than calling nanotime (14 vs 24ns, 28 vs 43ns, and 45 vs 126ns on those three platforms). I don't know how much of a difference this will make in complete applications, but cheaper clocks means less worry when adding profiling/tracing points.

CC @golang/runtime @golang/arm

[1] https://developer.arm.com/documentation/ddi0595/2021-03/AArch64-Registers/CNTVCT-EL0--Counter-timer-Virtual-Count-register

[2] https://elixir.bootlin.com/linux/v6.9/source/arch/arm64/include/asm/vdso/gettimeofday.h#L69

[3] https://developer.arm.com/documentation/ddi0601/2024-03/AArch32-Registers/CNTVCT--Counter-timer-Virtual-Count-register

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Performancearch-arm64compiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    Status

    Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions