Commit 370d7cb8 authored by rsesek@chromium.org's avatar rsesek@chromium.org

Add instrumentation to the MessagePumpMac family of classes.

This adds UMA-uploaded histograms of sampling intervals for key points of data:
* Total time spent in a CFRunLoop
* Total time waiting in CFRunLoop
* Total time servicing MessagePump::Delegate (the MessageLoop)
* The MessageLoop queue size and queueing delay before servicing

It adds 1 second sampling for 15 seconds at startup, only for the main thread
(NSApplication-based) run loops.

The data will be used to determine if adding scheduling-like behavior to the
MessagePump will result in more efficient processing of the MessageLoop work.

An unforunate side effect of this change is exposing another method on the
MessagePump::Delegate interface, but there does not appear to be a better way
to do this.

BUG=264886
R=jar@chromium.org, mark@chromium.org

Review URL: https://codereview.chromium.org/22911026

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221427 0039d316-1c4b-4281-b951-d872f2087c98
parent 3af9b864
......@@ -660,6 +660,20 @@ bool MessageLoop::DoIdleWork() {
return false;
}
void MessageLoop::GetQueueingInformation(size_t* queue_size,
TimeDelta* queueing_delay) {
*queue_size = work_queue_.size();
if (*queue_size == 0) {
*queueing_delay = TimeDelta();
return;
}
const PendingTask& next_to_run = work_queue_.front();
tracked_objects::Duration duration =
tracked_objects::TrackedTime::Now() - next_to_run.EffectiveTimePosted();
*queueing_delay = TimeDelta::FromMilliseconds(duration.InMilliseconds());
}
void MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here,
void(*deleter)(const void*),
const void* object) {
......
......@@ -478,6 +478,8 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate {
virtual bool DoWork() OVERRIDE;
virtual bool DoDelayedWork(TimeTicks* next_delayed_work_time) OVERRIDE;
virtual bool DoIdleWork() OVERRIDE;
virtual void GetQueueingInformation(size_t* queue_size,
TimeDelta* queueing_delay) OVERRIDE;
Type type_;
......
......@@ -6,10 +6,12 @@
#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_
#include "base/base_export.h"
#include "base/basictypes.h"
#include "base/threading/non_thread_safe.h"
namespace base {
class TimeDelta;
class TimeTicks;
class BASE_EXPORT MessagePump : public NonThreadSafe {
......@@ -39,6 +41,19 @@ class BASE_EXPORT MessagePump : public NonThreadSafe {
// Called from within Run just before the message pump goes to sleep.
// Returns true to indicate that idle work was done.
virtual bool DoIdleWork() = 0;
// Via the two required out pointers, returns the length of the Delegate's
// work queue and the length of time that the first item in the queue has
// been waiting to run. If the work queue is empty, the count and delay
// will both be zero.
// Note that this only counts the tasks in the ready-to-run queue and not
// the incoming queue that is used by other threads to post tasks. The
// latter queue requires holding a lock, which is deemed too expensive for
// instrumentation code. Under normal conditions, the incoming queue should
// be small or zero, but under heavy loads it may be much larger and
// |queue_count| may be up to 1/4 the size of the incoming queue.
virtual void GetQueueingInformation(size_t* queue_count,
TimeDelta* queueing_delay) {}
};
MessagePump();
......
......@@ -36,6 +36,8 @@
#include <CoreFoundation/CoreFoundation.h>
#include "base/memory/weak_ptr.h"
#if !defined(__OBJC__)
class NSAutoreleasePool;
#else // !defined(__OBJC__)
......@@ -57,6 +59,7 @@ class NSAutoreleasePool;
namespace base {
class MessagePumpInstrumentation;
class RunLoop;
class TimeTicks;
......@@ -93,6 +96,11 @@ class MessagePumpCFRunLoopBase : public MessagePump {
// objects autoreleased by work to fall into the current autorelease pool.
virtual NSAutoreleasePool* CreateAutoreleasePool();
// Enables instrumentation of the MessagePump. See MessagePumpInstrumentation
// in the implementation for details.
void EnableInstrumentation();
WeakPtr<MessagePumpInstrumentation> instrumentation_;
private:
// Timer callback scheduled by ScheduleDelayedWork. This does not do any
// work, but it signals work_source_ so that delayed work can be performed
......@@ -106,11 +114,11 @@ class MessagePumpCFRunLoopBase : public MessagePump {
static void RunWorkSource(void* info);
bool RunWork();
// Perform idle-priority work. This is normally called by PreWaitObserver,
// but is also associated with idle_work_source_. When this function
// actually does perform idle work, it will resignal that source. The
// static method calls the instance method; the instance method returns
// true if idle work was done.
// Perform idle-priority work. This is normally called by
// StartOrEndWaitObserver, but is also associated with idle_work_source_. When
// this function actually does perform idle work, it will resignal that
// source. The static method calls the instance method; the instance method
// returns true if idle work was done.
static void RunIdleWorkSource(void* info);
bool RunIdleWork();
......@@ -132,8 +140,8 @@ class MessagePumpCFRunLoopBase : public MessagePump {
// Observer callback responsible for performing idle-priority work, before
// the run loop goes to sleep. Associated with idle_work_observer_.
static void PreWaitObserver(CFRunLoopObserverRef observer,
CFRunLoopActivity activity, void* info);
static void StartOrEndWaitObserver(CFRunLoopObserverRef observer,
CFRunLoopActivity activity, void* info);
// Observer callback called before the run loop processes any sources.
// Associated with pre_source_observer_.
......
This diff is collapsed.
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