Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2121)

Unified Diff: content/renderer/input/main_thread_event_queue.cc

Issue 2166703003: Implement Main Thread RAF Aligned Input (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master_main_thread_queue
Patch Set: Fix build Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..ad9ca5216703d07a3de5b1a725f098cd1c810a05 100644
--- a/content/renderer/input/main_thread_event_queue.cc
+++ b/content/renderer/input/main_thread_event_queue.cc
@@ -4,17 +4,40 @@
#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 post-coalesced events processed per rAF task. 10 was
+// chosen because it really should never be hit yet prevents an infinite loop if
+// the compositor keeps delivering events faster than the main thread can
+// process them.
+const size_t kMaxEventsPerRafTask = 10;
+
+bool isContinuousEvent(const std::unique_ptr<EventWithDispatchType>& event) {
+ switch (event->event().type) {
+ case blink::WebInputEvent::MouseMove:
+ case blink::WebInputEvent::TouchMove:
+ case blink::WebInputEvent::MouseWheel:
+ return true;
+ default:
+ return false;
+ }
+}
tdresser 2016/08/25 14:38:41 Missing newline.
dtapuska 2016/08/25 15:01:35 Done.
+} // 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()),
+ last_coalesced_timestamp_(creation_timestamp_) {}
EventWithDispatchType::~EventWithDispatchType() {}
@@ -25,16 +48,17 @@ 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);
+ last_coalesced_timestamp_ = base::TimeTicks::Now();
}
+MainThreadEventQueue::SharedState::SharedState()
+ : sent_main_frame_request_(false) {}
+
+MainThreadEventQueue::SharedState::~SharedState() {}
+
MainThreadEventQueue::MainThreadEventQueue(
int routing_id,
MainThreadEventQueueClient* client,
@@ -46,6 +70,8 @@ MainThreadEventQueue::MainThreadEventQueue(
last_touch_start_forced_nonblocking_due_to_fling_(false),
enable_fling_passive_listener_flag_(base::FeatureList::IsEnabled(
features::kPassiveEventListenersDueToFling)),
+ handle_raf_aligned_input_(
+ base::FeatureList::IsEnabled(features::kRafAlignedInputEvents)),
main_task_runner_(main_task_runner),
renderer_scheduler_(renderer_scheduler) {}
@@ -110,16 +136,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 continuous events; otherwise
+ // the zero value would be dominated by non-continuous events.
+ if (isContinuousEvent(in_flight_event_)) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.MainThreadEventQueue.Continuous.QueueingTime",
+ (base::TimeTicks::Now() - in_flight_event_->creationTimestamp())
+ .ToInternalValue(),
+ 1, 10000000, 100);
+
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.MainThreadEventQueue.Continuous.FreshnessTime",
+ (base::TimeTicks::Now() - in_flight_event_->lastCoalescedTimestamp())
+ .ToInternalValue(),
+ 1, 10000000, 100);
+
+ UMA_HISTOGRAM_COUNTS_100("Event.MainThreadEventQueue.CoalescedCount",
+ in_flight_event_->coalescedEventIds().size());
+ } else {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.MainThreadEventQueue.NonContinuous.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 +177,41 @@ void MainThreadEventQueue::PopEventOnMainThread() {
in_flight_event_.reset();
}
+void MainThreadEventQueue::PossiblyScheduleMainFrame() {
+ if (!handle_raf_aligned_input_)
+ return;
+ bool needs_main_frame = false;
+ {
+ base::AutoLock lock(shared_state_lock_);
+ if (!shared_state_.sent_main_frame_request_ &&
+ !shared_state_.events_.empty() &&
+ isContinuousEvent(shared_state_.events_.front())) {
+ needs_main_frame = !shared_state_.sent_main_frame_request_;
+ shared_state_.sent_main_frame_request_ = false;
+ }
+ }
+ if (needs_main_frame)
+ client_->NeedsMainFrame(routing_id_);
+}
+
+void MainThreadEventQueue::DispatchSingleEvent() {
+ {
+ base::AutoLock lock(shared_state_lock_);
+ if (shared_state_.events_.empty())
+ return;
+
+ in_flight_event_ = shared_state_.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 +221,68 @@ void MainThreadEventQueue::EventHandled(blink::WebInputEvent::Type type,
}
}
+void MainThreadEventQueue::DispatchRafAlignedInput() {
+ if (!handle_raf_aligned_input_)
+ return;
+
+ {
+ base::AutoLock lock(shared_state_lock_);
+ shared_state_.sent_main_frame_request_ = false;
+ }
+
+ for (size_t i = 0; i < kMaxEventsPerRafTask; ++i) {
+ {
+ base::AutoLock lock(shared_state_lock_);
+ if (shared_state_.events_.empty())
+ break;
+
+ if (!isContinuousEvent(shared_state_.events_.front()))
+ break;
+ in_flight_event_ = shared_state_.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 is_continuous = isContinuousEvent(event);
+ 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;
+ base::AutoLock lock(shared_state_lock_);
+ size_t size_before = shared_state_.events_.size();
+ shared_state_.events_.Queue(std::move(event));
+ size_t size_after = shared_state_.events_.size();
+ if (size_before != size_after) {
+ if (!handle_raf_aligned_input_) {
+ send_notification_count = 1;
+ } else if (!is_continuous) {
+ 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 (isContinuousEvent(shared_state_.events_.at(pos - 1)))
+ send_notification_count++;
+ else
+ break;
+ }
+ } else {
+ needs_main_frame = !shared_state_.sent_main_frame_request_;
+ shared_state_.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

Powered by Google App Engine
This is Rietveld 408576698