Bug 213029

Summary: [5.12 Regression] clock_gettime() a lot slower with Hyper-V clocksource driver
Product: Drivers Reporter: Mohammed Gamal (mgamal)
Component: Platform_x86Assignee: drivers_platform_x86 (drivers_platform_x86)
Status: NEW ---    
Severity: normal CC: mgamal, mhkelley
Priority: P1    
Hardware: x86-64   
OS: Linux   
Kernel Version: 5.12 Subsystem:
Regression: No Bisected commit-id:

Description Mohammed Gamal 2021-05-11 13:08:22 UTC
Since kernel 5.12 the performance of clock_gettime() is a lot slower. There seems to be a regression concerning VDSO in the Hyper-V clocksource driver.

The following code snippet runs a lot slower:
===============================
# gcc gettime.c -o gettime
# cat gettime.c 

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char *argv[]) {
    struct timespec start;
    unsigned long i;

    for (i=0; i<100000000UL; i++) {
        if( clock_gettime(CLOCK_REALTIME, &start) == -1 ) {
            perror( "clock gettime" );
            exit( EXIT_FAILURE );
        }
    }

    return 0;
}
===============================

# cat /sys/devices/system/clocksource/clocksource0/current_clocksource
hyperv_clocksource_tsc_page

1) With kernel >= 5.12
# time ./gettime 
real	0m48.201s
user	0m14.788s
sys	0m31.531s


2) With kernel < 5.12
# time ./gettime
real	0m3.308s
user	0m3.214s
sys	0m0.003s


I bisected the kernel and the commit that introduces the regression seems to be this:

commit e4ab4658f1cff14c82202132f7af2cb5c2741469
Author: Michael Kelley <mikelley@microsoft.com>
Date:   Tue Mar 2 13:38:19 2021 -0800

    clocksource/drivers/hyper-v: Handle vDSO differences inline
    
    While the driver for the Hyper-V Reference TSC and STIMERs is architecture
    neutral, vDSO is implemented for x86/x64, but not for ARM64.  Current code
    calls into utility functions under arch/x86 (and coming, under arch/arm64)
    to handle the difference.
    
    Change this approach to handle the difference inline based on whether
    VDSO_CLOCK_MODE_HVCLOCK is present.  The new approach removes code under
    arch/* since the difference is tied more to the specifics of the Linux
    implementation than to the architecture.
    
    No functional change.
    
    Signed-off-by: Michael Kelley <mikelley@microsoft.com>
    Reviewed-by: Boqun Feng <boqun.feng@gmail.com>
    Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
    Link: https://lore.kernel.org/r/1614721102-2241-8-git-send-email-mikelley@microsoft.com
    Signed-off-by: Wei Liu <wei.liu@kernel.org>

It does indeed not introduce any functional changes, but degradation in performance is quite noticeable.
Comment 1 Michael Kelley 2021-05-12 15:02:44 UTC
And I was trying to be so clever. :-(  I see that Vitaly Kuznetsov has posted a patch to fix this.

One thing: The commit that causes the problem was first available in 5.13-RC1.  But your problem statement above says that you see the problem with 5.12. Can you confirm? The 5.12 release doesn't have the problematic commit.