Index: content/renderer/input/main_thread_event_queue.cc |
diff --git a/content/renderer/input/main_thread_event_queue.cc b/content/renderer/input/main_thread_event_queue.cc |
index 8c1b8675cfafb469d36ae1841c51a4d9256fe32e..65aeb1951d01ceec925646cdb52891005e2fefdd 100644 |
--- a/content/renderer/input/main_thread_event_queue.cc |
+++ b/content/renderer/input/main_thread_event_queue.cc |
@@ -4,17 +4,37 @@ |
#include "content/renderer/input/main_thread_event_queue.h" |
+#include "base/metrics/histogram_macros.h" |
#include "content/common/input/event_with_latency_info.h" |
#include "content/common/input_messages.h" |
namespace content { |
+namespace { |
+ |
+// The maximum number of events processed per RAF task. |
+const size_t kMaxEventsPerRafTask = 10; |
tdresser
2016/08/24 13:42:59
I don't completely understand this constant.
Supp
dtapuska
2016/08/24 17:10:06
So you want to send them all to the main thread at
|
+ |
+bool isContiniousEvent(const std::unique_ptr<EventWithDispatchType>& event) { |
tdresser
2016/08/24 13:42:59
Continuous
dtapuska
2016/08/24 17:10:06
done; face palm.
|
+ switch (event->event().type) { |
+ case blink::WebInputEvent::MouseMove: |
+ case blink::WebInputEvent::TouchMove: |
+ case blink::WebInputEvent::MouseWheel: |
+ return true; |
+ default: |
+ return false; |
+ } |
+} |
+} // namespace |
+ |
EventWithDispatchType::EventWithDispatchType( |
ui::ScopedWebInputEvent event, |
const ui::LatencyInfo& latency, |
InputEventDispatchType dispatch_type) |
: ScopedWebInputEventWithLatencyInfo(std::move(event), latency), |
- dispatch_type_(dispatch_type) {} |
+ dispatch_type_(dispatch_type), |
+ creation_timestamp_(base::TimeTicks::Now()), |
+ coalesced_timestamp_(creation_timestamp_) {} |
EventWithDispatchType::~EventWithDispatchType() {} |
@@ -25,27 +45,26 @@ bool EventWithDispatchType::CanCoalesceWith( |
} |
void EventWithDispatchType::CoalesceWith(const EventWithDispatchType& other) { |
- // If we are blocking and are coalescing touch, make sure to keep |
- // the touch ids that need to be acked. |
- if (dispatch_type_ == DISPATCH_TYPE_BLOCKING) { |
- // We should only have blocking touch events that need coalescing. |
- eventsToAck_.push_back( |
- ui::WebInputEventTraits::GetUniqueTouchEventId(other.event())); |
- } |
+ coalesced_event_ids_.push_back( |
+ ui::WebInputEventTraits::GetUniqueTouchEventId(other.event())); |
ScopedWebInputEventWithLatencyInfo::CoalesceWith(other); |
+ coalesced_timestamp_ = base::TimeTicks::Now(); |
} |
MainThreadEventQueue::MainThreadEventQueue( |
int routing_id, |
MainThreadEventQueueClient* client, |
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner, |
- blink::scheduler::RendererScheduler* renderer_scheduler) |
+ blink::scheduler::RendererScheduler* renderer_scheduler, |
+ bool handle_raf_aligned_input) |
: routing_id_(routing_id), |
client_(client), |
is_flinging_(false), |
last_touch_start_forced_nonblocking_due_to_fling_(false), |
enable_fling_passive_listener_flag_(base::FeatureList::IsEnabled( |
features::kPassiveEventListenersDueToFling)), |
+ handle_raf_aligned_input_(handle_raf_aligned_input), |
+ sent_main_frame_request_(false), |
main_task_runner_(main_task_runner), |
renderer_scheduler_(renderer_scheduler) {} |
@@ -110,16 +129,35 @@ bool MainThreadEventQueue::HandleEvent( |
return non_blocking; |
} |
-void MainThreadEventQueue::PopEventOnMainThread() { |
- { |
- base::AutoLock lock(event_queue_lock_); |
- if (!events_.empty()) |
- in_flight_event_ = events_.Pop(); |
- } |
- |
+void MainThreadEventQueue::DispatchInFlightEvent() { |
if (in_flight_event_) { |
+ // Report the coalesced count only for continious events; otherwise |
+ // the zero value would be dominated by non-continious events. |
+ if (isContiniousEvent(in_flight_event_)) { |
+ UMA_HISTOGRAM_CUSTOM_COUNTS( |
+ "Event.MainThreadEventQueue.Continious.QueueingTime", |
+ (base::TimeTicks::Now() - in_flight_event_->creationTimestamp()) |
+ .ToInternalValue(), |
+ 1, 10000000, 100); |
+ |
+ UMA_HISTOGRAM_CUSTOM_COUNTS( |
+ "Event.MainThreadEventQueue.Continious.FreshnessTime", |
+ (base::TimeTicks::Now() - in_flight_event_->coalescedTimestamp()) |
+ .ToInternalValue(), |
+ 1, 10000000, 100); |
+ |
+ UMA_HISTOGRAM_COUNTS_100("Event.MainThreadEventQueue.CoalescedCount", |
+ in_flight_event_->coalescedEventIds().size()); |
+ } else { |
+ UMA_HISTOGRAM_CUSTOM_COUNTS( |
+ "Event.MainThreadEventQueue.NonContinious.QueueingTime", |
+ (base::TimeTicks::Now() - in_flight_event_->creationTimestamp()) |
+ .ToInternalValue(), |
+ 1, 10000000, 100); |
+ } |
+ |
InputEventDispatchType dispatch_type = in_flight_event_->dispatchType(); |
- if (!in_flight_event_->eventsToAck().empty() && |
+ if (!in_flight_event_->coalescedEventIds().empty() && |
dispatch_type == DISPATCH_TYPE_BLOCKING) { |
dispatch_type = DISPATCH_TYPE_BLOCKING_NOTIFY_MAIN; |
} |
@@ -132,11 +170,40 @@ void MainThreadEventQueue::PopEventOnMainThread() { |
in_flight_event_.reset(); |
} |
+void MainThreadEventQueue::PossiblyScheduleMainFrame() { |
+ if (!handle_raf_aligned_input_) |
+ return; |
+ bool needs_main_frame = false; |
+ { |
+ base::AutoLock lock(event_queue_lock_); |
+ if (!sent_main_frame_request_ && !events_.empty() && |
+ isContiniousEvent(events_.front())) { |
+ needs_main_frame = !sent_main_frame_request_; |
+ sent_main_frame_request_ = false; |
+ } |
+ } |
+ if (needs_main_frame) |
+ client_->NeedsMainFrame(routing_id_); |
+} |
+ |
+void MainThreadEventQueue::DispatchSingleEvent() { |
+ { |
+ base::AutoLock lock(event_queue_lock_); |
+ if (events_.empty()) |
+ return; |
+ |
+ in_flight_event_ = events_.Pop(); |
+ } |
+ DispatchInFlightEvent(); |
+ PossiblyScheduleMainFrame(); |
+} |
+ |
void MainThreadEventQueue::EventHandled(blink::WebInputEvent::Type type, |
InputEventAckState ack_result) { |
- if (in_flight_event_) { |
- // Send acks for blocking touch events. |
- for (const auto id : in_flight_event_->eventsToAck()) { |
+ if (in_flight_event_ && |
+ in_flight_event_->dispatchType() == DISPATCH_TYPE_BLOCKING) { |
+ // We should only have blocking touch events that need coalescing. |
+ for (const auto id : in_flight_event_->coalescedEventIds()) { |
client_->SendInputEventAck(routing_id_, type, ack_result, id); |
if (renderer_scheduler_) { |
renderer_scheduler_->DidHandleInputEventOnMainThread( |
@@ -146,23 +213,68 @@ void MainThreadEventQueue::EventHandled(blink::WebInputEvent::Type type, |
} |
} |
+void MainThreadEventQueue::DispatchRafAlignedInput() { |
+ if (!handle_raf_aligned_input_) |
+ return; |
+ |
+ { |
+ base::AutoLock lock(event_queue_lock_); |
+ sent_main_frame_request_ = false; |
+ } |
+ |
+ for (size_t i = 0; i < kMaxEventsPerRafTask; ++i) { |
+ { |
+ base::AutoLock lock(event_queue_lock_); |
+ if (events_.empty()) |
+ break; |
+ |
+ if (!isContiniousEvent(events_.front())) |
+ break; |
+ in_flight_event_ = events_.Pop(); |
+ } |
+ DispatchInFlightEvent(); |
+ } |
+ PossiblyScheduleMainFrame(); |
+} |
+ |
void MainThreadEventQueue::SendEventNotificationToMainThread() { |
main_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&MainThreadEventQueue::PopEventOnMainThread, |
- this)); |
+ FROM_HERE, base::Bind(&MainThreadEventQueue::DispatchSingleEvent, this)); |
} |
void MainThreadEventQueue::QueueEvent( |
std::unique_ptr<EventWithDispatchType> event) { |
- bool send_notification = false; |
+ bool isContinious = isContiniousEvent(event); |
tdresser
2016/08/24 13:42:59
is_continuous
dtapuska
2016/08/24 17:10:06
done
|
+ size_t send_notification_count = 0; |
+ bool needs_main_frame = false; |
{ |
base::AutoLock lock(event_queue_lock_); |
size_t size_before = events_.size(); |
events_.Queue(std::move(event)); |
- send_notification = events_.size() != size_before; |
+ size_t size_after = events_.size(); |
+ if (size_before != size_after) { |
+ if (!handle_raf_aligned_input_) { |
+ send_notification_count = 1; |
+ } else if (!isContinious) { |
+ send_notification_count = 1; |
+ // If we had just enqueued a non-RAF input event we will send a series |
+ // of normal post messages to ensure they are all handled right away. |
+ for (size_t pos = size_after - 1; pos >= 1; --pos) { |
+ if (isContiniousEvent(events_.at(pos - 1))) |
+ send_notification_count++; |
+ else |
+ break; |
+ } |
+ } else { |
+ needs_main_frame = !sent_main_frame_request_; |
+ sent_main_frame_request_ = true; |
+ } |
+ } |
} |
- if (send_notification) |
+ for (size_t i = 0; i < send_notification_count; ++i) |
SendEventNotificationToMainThread(); |
+ if (needs_main_frame) |
+ client_->NeedsMainFrame(routing_id_); |
} |
} // namespace content |