Skip to content

runtime: use vDSO to accelerate time.Now on linux/386 #22190

@somersf

Description

@somersf

Last updated: 2017-10-09

Abstract

Use the Linux vDSO __vdso_clock_gettime function (if available) to accelerate calls to time.Now() on linux/386.

Background

The Linux kernel can provide a "fast path" for some heavily used system calls which can be satisfied in user space more efficiently. The vDSO is an ELF-formatted virtual dynamic shared library injected into a process address space by the kernel, usually provided through an auxv entry at process startup. Several clock and time-related functions are included in this set of functions. When the vDSO is not present, normal syscalls must be used.

This mechanism is already in use on linux/amd64 to accelerate time.Now().

Proposal

The proposal is to use the same approach as used on linux/amd64 to locate the relevant vDSO function, and use it if available, to accelerate time.Now() on linux/386.

The proposal is to only accelerate the clock functions required to implement time.Now().
No other calls will be affected.

Rationale

There is a significant performance difference between a syscall to obtain a clock, and a corresponding vDSO-based call.

A prototype implementation found that the vDSO path is 5x to 10x faster than the syscall equivalent, depending on processor, virtualization etc.

For certain applications that make heavy use of timestamping (for example, metrics and telemetry), improving the performance of timestamping can make a significant performance improvement overall.

As of go 1.9, time.Now() on linux/386 requires two syscalls, which has doubled the call cost over previous versions. Adding vDSO support would more than pay for this.

Compatibility

If the vDSO-accelerated function is not found at runtime, then the existing syscall implementation will automatically be used as fallback.

The change will be limited to the time functions provided internally in runtime, and used by time.Now(), so that other calls will not be affected.

Implementation

Adapt the code currently in src/runtime/vdso_linux_amd64.go so that it can also be used for ELF32 on linux/386. The initial implementation will be based on a code copy-and-edit so that only linux/386 is affected by the change.

Adapt the runtime.walltime() and runtime.nanotime() functions (in src/runtime/sys_linux_386.s) to check for and use __vdso_clock_gettime if it was found during startup, or fallback to the existing syscall if not.

Refactor The vDSO ELF symbol lookup code to eliminate duplication between linux/386 and linux/amd64. The ELF structure definitions, and required symbols differ between 32-bit and 64-bit, but the lookup code is the same.

Open issues

Number of changesets

I propose implementing this with two changesets:

  • support linux/386 by duplicating code from linux/amd64, so that 386 support can be reviewed/added without disturbing code for other platforms.
  • refactor code affecting both linux/amd64 and linux/386 to eliminate code duplication.

Is this OK, or should a single changeset be used?

Tests

There don't appear to be any explicit tests for linux/amd64 to verify that the fallback path can be called. I'll include a basic test for this covering linux/386 and linux/amd64, though I am unsure if it is necessary, or alternatively - if the test should be enhanced further.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions