Index: chrome/browser/metrics/histogram_synchronizer.cc |
=================================================================== |
--- chrome/browser/metrics/histogram_synchronizer.cc (revision 146279) |
+++ chrome/browser/metrics/histogram_synchronizer.cc (working copy) |
@@ -1,264 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/metrics/histogram_synchronizer.h" |
- |
-#include "base/bind.h" |
-#include "base/logging.h" |
-#include "base/metrics/histogram.h" |
-#include "base/threading/thread.h" |
-#include "base/threading/thread_restrictions.h" |
-#include "chrome/common/chrome_constants.h" |
-#include "chrome/common/render_messages.h" |
-#include "content/public/browser/browser_thread.h" |
-#include "content/public/browser/render_process_host.h" |
- |
-using base::Time; |
-using base::TimeDelta; |
-using base::TimeTicks; |
-using content::BrowserThread; |
- |
-// Negative numbers are never used as sequence numbers. We explicitly pick a |
-// negative number that is "so negative" that even when we add one (as is done |
-// when we generated the next sequence number) that it will still be negative. |
-// We have code that handles wrapping around on an overflow into negative |
-// territory. |
-static const int kNeverUsableSequenceNumber = -2; |
- |
-HistogramSynchronizer::HistogramSynchronizer() |
- : lock_(), |
- received_all_renderer_histograms_(&lock_), |
- callback_thread_(NULL), |
- last_used_sequence_number_(kNeverUsableSequenceNumber), |
- async_sequence_number_(kNeverUsableSequenceNumber), |
- async_renderers_pending_(0), |
- synchronous_sequence_number_(kNeverUsableSequenceNumber), |
- synchronous_renderers_pending_(0) { |
- DCHECK(histogram_synchronizer_ == NULL); |
- histogram_synchronizer_ = this; |
-} |
- |
-HistogramSynchronizer::~HistogramSynchronizer() { |
- // Just in case we have any pending tasks, clear them out. |
- SetCallbackTaskAndThread(NULL, base::Closure()); |
- histogram_synchronizer_ = NULL; |
-} |
- |
-// static |
-HistogramSynchronizer* HistogramSynchronizer::CurrentSynchronizer() { |
- DCHECK(histogram_synchronizer_ != NULL); |
- return histogram_synchronizer_; |
-} |
- |
-void HistogramSynchronizer::FetchRendererHistogramsSynchronously( |
- TimeDelta wait_time) { |
- NotifyAllRenderers(SYNCHRONOUS_HISTOGRAMS); |
- |
- TimeTicks start = TimeTicks::Now(); |
- TimeTicks end_time = start + wait_time; |
- int unresponsive_renderer_count; |
- { |
- base::AutoLock auto_lock(lock_); |
- while (synchronous_renderers_pending_ > 0 && TimeTicks::Now() < end_time) { |
- wait_time = end_time - TimeTicks::Now(); |
- base::ThreadRestrictions::ScopedAllowWait allow_wait; |
- received_all_renderer_histograms_.TimedWait(wait_time); |
- } |
- unresponsive_renderer_count = synchronous_renderers_pending_; |
- synchronous_renderers_pending_ = 0; |
- synchronous_sequence_number_ = kNeverUsableSequenceNumber; |
- } |
- UMA_HISTOGRAM_COUNTS("Histogram.RendersNotRespondingSynchronous", |
- unresponsive_renderer_count); |
- if (!unresponsive_renderer_count) |
- UMA_HISTOGRAM_TIMES("Histogram.FetchRendererHistogramsSynchronously", |
- TimeTicks::Now() - start); |
-} |
- |
-// static |
-void HistogramSynchronizer::FetchRendererHistogramsAsynchronously( |
- MessageLoop* callback_thread, |
- const base::Closure& callback, |
- base::TimeDelta wait_time) { |
- DCHECK(callback_thread != NULL); |
- DCHECK(!callback.is_null()); |
- |
- HistogramSynchronizer* current_synchronizer = CurrentSynchronizer(); |
- |
- if (current_synchronizer == NULL) { |
- // System teardown is happening. |
- callback_thread->PostTask(FROM_HERE, callback); |
- return; |
- } |
- |
- current_synchronizer->SetCallbackTaskAndThread(callback_thread, |
- callback); |
- |
- int sequence_number = |
- current_synchronizer->NotifyAllRenderers(ASYNC_HISTOGRAMS); |
- |
- // Post a task that would be called after waiting for wait_time. This acts |
- // as a watchdog, to ensure that a non-responsive renderer won't block us from |
- // making the callback. |
- BrowserThread::PostDelayedTask( |
- BrowserThread::UI, FROM_HERE, |
- base::Bind( |
- &HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback, |
- current_synchronizer, |
- sequence_number), |
- wait_time); |
-} |
- |
-// static |
-void HistogramSynchronizer::DeserializeHistogramList( |
- int sequence_number, |
- const std::vector<std::string>& histograms) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
- for (std::vector<std::string>::const_iterator it = histograms.begin(); |
- it < histograms.end(); |
- ++it) { |
- base::Histogram::DeserializeHistogramInfo(*it); |
- } |
- |
- HistogramSynchronizer* current_synchronizer = CurrentSynchronizer(); |
- if (current_synchronizer == NULL) |
- return; |
- |
- // Record that we have received a histogram from renderer process. |
- current_synchronizer->DecrementPendingRenderers(sequence_number); |
-} |
- |
-int HistogramSynchronizer::NotifyAllRenderers( |
- RendererHistogramRequester requester) { |
- // To iterate over RenderProcessHosts, or to send messages to the hosts, we |
- // need to be on the UI thread. |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- int notification_count = 0; |
- for (content::RenderProcessHost::iterator it( |
- content::RenderProcessHost::AllHostsIterator()); |
- !it.IsAtEnd(); it.Advance()) |
- ++notification_count; |
- |
- int sequence_number = GetNextAvailableSequenceNumber(requester, |
- notification_count); |
- for (content::RenderProcessHost::iterator it( |
- content::RenderProcessHost::AllHostsIterator()); |
- !it.IsAtEnd(); it.Advance()) { |
- if (!it.GetCurrentValue()->Send( |
- new ChromeViewMsg_GetRendererHistograms(sequence_number))) |
- DecrementPendingRenderers(sequence_number); |
- } |
- |
- return sequence_number; |
-} |
- |
-void HistogramSynchronizer::DecrementPendingRenderers(int sequence_number) { |
- bool synchronous_completed = false; |
- bool asynchronous_completed = false; |
- |
- { |
- base::AutoLock auto_lock(lock_); |
- if (sequence_number == async_sequence_number_) { |
- if (--async_renderers_pending_ <= 0) |
- asynchronous_completed = true; |
- } else if (sequence_number == synchronous_sequence_number_) { |
- if (--synchronous_renderers_pending_ <= 0) |
- synchronous_completed = true; |
- } |
- } |
- |
- if (asynchronous_completed) |
- ForceHistogramSynchronizationDoneCallback(sequence_number); |
- else if (synchronous_completed) |
- received_all_renderer_histograms_.Signal(); |
-} |
- |
-void HistogramSynchronizer::SetCallbackTaskAndThread( |
- MessageLoop* callback_thread, |
- const base::Closure& callback) { |
- base::Closure old_callback; |
- MessageLoop* old_thread = NULL; |
- TimeTicks old_start_time; |
- int unresponsive_renderers; |
- const TimeTicks now = TimeTicks::Now(); |
- { |
- base::AutoLock auto_lock(lock_); |
- old_callback = callback_; |
- callback_ = callback; |
- old_thread = callback_thread_; |
- callback_thread_ = callback_thread; |
- unresponsive_renderers = async_renderers_pending_; |
- old_start_time = async_callback_start_time_; |
- async_callback_start_time_ = now; |
- // Prevent premature calling of our new callbacks. |
- async_sequence_number_ = kNeverUsableSequenceNumber; |
- } |
- // Just in case there was a task pending.... |
- InternalPostTask(old_thread, old_callback, unresponsive_renderers, |
- old_start_time); |
-} |
- |
-void HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback( |
- int sequence_number) { |
- base::Closure callback; |
- MessageLoop* thread = NULL; |
- TimeTicks started; |
- int unresponsive_renderers; |
- { |
- base::AutoLock lock(lock_); |
- if (sequence_number != async_sequence_number_) |
- return; |
- callback = callback_; |
- thread = callback_thread_; |
- callback_.Reset(); |
- callback_thread_ = NULL; |
- started = async_callback_start_time_; |
- unresponsive_renderers = async_renderers_pending_; |
- } |
- InternalPostTask(thread, callback, unresponsive_renderers, started); |
-} |
- |
-void HistogramSynchronizer::InternalPostTask(MessageLoop* thread, |
- const base::Closure& callback, |
- int unresponsive_renderers, |
- const base::TimeTicks& started) { |
- if (callback.is_null() || !thread) |
- return; |
- UMA_HISTOGRAM_COUNTS("Histogram.RendersNotRespondingAsynchronous", |
- unresponsive_renderers); |
- if (!unresponsive_renderers) { |
- UMA_HISTOGRAM_TIMES("Histogram.FetchRendererHistogramsAsynchronously", |
- TimeTicks::Now() - started); |
- } |
- |
- thread->PostTask(FROM_HERE, callback); |
-} |
- |
-int HistogramSynchronizer::GetNextAvailableSequenceNumber( |
- RendererHistogramRequester requester, |
- int renderer_count) { |
- base::AutoLock auto_lock(lock_); |
- ++last_used_sequence_number_; |
- // Watch out for wrapping to a negative number. |
- if (last_used_sequence_number_ < 0) { |
- // Bypass the reserved number, which is used when a renderer spontaneously |
- // decides to send some histogram data. |
- last_used_sequence_number_ = |
- chrome::kHistogramSynchronizerReservedSequenceNumber + 1; |
- } |
- DCHECK_NE(last_used_sequence_number_, |
- chrome::kHistogramSynchronizerReservedSequenceNumber); |
- if (requester == ASYNC_HISTOGRAMS) { |
- async_sequence_number_ = last_used_sequence_number_; |
- async_renderers_pending_ = renderer_count; |
- } else if (requester == SYNCHRONOUS_HISTOGRAMS) { |
- synchronous_sequence_number_ = last_used_sequence_number_; |
- synchronous_renderers_pending_ = renderer_count; |
- } |
- return last_used_sequence_number_; |
-} |
- |
-// static |
-HistogramSynchronizer* HistogramSynchronizer::histogram_synchronizer_ = NULL; |