From: Zhao Yakui <[email protected]>
On some machines the HPET clock source is selected because TSC stops in course
of entering the deep C-state. And it will take about 1800 cycles to read the
HPET counter(about 1us latency). Sometimes the function of read_hpet will be
called more than 20000 every second when playing media workload. And one
important contributor is to call the CLOCK_MONOTONIC posix timer in Xorg.
Now Linux kernel supports the CLOCK_NONOTONIC_COARSE posix timer, which
will return the time at the last tick. Compared with CLOCK_REALTIME/MONOTONIC,
it is much faster as it can avoid the access to the hardware. In such case
the application can make the trade-off between proper speed/granularity.
http://marc.info/?l=linux-kernel&m=125073483507611&w=2
In fact the time returned by CLOCK_MONOTONIC posix timer is transferred
to millseconds. If the system tick is greater than or equal to 1000Hz, we
still can can keep the granualrity when using CLOCK_MONOTONIC_COARSE timer while
it can remove the overhead of read_hpet in Xorg.
In our test about 12% overhead of read_hpet can be reduced when playing
the media workload, which helps to reduce the cpu C0 usage from 43% to 42%.
Signed-off-by: Zhao Yakui <[email protected]>
Tested-by: Samuel Xu <[email protected]>
CC: Adam Jackson <[email protected]>
---
os/utils.c | 14 +++++++++++++-
1 files changed, 13 insertions(+), 1 deletions(-)
diff --git a/os/utils.c b/os/utils.c
index 51455cc..a08d591 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -242,6 +242,10 @@ OsSignal(int sig, OsSigHandlerPtr handler)
#endif
#endif
+#ifndef CLOCK_MONOTONIC_COARSE
+#define CLOCK_MONOTONIC_COARSE 6
+#endif
+
static Bool StillLocking = FALSE;
static char LockFile[PATH_MAX];
static Bool nolock = FALSE;
@@ -427,7 +431,15 @@ GetTimeInMillis(void)
#ifdef MONOTONIC_CLOCK
struct timespec tp;
- if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
+ static clockid_t clockid;
+ if (!clockid) {
+ if ((clock_getres(CLOCK_MONOTONIC_COARSE, &tp) == 0) &&
+ (tp.tv_nsec / 1000 <= 1000))
+ clockid = CLOCK_MONOTONIC_COARSE;
+ else
+ clockid = CLOCK_MONOTONIC;
+ }
+ if (clock_gettime(clockid, &tp) == 0)
return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
#endif
--
1.5.4.5
_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel