summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-05 19:36:20 +0000
committerjeremy@chromium.org <jeremy@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-05 19:36:20 +0000
commit57cd3d24748da3060fa42b70979a4c0390139ba1 (patch)
treeab2984c37a500b24e5adfebbb9dc95dc25875574
parent95218f20e3d6d5214857076ecd0c2e6e89f3669e (diff)
downloadchromium_src-57cd3d24748da3060fa42b70979a4c0390139ba1.zip
chromium_src-57cd3d24748da3060fa42b70979a4c0390139ba1.tar.gz
chromium_src-57cd3d24748da3060fa42b70979a4c0390139ba1.tar.bz2
[Mac] Maximise timer slack for background tabs
When a tab not playing audio is sent to the background, set timer slack to its maximum value. Support for setting timer slack is added at the MessageLoop level, the concrete implementation of this CL only affects CFMessagePump backed MessageLoops (which means just the main thread for backgrounded renderer processes at present). The MessageLoop implementation is designed to support its use on Windows and Linux (the Windows API sets slack per-timer like the Mac one, while on Linux slack, is set per-thread via a call to prctl() using PR_SET_TIMERSLACK). BUG=356804 Review URL: https://codereview.chromium.org/289863005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@275218 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/base.gypi1
-rw-r--r--base/message_loop/message_loop.h6
-rw-r--r--base/message_loop/message_pump.cc3
-rw-r--r--base/message_loop/message_pump.h4
-rw-r--r--base/message_loop/message_pump_mac.h4
-rw-r--r--base/message_loop/message_pump_mac.mm39
-rw-r--r--base/message_loop/timer_slack.h22
-rw-r--r--content/browser/renderer_host/render_process_host_impl.cc11
-rw-r--r--content/child/child_thread.cc15
-rw-r--r--content/child/child_thread.h2
-rw-r--r--content/common/child_process_messages.h2
11 files changed, 97 insertions, 12 deletions
diff --git a/base/base.gypi b/base/base.gypi
index 8144354..e285bff 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -357,6 +357,7 @@
'message_loop/message_pump_default.h',
'message_loop/message_pump_win.cc',
'message_loop/message_pump_win.h',
+ 'message_loop/timer_slack.h',
'metrics/sample_map.cc',
'metrics/sample_map.h',
'metrics/sample_vector.cc',
diff --git a/base/message_loop/message_loop.h b/base/message_loop/message_loop.h
index 165299d..22d4f73 100644
--- a/base/message_loop/message_loop.h
+++ b/base/message_loop/message_loop.h
@@ -18,6 +18,7 @@
#include "base/message_loop/message_loop_proxy.h"
#include "base/message_loop/message_loop_proxy_impl.h"
#include "base/message_loop/message_pump.h"
+#include "base/message_loop/timer_slack.h"
#include "base/observer_list.h"
#include "base/pending_task.h"
#include "base/sequenced_task_runner_helpers.h"
@@ -274,6 +275,11 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate {
// arbitrary MessageLoop to QuitWhenIdle.
static Closure QuitWhenIdleClosure();
+ // Set the timer slack for this message loop.
+ void SetTimerSlack(TimerSlack timer_slack) {
+ pump_->SetTimerSlack(timer_slack);
+ }
+
// Returns true if this loop is |type|. This allows subclasses (especially
// those in tests) to specialize how they are identified.
virtual bool IsType(Type type) const;
diff --git a/base/message_loop/message_pump.cc b/base/message_loop/message_pump.cc
index 7ffc2b1..3d85b9b 100644
--- a/base/message_loop/message_pump.cc
+++ b/base/message_loop/message_pump.cc
@@ -12,4 +12,7 @@ MessagePump::MessagePump() {
MessagePump::~MessagePump() {
}
+void MessagePump::SetTimerSlack(TimerSlack) {
+}
+
} // namespace base
diff --git a/base/message_loop/message_pump.h b/base/message_loop/message_pump.h
index 816bb3c..a795f31 100644
--- a/base/message_loop/message_pump.h
+++ b/base/message_loop/message_pump.h
@@ -7,6 +7,7 @@
#include "base/base_export.h"
#include "base/basictypes.h"
+#include "base/message_loop/timer_slack.h"
#include "base/threading/non_thread_safe.h"
namespace base {
@@ -134,6 +135,9 @@ class BASE_EXPORT MessagePump : public NonThreadSafe {
// cancelling any pending DoDelayedWork callback. This method may only be
// used on the thread that called Run.
virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) = 0;
+
+ // Sets the timer slack to the specified value.
+ virtual void SetTimerSlack(TimerSlack timer_slack);
};
} // namespace base
diff --git a/base/message_loop/message_pump_mac.h b/base/message_loop/message_pump_mac.h
index afdd7d1..6667279 100644
--- a/base/message_loop/message_pump_mac.h
+++ b/base/message_loop/message_pump_mac.h
@@ -37,6 +37,7 @@
#include <CoreFoundation/CoreFoundation.h>
#include "base/memory/weak_ptr.h"
+#include "base/message_loop/timer_slack.h"
#if defined(__OBJC__)
#if defined(OS_IOS)
@@ -93,6 +94,7 @@ class MessagePumpCFRunLoopBase : public MessagePump {
virtual void ScheduleWork() OVERRIDE;
virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) OVERRIDE;
+ virtual void SetTimerSlack(TimerSlack timer_slack) OVERRIDE;
protected:
// Accessors for private data members to be used by subclasses.
@@ -195,6 +197,8 @@ class MessagePumpCFRunLoopBase : public MessagePump {
// See PowerStateNotification.
CFAbsoluteTime delayed_work_fire_time_;
+ base::TimerSlack timer_slack_;
+
// The recursion depth of the currently-executing CFRunLoopRun loop on the
// run loop's thread. 0 if no run loops are running inside of whatever scope
// the object was created in.
diff --git a/base/message_loop/message_pump_mac.mm b/base/message_loop/message_pump_mac.mm
index 891cc34..25aac17 100644
--- a/base/message_loop/message_pump_mac.mm
+++ b/base/message_loop/message_pump_mac.mm
@@ -4,6 +4,7 @@
#import "base/message_loop/message_pump_mac.h"
+#include <dlfcn.h>
#import <Foundation/Foundation.h>
#include <limits>
@@ -12,6 +13,7 @@
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/mac/scoped_cftyperef.h"
+#include "base/message_loop/timer_slack.h"
#include "base/metrics/histogram.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
@@ -35,6 +37,33 @@ const CFTimeInterval kCFTimeIntervalMax =
bool g_not_using_cr_app = false;
#endif
+// Call through to CFRunLoopTimerSetTolerance(), which is only available on
+// OS X 10.9.
+void SetTimerTolerance(CFRunLoopTimerRef timer, CFTimeInterval tolerance) {
+ typedef void (*CFRunLoopTimerSetTolerancePtr)(CFRunLoopTimerRef timer,
+ CFTimeInterval tolerance);
+
+ static CFRunLoopTimerSetTolerancePtr settimertolerance_function_ptr;
+
+ static dispatch_once_t get_timer_tolerance_function_ptr_once;
+ dispatch_once(&get_timer_tolerance_function_ptr_once, ^{
+ NSBundle* bundle =[NSBundle
+ bundleWithPath:@"/System/Library/Frameworks/CoreFoundation.framework"];
+ const char* path = [[bundle executablePath] fileSystemRepresentation];
+ CHECK(path);
+ void* library_handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
+ CHECK(library_handle) << dlerror();
+ settimertolerance_function_ptr =
+ reinterpret_cast<CFRunLoopTimerSetTolerancePtr>(
+ dlsym(library_handle, "CFRunLoopTimerSetTolerance"));
+
+ dlclose(library_handle);
+ });
+
+ if (settimertolerance_function_ptr)
+ settimertolerance_function_ptr(timer, tolerance);
+}
+
} // namespace
namespace base {
@@ -282,6 +311,7 @@ class MessagePumpInstrumentation {
MessagePumpCFRunLoopBase::MessagePumpCFRunLoopBase()
: delegate_(NULL),
delayed_work_fire_time_(kCFTimeIntervalMax),
+ timer_slack_(base::TIMER_SLACK_NONE),
nesting_level_(0),
run_nesting_level_(0),
deepest_nesting_level_(0),
@@ -438,6 +468,15 @@ void MessagePumpCFRunLoopBase::ScheduleDelayedWork(
TimeDelta delta = delayed_work_time - TimeTicks::Now();
delayed_work_fire_time_ = CFAbsoluteTimeGetCurrent() + delta.InSecondsF();
CFRunLoopTimerSetNextFireDate(delayed_work_timer_, delayed_work_fire_time_);
+ if (timer_slack_ == TIMER_SLACK_MAXIMUM) {
+ SetTimerTolerance(delayed_work_timer_, delta.InSecondsF() * 0.5);
+ } else {
+ SetTimerTolerance(delayed_work_timer_, 0);
+ }
+}
+
+void MessagePumpCFRunLoopBase::SetTimerSlack(TimerSlack timer_slack) {
+ timer_slack_ = timer_slack;
}
// Called from the run loop.
diff --git a/base/message_loop/timer_slack.h b/base/message_loop/timer_slack.h
new file mode 100644
index 0000000..1ad6ca9
--- /dev/null
+++ b/base/message_loop/timer_slack.h
@@ -0,0 +1,22 @@
+// Copyright 2014 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.
+
+#ifndef BASE_MESSAGE_LOOP_TIMER_SLACK_H_
+#define BASE_MESSAGE_LOOP_TIMER_SLACK_H_
+
+namespace base {
+
+// Amount of timer slack to use for delayed timers. Increasing timer slack
+// allows the OS to coalesce timers more effectively.
+enum TimerSlack {
+ // Lowest value for timer slack allowed by OS.
+ TIMER_SLACK_NONE,
+
+ // Maximal value for timer slack allowed by OS.
+ TIMER_SLACK_MAXIMUM
+};
+
+} // namespace base
+
+#endif // BASE_MESSAGE_LOOP_TIMER_SLACK_H_
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index aed78ae..11f3944 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2012,16 +2012,19 @@ void RenderProcessHostImpl::SetBackgrounded(bool backgrounded) {
// is to not invoke the SetPriorityClass API if the dll is loaded.
if (GetModuleHandle(L"cbstext.dll"))
return;
+#endif // OS_WIN
- // Windows Vista+ has a fancy process backgrounding mode that can only be set
- // from within the process. So notify the child process of background state.
+ // Notify the child process of background state.
Send(new ChildProcessMsg_SetProcessBackgrounded(backgrounded));
-#else
+#if !defined(OS_WIN)
// Backgrounding may require elevated privileges not available to renderer
// processes, so control backgrounding from the process host.
+
+ // Windows Vista+ has a fancy process backgrounding mode that can only be set
+ // from within the process.
child_process_launcher_->SetProcessBackgrounded(backgrounded);
-#endif // OS_WIN
+#endif // !OS_WIN
}
void RenderProcessHostImpl::OnProcessLaunched() {
diff --git a/content/child/child_thread.cc b/content/child/child_thread.cc
index 044a5ca..5e77c404 100644
--- a/content/child/child_thread.cc
+++ b/content/child/child_thread.cc
@@ -16,6 +16,7 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
+#include "base/message_loop/timer_slack.h"
#include "base/process/kill.h"
#include "base/process/process_handle.h"
#include "base/strings/string_util.h"
@@ -442,10 +443,8 @@ bool ChildThread::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ChildProcessMsg_GetChildProfilerData,
OnGetChildProfilerData)
IPC_MESSAGE_HANDLER(ChildProcessMsg_DumpHandles, OnDumpHandles)
-#if defined(OS_WIN)
IPC_MESSAGE_HANDLER(ChildProcessMsg_SetProcessBackgrounded,
OnProcessBackgrounded)
-#endif
#if defined(USE_TCMALLOC)
IPC_MESSAGE_HANDLER(ChildProcessMsg_GetTcmallocStats, OnGetTcmallocStats)
#endif
@@ -554,10 +553,18 @@ void ChildThread::EnsureConnected() {
base::KillProcess(base::GetCurrentProcessHandle(), 0, false);
}
-#if defined(OS_WIN)
void ChildThread::OnProcessBackgrounded(bool background) {
+ // Set timer slack to maximum on main thread when in background.
+ base::TimerSlack timer_slack = base::TIMER_SLACK_NONE;
+ if (background)
+ timer_slack = base::TIMER_SLACK_MAXIMUM;
+ base::MessageLoop::current()->SetTimerSlack(timer_slack);
+
+#ifdef OS_WIN
+ // Windows Vista+ has a fancy process backgrounding mode that can only be set
+ // from within the process.
base::Process::Current().SetProcessBackgrounded(background);
+#endif // OS_WIN
}
-#endif
} // namespace content
diff --git a/content/child/child_thread.h b/content/child/child_thread.h
index 9660f80..b272db3 100644
--- a/content/child/child_thread.h
+++ b/content/child/child_thread.h
@@ -195,9 +195,7 @@ class CONTENT_EXPORT ChildThread
void OnSetProfilerStatus(tracked_objects::ThreadData::Status status);
void OnGetChildProfilerData(int sequence_number);
void OnDumpHandles();
-#if defined(OS_WIN)
void OnProcessBackgrounded(bool background);
-#endif
#ifdef IPC_MESSAGE_LOG_ENABLED
void OnSetIPCLoggingEnabled(bool enable);
#endif
diff --git a/content/common/child_process_messages.h b/content/common/child_process_messages.h
index 67191fc..da76e02 100644
--- a/content/common/child_process_messages.h
+++ b/content/common/child_process_messages.h
@@ -111,11 +111,9 @@ IPC_MESSAGE_CONTROL1(ChildProcessMsg_GetChildHistogramData,
// Sent to child processes to dump their handle table.
IPC_MESSAGE_CONTROL0(ChildProcessMsg_DumpHandles)
-#if defined(OS_WIN)
// Sent to child processes to tell them to enter or leave background mode.
IPC_MESSAGE_CONTROL1(ChildProcessMsg_SetProcessBackgrounded,
bool /* background */)
-#endif
#if defined(USE_TCMALLOC)
// Sent to child process to request tcmalloc stats.