Skip to content

time.perf_counter(): compute Greatest Common Denonimator (GCD) to reduce risk of integer overflow #112567

Closed
@vstinner

Description

@vstinner

The time.perf_counter() function is implemented by calling QueryPerformanceCounter() and QueryPerformanceFrequency(). It computes QueryPerformanceCounter() * SEC_TO_SEC / QueryPerformanceFrequency() using int64_t integers. The problem is that SEC_TO_SEC is big: 10^9.

QueryPerformanceFrequency() usually returns 10 MHz on Windows 10 and newer. The fraction SEC_TO_NS / frequency = 1_000_000_000 / 10_000_000 can be simplified to 100 / 1.

I propose using a fraction internally to convert QueryPerformanceCounter() value to a number of seconds, and simplify the fraction using the Greatest Common Denominator (GCD).

There are multiple functions using a fraction:

  • _PyTime_GetClockWithInfo() for clock() -- time.process_time() in Python
  • _PyTime_GetProcessTimeWithInfo() for times() -- time.process_time() in Python
  • py_get_monotonic_clock() for mach_absolute_time() on macOS -- time.monotonic() in Python
  • py_get_win_perf_counter() for QueryPerformanceCounter() on Windows -- time.perf_counter() in Python

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions