Chromium Code Reviews| 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 |