summaryrefslogtreecommitdiffstats
path: root/base/message_loop
diff options
context:
space:
mode:
authorbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-11 09:24:42 +0000
committerbulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-11 09:24:42 +0000
commit97532f3fa4d5137cd932a4e29d806380c43a07cf (patch)
tree106d7756917d22ab1b6ee547fa43b43e5e634c34 /base/message_loop
parent3aa5487f2cc7b4838eb4bafdc471faaba24db434 (diff)
downloadchromium_src-97532f3fa4d5137cd932a4e29d806380c43a07cf.zip
chromium_src-97532f3fa4d5137cd932a4e29d806380c43a07cf.tar.gz
chromium_src-97532f3fa4d5137cd932a4e29d806380c43a07cf.tar.bz2
Android: minor improvements in SystemMessageHandler.
- android.os.MessageQueue.removeMessage is somewhat expensive. It was calling that method for every single message, and re-inserting a new one with slightly lower delay everytime. Fix that by only scheduling a new message if it must happen sooner. BUG=349059 Review URL: https://codereview.chromium.org/180783017 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@256158 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/message_loop')
-rw-r--r--base/message_loop/message_pump_android.cc58
1 files changed, 43 insertions, 15 deletions
diff --git a/base/message_loop/message_pump_android.cc b/base/message_loop/message_pump_android.cc
index e756fdd..ee8ff4d 100644
--- a/base/message_loop/message_pump_android.cc
+++ b/base/message_loop/message_pump_android.cc
@@ -21,7 +21,8 @@ using base::android::ScopedJavaLocalRef;
// ----------------------------------------------------------------------------
// This method can not move to anonymous namespace as it has been declared as
// 'static' in system_message_handler_jni.h.
-static void DoRunLoopOnce(JNIEnv* env, jobject obj, jlong native_delegate) {
+static void DoRunLoopOnce(JNIEnv* env, jobject obj, jlong native_delegate,
+ jlong delayed_scheduled_time_ticks) {
base::MessagePump::Delegate* delegate =
reinterpret_cast<base::MessagePump::Delegate*>(native_delegate);
DCHECK(delegate);
@@ -33,16 +34,42 @@ static void DoRunLoopOnce(JNIEnv* env, jobject obj, jlong native_delegate) {
// that will be processed before calling here again.
bool did_work = delegate->DoWork();
- // This is the time when we need to do delayed work.
- base::TimeTicks delayed_work_time;
- did_work |= delegate->DoDelayedWork(&delayed_work_time);
-
- // Always call this if there is a delayed message waiting in the queue
- // since is at most one delayed message in the Java message handler, and this
- // function call may be the result of that message being handled.
- if (!delayed_work_time.is_null()) {
- Java_SystemMessageHandler_setDelayedTimer(env, obj,
- (delayed_work_time - base::TimeTicks::Now()).InMillisecondsRoundedUp());
+ // In the java side, |SystemMessageHandler| keeps a single "delayed" message.
+ // It's an expensive operation to |removeMessage| there, so this is optimized
+ // to avoid those calls.
+ //
+ // At this stage, |next_delayed_work_time| can be:
+ // 1) The same as previously scheduled: nothing to be done, move along. This
+ // is the typical case, since this method is called for every single message.
+ //
+ // 2) Not previously scheduled: just post a new message in java.
+ //
+ // 3) Shorter than previously scheduled: far less common. In this case,
+ // |removeMessage| and post a new one.
+ //
+ // 4) Longer than previously scheduled (or null): nothing to be done, move
+ // along.
+ //
+ // Side note: base::TimeTicks is a C++ representation and can't be
+ // compared in java. When calling |scheduleDelayedWork|, pass the
+ // |InternalValue()| to java and then back to C++ so the comparisons can be
+ // done here.
+ // This roundtrip allows comparing TimeTicks directly (cheap) and
+ // avoid comparisons with TimeDelta / Now() (expensive).
+ base::TimeTicks next_delayed_work_time;
+ did_work |= delegate->DoDelayedWork(&next_delayed_work_time);
+
+ if (!next_delayed_work_time.is_null()) {
+ // Schedule a new message if there's nothing already scheduled or there's a
+ // shorter delay than previously scheduled (see (2) and (3) above).
+ if (delayed_scheduled_time_ticks == 0 ||
+ next_delayed_work_time < base::TimeTicks::FromInternalValue(
+ delayed_scheduled_time_ticks)) {
+ Java_SystemMessageHandler_scheduleDelayedWork(env, obj,
+ next_delayed_work_time.ToInternalValue(),
+ (next_delayed_work_time -
+ base::TimeTicks::Now()).InMillisecondsRoundedUp());
+ }
}
// This is a major difference between android and other platforms: since we
@@ -90,7 +117,7 @@ void MessagePumpForUI::Quit() {
JNIEnv* env = base::android::AttachCurrentThread();
DCHECK(env);
- Java_SystemMessageHandler_removeTimer(env,
+ Java_SystemMessageHandler_removeScheduledWork(env,
system_message_handler_obj_.obj());
system_message_handler_obj_.Reset();
}
@@ -108,7 +135,7 @@ void MessagePumpForUI::ScheduleWork() {
JNIEnv* env = base::android::AttachCurrentThread();
DCHECK(env);
- Java_SystemMessageHandler_setTimer(env,
+ Java_SystemMessageHandler_scheduleWork(env,
system_message_handler_obj_.obj());
}
@@ -122,8 +149,9 @@ void MessagePumpForUI::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
(delayed_work_time - TimeTicks::Now()).InMillisecondsRoundedUp();
// Note that we're truncating to milliseconds as required by the java side,
// even though delayed_work_time is microseconds resolution.
- Java_SystemMessageHandler_setDelayedTimer(env,
- system_message_handler_obj_.obj(), millis);
+ Java_SystemMessageHandler_scheduleDelayedWork(env,
+ system_message_handler_obj_.obj(),
+ delayed_work_time.ToInternalValue(), millis);
}
// static