Commit 4f3e2866 authored by majidvp's avatar majidvp Committed by Commit bot

Limit InterProcessTimeTickConverter to platforms that require it

On most platforms the monotonic clock is system wide which means it is
consistent across processes making conversion unnecessary. In fact not
only it is unnecessary but harmfull because the
InterProcessTimeTickConverter (IPTTC) conversion [1] is an estimation
which introduces some error.

The patch limits the usage of IPTTC to platforms that require it which
is any Windows where we cannot use |QueryPerformanceCounter|.

After this change we will only collect UMA metrics[2] for IPTTC on
platforms where it is used.

[1] https://docs.google.com/document/d/1RcaOZ1G8ttAez9YuilvbDJCkCaYuLKqNkVpQvIBqsvM/edit
[2] Affects InterProcessTimeTicks.*

BUG=616574
CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_site_isolation

Review-Url: https://codereview.chromium.org/2090783002
Cr-Commit-Position: refs/heads/master@{#407270}
parent 00314989
...@@ -713,6 +713,13 @@ class BASE_EXPORT TimeTicks : public time_internal::TimeBase<TimeTicks> { ...@@ -713,6 +713,13 @@ class BASE_EXPORT TimeTicks : public time_internal::TimeBase<TimeTicks> {
// clock will be used instead. // clock will be used instead.
static bool IsHighResolution(); static bool IsHighResolution();
// Returns true if TimeTicks is consistent across processes, meaning that
// timestamps taken on different processes can be safely compared with one
// another. (Note that, even on platforms where this returns true, time values
// from different threads that are within one tick of each other must be
// considered to have an ambiguous ordering.)
static bool IsConsistentAcrossProcesses();
#if defined(OS_WIN) #if defined(OS_WIN)
// Translates an absolute QPC timestamp into a TimeTicks value. The returned // Translates an absolute QPC timestamp into a TimeTicks value. The returned
// value has the same origin as Now(). Do NOT attempt to use this if // value has the same origin as Now(). Do NOT attempt to use this if
......
...@@ -258,6 +258,11 @@ bool TimeTicks::IsHighResolution() { ...@@ -258,6 +258,11 @@ bool TimeTicks::IsHighResolution() {
return true; return true;
} }
// static
bool TimeTicks::IsConsistentAcrossProcesses() {
return true;
}
// static // static
TimeTicks::Clock TimeTicks::GetClock() { TimeTicks::Clock TimeTicks::GetClock() {
#if defined(OS_IOS) #if defined(OS_IOS)
......
...@@ -339,6 +339,11 @@ bool TimeTicks::IsHighResolution() { ...@@ -339,6 +339,11 @@ bool TimeTicks::IsHighResolution() {
return true; return true;
} }
// static
bool TimeTicks::IsConsistentAcrossProcesses() {
return true;
}
// static // static
ThreadTicks ThreadTicks::Now() { ThreadTicks ThreadTicks::Now() {
#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ #if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
......
...@@ -503,6 +503,26 @@ bool TimeTicks::IsHighResolution() { ...@@ -503,6 +503,26 @@ bool TimeTicks::IsHighResolution() {
return g_now_function == &QPCNow; return g_now_function == &QPCNow;
} }
// static
bool TimeTicks::IsConsistentAcrossProcesses() {
// According to Windows documentation [1] QPC is consistent post-Windows
// Vista. So if we are using QPC then we are consistent which is the same as
// being high resolution.
//
// [1] https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
//
// "In general, the performance counter results are consistent across all
// processors in multi-core and multi-processor systems, even when measured on
// different threads or processes. Here are some exceptions to this rule:
// - Pre-Windows Vista operating systems that run on certain processors might
// violate this consistency because of one of these reasons:
// 1. The hardware processors have a non-invariant TSC and the BIOS
// doesn't indicate this condition correctly.
// 2. The TSC synchronization algorithm that was used wasn't suitable for
// systems with large numbers of processors."
return IsHighResolution();
}
// static // static
TimeTicks::Clock TimeTicks::GetClock() { TimeTicks::Clock TimeTicks::GetClock() {
return IsHighResolution() ? return IsHighResolution() ?
......
...@@ -1363,11 +1363,14 @@ void RenderFrameHostImpl::OnBeforeUnloadACK( ...@@ -1363,11 +1363,14 @@ void RenderFrameHostImpl::OnBeforeUnloadACK(
base::TimeTicks before_unload_end_time = renderer_before_unload_end_time; base::TimeTicks before_unload_end_time = renderer_before_unload_end_time;
if (!renderer_before_unload_start_time.is_null() && if (!renderer_before_unload_start_time.is_null() &&
!renderer_before_unload_end_time.is_null()) { !renderer_before_unload_end_time.is_null()) {
// When passing TimeTicks across process boundaries, we need to compensate
// for any skew between the processes. Here we are converting the
// renderer's notion of before_unload_end_time to TimeTicks in the browser
// process. See comments in inter_process_time_ticks_converter.h for more.
base::TimeTicks receive_before_unload_ack_time = base::TimeTicks::Now(); base::TimeTicks receive_before_unload_ack_time = base::TimeTicks::Now();
if (!base::TimeTicks::IsConsistentAcrossProcesses()) {
// TimeTicks is not consistent across processes and we are passing
// TimeTicks across process boundaries so we need to compensate for any
// skew between the processes. Here we are converting the renderer's
// notion of before_unload_end_time to TimeTicks in the browser process.
// See comments in inter_process_time_ticks_converter.h for more.
InterProcessTimeTicksConverter converter( InterProcessTimeTicksConverter converter(
LocalTimeTicks::FromTimeTicks(send_before_unload_start_time_), LocalTimeTicks::FromTimeTicks(send_before_unload_start_time_),
LocalTimeTicks::FromTimeTicks(receive_before_unload_ack_time), LocalTimeTicks::FromTimeTicks(receive_before_unload_ack_time),
...@@ -1394,6 +1397,7 @@ void RenderFrameHostImpl::OnBeforeUnloadACK( ...@@ -1394,6 +1397,7 @@ void RenderFrameHostImpl::OnBeforeUnloadACK(
UMA_HISTOGRAM_BOOLEAN( UMA_HISTOGRAM_BOOLEAN(
"InterProcessTimeTicks.IsSkewAdditive_RendererToBrowser", "InterProcessTimeTicks.IsSkewAdditive_RendererToBrowser",
is_skew_additive); is_skew_additive);
}
base::TimeDelta on_before_unload_overhead_time = base::TimeDelta on_before_unload_overhead_time =
(receive_before_unload_ack_time - send_before_unload_start_time_) - (receive_before_unload_ack_time - send_before_unload_start_time_) -
......
...@@ -608,7 +608,8 @@ void ResourceDispatcher::ToResourceResponseInfo( ...@@ -608,7 +608,8 @@ void ResourceDispatcher::ToResourceResponseInfo(
const ResourceResponseHead& browser_info, const ResourceResponseHead& browser_info,
ResourceResponseInfo* renderer_info) const { ResourceResponseInfo* renderer_info) const {
*renderer_info = browser_info; *renderer_info = browser_info;
if (request_info.request_start.is_null() || if (base::TimeTicks::IsConsistentAcrossProcesses() ||
request_info.request_start.is_null() ||
request_info.response_start.is_null() || request_info.response_start.is_null() ||
browser_info.request_start.is_null() || browser_info.request_start.is_null() ||
browser_info.response_start.is_null() || browser_info.response_start.is_null() ||
......
...@@ -17,8 +17,9 @@ class LocalTimeTicks; ...@@ -17,8 +17,9 @@ class LocalTimeTicks;
class RemoteTimeDelta; class RemoteTimeDelta;
class RemoteTimeTicks; class RemoteTimeTicks;
// On Windows, TimeTicks are not consistent between processes. Often, the values // On Windows, TimeTicks are not always consistent between processes as
// on one process have a static offset relative to another. Occasionally, these // indicated by |TimeTicks::IsConsistentAcrossProcesses()|. Often, the values on
// one process have a static offset relative to another. Occasionally, these
// offsets shift while running. // offsets shift while running.
// //
// To combat this, any TimeTicks values sent from the remote process to the // To combat this, any TimeTicks values sent from the remote process to the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment