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() { ...@@ -660,6 +660,20 @@ bool MessageLoop::DoIdleWork() {
return false; 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 MessageLoop::DeleteSoonInternal(const tracked_objects::Location& from_here,
void(*deleter)(const void*), void(*deleter)(const void*),
const void* object) { const void* object) {
......
...@@ -478,6 +478,8 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate { ...@@ -478,6 +478,8 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate {
virtual bool DoWork() OVERRIDE; virtual bool DoWork() OVERRIDE;
virtual bool DoDelayedWork(TimeTicks* next_delayed_work_time) OVERRIDE; virtual bool DoDelayedWork(TimeTicks* next_delayed_work_time) OVERRIDE;
virtual bool DoIdleWork() OVERRIDE; virtual bool DoIdleWork() OVERRIDE;
virtual void GetQueueingInformation(size_t* queue_size,
TimeDelta* queueing_delay) OVERRIDE;
Type type_; Type type_;
......
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_ #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_H_
#include "base/base_export.h" #include "base/base_export.h"
#include "base/basictypes.h"
#include "base/threading/non_thread_safe.h" #include "base/threading/non_thread_safe.h"
namespace base { namespace base {
class TimeDelta;
class TimeTicks; class TimeTicks;
class BASE_EXPORT MessagePump : public NonThreadSafe { class BASE_EXPORT MessagePump : public NonThreadSafe {
...@@ -39,6 +41,19 @@ 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. // Called from within Run just before the message pump goes to sleep.
// Returns true to indicate that idle work was done. // Returns true to indicate that idle work was done.
virtual bool DoIdleWork() = 0; 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(); MessagePump();
......
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#include "base/memory/weak_ptr.h"
#if !defined(__OBJC__) #if !defined(__OBJC__)
class NSAutoreleasePool; class NSAutoreleasePool;
#else // !defined(__OBJC__) #else // !defined(__OBJC__)
...@@ -57,6 +59,7 @@ class NSAutoreleasePool; ...@@ -57,6 +59,7 @@ class NSAutoreleasePool;
namespace base { namespace base {
class MessagePumpInstrumentation;
class RunLoop; class RunLoop;
class TimeTicks; class TimeTicks;
...@@ -93,6 +96,11 @@ class MessagePumpCFRunLoopBase : public MessagePump { ...@@ -93,6 +96,11 @@ class MessagePumpCFRunLoopBase : public MessagePump {
// objects autoreleased by work to fall into the current autorelease pool. // objects autoreleased by work to fall into the current autorelease pool.
virtual NSAutoreleasePool* CreateAutoreleasePool(); virtual NSAutoreleasePool* CreateAutoreleasePool();
// Enables instrumentation of the MessagePump. See MessagePumpInstrumentation
// in the implementation for details.
void EnableInstrumentation();
WeakPtr<MessagePumpInstrumentation> instrumentation_;
private: private:
// Timer callback scheduled by ScheduleDelayedWork. This does not do any // Timer callback scheduled by ScheduleDelayedWork. This does not do any
// work, but it signals work_source_ so that delayed work can be performed // work, but it signals work_source_ so that delayed work can be performed
...@@ -106,11 +114,11 @@ class MessagePumpCFRunLoopBase : public MessagePump { ...@@ -106,11 +114,11 @@ class MessagePumpCFRunLoopBase : public MessagePump {
static void RunWorkSource(void* info); static void RunWorkSource(void* info);
bool RunWork(); bool RunWork();
// Perform idle-priority work. This is normally called by PreWaitObserver, // Perform idle-priority work. This is normally called by
// but is also associated with idle_work_source_. When this function // StartOrEndWaitObserver, but is also associated with idle_work_source_. When
// actually does perform idle work, it will resignal that source. The // this function actually does perform idle work, it will resignal that
// static method calls the instance method; the instance method returns // source. The static method calls the instance method; the instance method
// true if idle work was done. // returns true if idle work was done.
static void RunIdleWorkSource(void* info); static void RunIdleWorkSource(void* info);
bool RunIdleWork(); bool RunIdleWork();
...@@ -132,7 +140,7 @@ class MessagePumpCFRunLoopBase : public MessagePump { ...@@ -132,7 +140,7 @@ class MessagePumpCFRunLoopBase : public MessagePump {
// Observer callback responsible for performing idle-priority work, before // Observer callback responsible for performing idle-priority work, before
// the run loop goes to sleep. Associated with idle_work_observer_. // the run loop goes to sleep. Associated with idle_work_observer_.
static void PreWaitObserver(CFRunLoopObserverRef observer, static void StartOrEndWaitObserver(CFRunLoopObserverRef observer,
CFRunLoopActivity activity, void* info); CFRunLoopActivity activity, void* info);
// Observer callback called before the run loop processes any sources. // Observer callback called before the run loop processes any sources.
......
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