Chromium Code Reviews| Index: content/renderer/scheduler/throttled_message_sender.cc |
| diff --git a/content/renderer/scheduler/throttled_message_sender.cc b/content/renderer/scheduler/throttled_message_sender.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..242d4105b1616949cfe72de8326f5f8c8456464a |
| --- /dev/null |
| +++ b/content/renderer/scheduler/throttled_message_sender.cc |
| @@ -0,0 +1,116 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/renderer/scheduler/throttled_message_sender.h" |
| + |
| +#include "base/auto_reset.h" |
| +#include "content/renderer/scheduler/renderer_scheduler.h" |
| +#include "ipc/ipc_message.h" |
| + |
| +namespace content { |
| +namespace { |
| + |
| +const int kReasonableFlushesPerSecond = 60; |
|
picksi1
2015/01/13 11:24:44
Is this 60 related to the 60*4 in kMaxResourceMess
jdduke (slow)
2015/01/13 16:18:11
It's not really related, but I'll add a comment.
|
| + |
| +} // namespace |
| + |
| +ThrottledMessageSender::ThrottledMessageSender(IPC::Sender* proxied_sender, |
| + RendererScheduler* scheduler, |
| + int max_sent_messages_per_second) |
| + : proxied_sender_(proxied_sender), |
| + scheduler_(scheduler), |
| + max_sent_messages_per_flush_( |
| + std::max(1, |
| + max_sent_messages_per_second / kReasonableFlushesPerSecond)), |
| + flush_period_(base::TimeDelta::FromSecondsD( |
| + 1.f / |
| + std::min(max_sent_messages_per_second, kReasonableFlushesPerSecond))), |
| + sent_messages_since_last_flush_(0), |
| + flush_timer_(FROM_HERE, |
|
Sami
2015/01/13 14:47:35
I wonder if we should build some kind of use-idle-
rmcilroy
2015/01/13 15:24:37
I like this idea (if not the name... ;). How abou
jdduke (slow)
2015/01/13 16:18:11
All solid options, I'm open to whatever you all th
|
| + flush_period_, |
| + base::Bind(&ThrottledMessageSender::FlushThrottled, |
| + base::Unretained(this)), |
| + false /* is_repeating */), |
| + is_sending_via_proxied_(false) { |
| + DCHECK(proxied_sender); |
| + DCHECK(scheduler); |
| + DCHECK_GT(max_sent_messages_per_second, 0); |
| + flush_timer_.SetTaskRunner(scheduler->DefaultTaskRunner()); |
| +} |
| + |
| +ThrottledMessageSender::~ThrottledMessageSender() { |
| + FlushAll(); |
| + DCHECK(throttled_messages_.empty()); |
| +} |
| + |
| +bool ThrottledMessageSender::Send(IPC::Message* msg) { |
| + DCHECK(!is_sending_via_proxied_); |
| + thread_checker_.CalledOnValidThread(); |
| + |
| + if (msg->is_sync()) { |
| + FlushAll(); |
| + return SendViaProxiedSender(msg); |
| + } |
| + |
| + if (!throttled_messages_.empty()) { |
| + throttled_messages_.push_back(msg); |
|
picksi1
2015/01/13 11:24:44
cunning!
|
| + return true; |
| + } |
| + |
| + if (!scheduler_->ShouldYieldForHighPriorityWork()) |
|
alex clarke (OOO till 29th)
2015/01/13 10:38:02
I think you'd get better results if the scheduler
Sami
2015/01/13 14:47:35
What advantage were you thinking of? This feels li
rmcilroy
2015/01/13 15:24:37
I agree with Sami here - I think this shouldn't be
alex clarke (OOO till 29th)
2015/01/13 15:46:55
As far as I understand it, the intent here is to t
jdduke (slow)
2015/01/13 16:18:11
I agree with Alex here, and was actually going to
|
| + return SendViaProxiedSender(msg); |
| + |
| + if (Now() > (last_sent_message_time_ + flush_period_)) { |
| + // If sufficient time has passed since the previous send, we can effectively |
| + // mark the pipeline as flushed. |
| + sent_messages_since_last_flush_ = 0; |
| + return SendViaProxiedSender(msg); |
| + } |
| + |
| + if (sent_messages_since_last_flush_ < max_sent_messages_per_flush_) |
| + return SendViaProxiedSender(msg); |
| + |
| + throttled_messages_.push_back(msg); |
| + DCHECK(!flush_timer_.IsRunning()); |
| + flush_timer_.Reset(); |
| + return true; |
| +} |
| + |
| +base::TimeTicks ThrottledMessageSender::Now() const { |
| + return base::TimeTicks::Now(); |
| +} |
| + |
| +void ThrottledMessageSender::FlushAll() { |
| + sent_messages_since_last_flush_ = 0; |
|
picksi1
2015/01/13 11:24:44
Can you confirm that there are no threading issues
jdduke (slow)
2015/01/13 16:18:11
Yeah, I've got the |DCHECK(!is_sending_via_proxied
|
| + flush_timer_.Stop(); |
| + |
| + for (auto& msg : throttled_messages_) |
| + SendViaProxiedSender(msg); |
| + throttled_messages_.clear(); |
| +} |
| + |
| +void ThrottledMessageSender::FlushThrottled() { |
| + sent_messages_since_last_flush_ = 0; |
| + |
| + while (!throttled_messages_.empty() && |
|
picksi1
2015/01/13 11:24:44
Suggestion for discussion: Rather than checking fo
jdduke (slow)
2015/01/13 16:18:11
That's a solid option, though it would prevent the
|
| + sent_messages_since_last_flush_ < max_sent_messages_per_flush_) { |
| + IPC::Message* msg = throttled_messages_.front(); |
| + throttled_messages_.pop_front(); |
| + SendViaProxiedSender(msg); |
|
Sami
2015/01/13 14:47:35
Should we yield here too (after sending at least o
jdduke (slow)
2015/01/13 16:18:11
Hmm, the |Send| itself should be fairly cheap (max
|
| + } |
| + |
| + if (!throttled_messages_.empty()) |
| + flush_timer_.Reset(); |
| +} |
| + |
| +bool ThrottledMessageSender::SendViaProxiedSender(IPC::Message* msg) { |
| + DCHECK(!is_sending_via_proxied_); |
| + base::AutoReset<bool> is_sending_via_proxied_resetter( |
| + &is_sending_via_proxied_, true); |
| + last_sent_message_time_ = Now(); |
| + ++sent_messages_since_last_flush_; |
| + return proxied_sender_->Send(msg); |
| +} |
| + |
| +} // namespace content |