diff options
author | bulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-11 09:24:42 +0000 |
---|---|---|
committer | bulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-11 09:24:42 +0000 |
commit | 97532f3fa4d5137cd932a4e29d806380c43a07cf (patch) | |
tree | 106d7756917d22ab1b6ee547fa43b43e5e634c34 /base/message_loop | |
parent | 3aa5487f2cc7b4838eb4bafdc471faaba24db434 (diff) | |
download | chromium_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.cc | 58 |
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 |