Chromium Code Reviews| Index: mojo/common/message_pump_mojo.cc |
| diff --git a/mojo/common/message_pump_mojo.cc b/mojo/common/message_pump_mojo.cc |
| index afbf8f983b8fb4b57de6d2982a0a59bd7d600840..62c90fc0a253ec1ae18fd664939615e7bc279aa3 100644 |
| --- a/mojo/common/message_pump_mojo.cc |
| +++ b/mojo/common/message_pump_mojo.cc |
| @@ -53,6 +53,10 @@ struct MessagePumpMojo::RunState { |
| ScopedMessagePipeHandle read_handle; |
| ScopedMessagePipeHandle write_handle; |
| + // Cached structures to avoid the heap allocation cost of std::vector<>. |
| + scoped_ptr<WaitState> wait_state; |
| + scoped_ptr<HandleToHandlerList> cloned_handlers; |
| + |
| bool should_quit; |
| }; |
| @@ -172,10 +176,13 @@ void MessagePumpMojo::DoRunLoop(RunState* run_state, Delegate* delegate) { |
| bool MessagePumpMojo::DoInternalWork(const RunState& run_state, bool block) { |
| const MojoDeadline deadline = block ? GetDeadlineForWait(run_state) : 0; |
| - const WaitState wait_state = GetWaitState(run_state); |
| + if (!run_state_->wait_state) |
| + run_state_->wait_state.reset(new WaitState); |
| + GetWaitState(run_state, run_state_->wait_state.get()); |
| const WaitManyResult wait_many_result = |
| - WaitMany(wait_state.handles, wait_state.wait_signals, deadline, nullptr); |
| + WaitMany(run_state_->wait_state->handles, |
| + run_state_->wait_state->wait_signals, deadline, nullptr); |
| const MojoResult result = wait_many_result.result; |
| bool did_work = true; |
| if (result == MOJO_RESULT_OK) { |
| @@ -184,18 +191,21 @@ bool MessagePumpMojo::DoInternalWork(const RunState& run_state, bool block) { |
| ReadMessageRaw(run_state.read_handle.get(), NULL, NULL, NULL, NULL, |
| MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); |
| } else { |
| - DCHECK(handlers_.find(wait_state.handles[wait_many_result.index]) != |
| + DCHECK(handlers_.find( |
| + run_state_->wait_state->handles[wait_many_result.index]) != |
| handlers_.end()); |
| WillSignalHandler(); |
| - handlers_[wait_state.handles[wait_many_result.index]] |
| - .handler->OnHandleReady(wait_state.handles[wait_many_result.index]); |
| + handlers_[run_state_->wait_state->handles[wait_many_result.index]] |
| + .handler->OnHandleReady( |
| + run_state_->wait_state->handles[wait_many_result.index]); |
| DidSignalHandler(); |
| } |
| } else { |
| switch (result) { |
| case MOJO_RESULT_CANCELLED: |
| case MOJO_RESULT_FAILED_PRECONDITION: |
| - RemoveInvalidHandle(wait_state, result, wait_many_result.index); |
| + RemoveInvalidHandle(*run_state_->wait_state, result, |
| + wait_many_result.index); |
| break; |
| case MOJO_RESULT_DEADLINE_EXCEEDED: |
| did_work = false; |
| @@ -206,13 +216,31 @@ bool MessagePumpMojo::DoInternalWork(const RunState& run_state, bool block) { |
| CHECK(false); |
| } |
| } |
| + // To keep memory usage under control, delete the WaitState object at the end |
| + // if it's vectors are too big by a factor of 2. Pre-C++11 doesn't have a way |
| + // to shrink vectors, so just get rid of them and re-create on the next round. |
| + if (run_state_->wait_state->handles.capacity() > |
| + 2 * run_state_->wait_state->handles.size() || |
| + run_state_->wait_state->wait_signals.capacity() > |
| + 2 * run_state_->wait_state->wait_signals.size()) { |
|
qsr
2015/05/28 09:33:48
Not sure the || is needed here. The 2 vectors shou
Anand Mistry (off Chromium)
2015/05/28 23:27:45
Good point. They should be in sync.
|
| + run_state_->wait_state.reset(); |
| + } |
| // Notify and remove any handlers whose time has expired. Make a copy in case |
| // someone tries to add/remove new handlers from notification. |
| - const HandleToHandler cloned_handlers(handlers_); |
| + if (!run_state_->cloned_handlers) { |
| + run_state_->cloned_handlers.reset(new HandleToHandlerList); |
| + run_state_->cloned_handlers->reserve(handlers_.size()); |
|
qsr
2015/05/28 09:33:48
Isn't the reserve always useful, whether the list
Anand Mistry (off Chromium)
2015/05/28 23:27:45
Done.
|
| + } else { |
| + run_state_->cloned_handlers->clear(); |
| + } |
| + for (const auto& handler : handlers_) { |
| + run_state_->cloned_handlers->push_back(handler); |
| + } |
| const base::TimeTicks now(internal::NowTicks()); |
| - for (HandleToHandler::const_iterator i = cloned_handlers.begin(); |
| - i != cloned_handlers.end(); ++i) { |
| + for (HandleToHandlerList::const_iterator i = |
| + run_state_->cloned_handlers->begin(); |
| + i != run_state_->cloned_handlers->end(); ++i) { |
| // Since we're iterating over a clone of the handlers, verify the handler is |
| // still valid before notifying. |
| if (!i->second.deadline.is_null() && i->second.deadline < now && |
| @@ -225,6 +253,10 @@ bool MessagePumpMojo::DoInternalWork(const RunState& run_state, bool block) { |
| did_work = true; |
| } |
| } |
| + if (run_state_->cloned_handlers->capacity() > |
| + 2 * run_state_->cloned_handlers->size()) { |
| + run_state_->cloned_handlers.reset(); |
| + } |
| return did_work; |
| } |
| @@ -256,18 +288,19 @@ void MessagePumpMojo::SignalControlPipe(const RunState& run_state) { |
| CHECK_EQ(MOJO_RESULT_OK, result); |
| } |
| -MessagePumpMojo::WaitState MessagePumpMojo::GetWaitState( |
| - const RunState& run_state) const { |
| - WaitState wait_state; |
| - wait_state.handles.push_back(run_state.read_handle.get()); |
| - wait_state.wait_signals.push_back(MOJO_HANDLE_SIGNAL_READABLE); |
| +void MessagePumpMojo::GetWaitState( |
| + const RunState& run_state, |
| + MessagePumpMojo::WaitState* wait_state) const { |
| + wait_state->handles.clear(); |
| + wait_state->wait_signals.clear(); |
|
qsr
2015/05/28 09:33:48
Do you want to use resize here?
Anand Mistry (off Chromium)
2015/05/28 23:27:45
Nah. That would change the logic here and I don't
qsr
2015/05/29 07:56:08
Sorry, I meant reserve, not resize. That will not
Anand Mistry (off Chromium)
2015/05/29 09:00:57
Done.
|
| + wait_state->handles.push_back(run_state.read_handle.get()); |
| + wait_state->wait_signals.push_back(MOJO_HANDLE_SIGNAL_READABLE); |
| for (HandleToHandler::const_iterator i = handlers_.begin(); |
| i != handlers_.end(); ++i) { |
| - wait_state.handles.push_back(i->first); |
| - wait_state.wait_signals.push_back(i->second.wait_signals); |
| + wait_state->handles.push_back(i->first); |
| + wait_state->wait_signals.push_back(i->second.wait_signals); |
| } |
| - return wait_state; |
| } |
| MojoDeadline MessagePumpMojo::GetDeadlineForWait( |