diff options
author | jbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-19 17:16:19 +0000 |
---|---|---|
committer | jbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-19 17:16:19 +0000 |
commit | c8867ff8d91f5be838ddb179bd08261807cc8cb2 (patch) | |
tree | ab0a2efb19bcb8a30a7b6dcbee1d743aa8f22a83 | |
parent | acf25bc074f81f41b0373c5c8ebe5ac599b2dcf0 (diff) | |
download | chromium_src-c8867ff8d91f5be838ddb179bd08261807cc8cb2.zip chromium_src-c8867ff8d91f5be838ddb179bd08261807cc8cb2.tar.gz chromium_src-c8867ff8d91f5be838ddb179bd08261807cc8cb2.tar.bz2 |
Updated event trace code to stop on buffer full condition for any child process. Added more trace events to show expensive blocking IPCs in renderer process.
BUG=79510
TEST=start trace in about:gpu; open some WebGL windows; when trace Buffer usage reaches 100%, verify that the trace is ended
Review URL: http://codereview.chromium.org/6870020
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82115 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/resources/gpu_internals/tracing_controller.js | 36 | ||||
-rw-r--r-- | chrome/browser/ui/webui/gpu_internals_ui.cc | 17 | ||||
-rw-r--r-- | content/browser/trace_controller.cc | 101 | ||||
-rw-r--r-- | content/browser/trace_controller.h | 31 | ||||
-rw-r--r-- | content/browser/trace_message_filter.cc | 43 | ||||
-rw-r--r-- | content/browser/trace_message_filter.h | 8 | ||||
-rw-r--r-- | content/common/child_process_messages.h | 10 | ||||
-rw-r--r-- | content/common/child_trace_message_filter.cc | 21 | ||||
-rw-r--r-- | content/common/child_trace_message_filter.h | 2 | ||||
-rw-r--r-- | content/common/gpu/gpu_command_buffer_stub.cc | 2 | ||||
-rw-r--r-- | content/renderer/command_buffer_proxy.cc | 2 | ||||
-rw-r--r-- | content/renderer/renderer_gl_context.cc | 1 | ||||
-rw-r--r-- | gpu/command_buffer/client/cmd_buffer_helper.cc | 3 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder.cc | 3 | ||||
-rw-r--r-- | gpu/common/gpu_trace_event.cc | 12 | ||||
-rw-r--r-- | gpu/common/gpu_trace_event.h | 9 |
16 files changed, 272 insertions, 29 deletions
diff --git a/chrome/browser/resources/gpu_internals/tracing_controller.js b/chrome/browser/resources/gpu_internals/tracing_controller.js index 25bffa9..7b67c122 100644 --- a/chrome/browser/resources/gpu_internals/tracing_controller.js +++ b/chrome/browser/resources/gpu_internals/tracing_controller.js @@ -17,6 +17,9 @@ cr.define('gpu', function() { this.statusDiv_ = document.createElement('div'); this.overlay_.appendChild(this.statusDiv_); + this.bufferPercentDiv_ = document.createElement('div'); + this.overlay_.appendChild(this.bufferPercentDiv_); + this.stopButton_ = document.createElement('button'); this.stopButton_.onclick = this.endTracing.bind(this); this.stopButton_.innerText = 'Stop tracing'; @@ -39,6 +42,24 @@ cr.define('gpu', function() { __proto__: cr.EventTarget.prototype, tracingEnabled_: false, + tracingEnding_: false, + + onRequestBufferPercentFullComplete: function(percent_full) { + if (!this.overlay_.visible) + return; + + window.setTimeout(this.beginRequestBufferPercentFull_.bind(this), 250); + + this.bufferPercentDiv_.textContent = 'Buffer usage: ' + + Math.round(100 * percent_full) + '%'; + }, + + /** + * Begin requesting the buffer fullness + */ + beginRequestBufferPercentFull_: function() { + chrome.send('beginRequestBufferPercentFull'); + }, /** * Called by info_view to empty the trace buffer @@ -53,10 +74,13 @@ cr.define('gpu', function() { this.tracingEnabled_ = true; console.log('Beginning to trace...'); + this.statusDiv_.textContent = 'Tracing active.'; this.traceEvents_ = []; - if (!browserBridge.debugMode) + if (!browserBridge.debugMode) { chrome.send('beginTracing'); + this.beginRequestBufferPercentFull_(); + } this.tracingEnabled_ = true; @@ -106,6 +130,7 @@ cr.define('gpu', function() { * Callbed by gpu c++ code when new GPU trace data arrives. */ onTraceDataCollected: function(events) { + this.statusDiv_.textContent = 'Processing trace...'; this.traceEvents_.push.apply(this.traceEvents_, events); }, @@ -114,10 +139,10 @@ cr.define('gpu', function() { */ endTracing: function() { if (!this.tracingEnabled_) throw new Error('Tracing not begun.'); + if (this.tracingEnding_) return; + this.tracingEnding_ = true; - window.removeEventListener('keydown', this.onKeydownBoundToThis_); - window.removeEventListener('keypress', this.onKeypressBoundToThis_); - + this.statusDiv_.textContent = 'Ending trace...'; console.log('Finishing trace'); this.statusDiv_.textContent = 'Downloading trace data...'; this.stopButton_.hidden = true; @@ -139,8 +164,11 @@ cr.define('gpu', function() { * Called by the browser when all processes complete tracing. */ onEndTracingComplete: function() { + window.removeEventListener('keydown', this.onKeydownBoundToThis_); + window.removeEventListener('keypress', this.onKeypressBoundToThis_); this.overlay_.visible = false; this.tracingEnabled_ = false; + this.tracingEnding_ = false; console.log('onEndTracingComplete p1 with ' + this.traceEvents_.length + ' events.'); var e = new cr.Event('traceEnded'); diff --git a/chrome/browser/ui/webui/gpu_internals_ui.cc b/chrome/browser/ui/webui/gpu_internals_ui.cc index fb7c9c2..dcfab3a 100644 --- a/chrome/browser/ui/webui/gpu_internals_ui.cc +++ b/chrome/browser/ui/webui/gpu_internals_ui.cc @@ -14,6 +14,7 @@ #include "base/memory/singleton.h" #include "base/message_loop.h" #include "base/path_service.h" +#include "base/scoped_ptr.h" #include "base/string_number_conversions.h" #include "base/string_piece.h" #include "base/utf_string_conversions.h" @@ -85,6 +86,7 @@ class GpuMessageHandler void OnEndTracingAsync(const ListValue* list); void OnBrowserBridgeInitialized(const ListValue* list); void OnCallAsync(const ListValue* list); + void OnBeginRequestBufferPercentFull(const ListValue* list); void OnLoadTraceFile(const ListValue* list); void OnSaveTraceFile(const ListValue* list); @@ -104,6 +106,7 @@ class GpuMessageHandler // TraceSubscriber implementation. virtual void OnEndTracingComplete(); virtual void OnTraceDataCollected(const std::string& json_events); + virtual void OnTraceBufferPercentFullReply(float percent_full); // Executes the javascript function |function_name| in the renderer, passing // it the argument |value|. @@ -232,6 +235,9 @@ void GpuMessageHandler::RegisterMessages() { "callAsync", NewCallback(this, &GpuMessageHandler::OnCallAsync)); web_ui_->RegisterMessageCallback( + "beginRequestBufferPercentFull", + NewCallback(this, &GpuMessageHandler::OnBeginRequestBufferPercentFull)); + web_ui_->RegisterMessageCallback( "loadTraceFile", NewCallback(this, &GpuMessageHandler::OnLoadTraceFile)); web_ui_->RegisterMessageCallback( @@ -286,6 +292,10 @@ void GpuMessageHandler::OnCallAsync(const ListValue* args) { } } +void GpuMessageHandler::OnBeginRequestBufferPercentFull(const ListValue* list) { + TraceController::GetInstance()->GetTraceBufferPercentFullAsync(this); +} + class ReadTraceFileTask : public Task { public: ReadTraceFileTask(TaskProxy* proxy, const FilePath& path) @@ -610,6 +620,13 @@ void GpuMessageHandler::OnTraceDataCollected(const std::string& json_events) { WideToUTF16Hack(javascript)); } +void GpuMessageHandler::OnTraceBufferPercentFullReply(float percent_full) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + web_ui_->CallJavascriptFunction( + "tracingController.onRequestBufferPercentFullComplete", + *scoped_ptr<Value>(Value::CreateDoubleValue(percent_full))); +} + } // namespace diff --git a/content/browser/trace_controller.cc b/content/browser/trace_controller.cc index e2e046a..5bf2efa 100644 --- a/content/browser/trace_controller.cc +++ b/content/browser/trace_controller.cc @@ -12,9 +12,11 @@ TraceController::TraceController() : - pending_ack_count_(0), - is_tracing_(false), - subscriber_(NULL) { + subscriber_(NULL), + pending_end_ack_count_(0), + pending_bpf_ack_count_(0), + maximum_bpf_(0.0f), + is_tracing_(false) { gpu::TraceLog::GetInstance()->SetOutputCallback( NewCallback(this, &TraceController::OnTraceDataCollected)); } @@ -59,11 +61,11 @@ bool TraceController::EndTracingAsync(TraceSubscriber* subscriber) { // is empty. In that case we can immediately tell the subscriber that tracing // has ended. To avoid recursive calls back to the subscriber, we will just // use the existing asynchronous OnEndTracingAck code. - // Count myself (local trace) in pending_ack_count_, acked below. - pending_ack_count_ = filters_.size() + 1; + // Count myself (local trace) in pending_end_ack_count_, acked below. + pending_end_ack_count_ = filters_.size() + 1; // Handle special case of zero child processes. - if (pending_ack_count_ == 1) { + if (pending_end_ack_count_ == 1) { // Ack asynchronously now, because we don't have any children to wait for. BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(this, &TraceController::OnEndTracingAck)); @@ -77,13 +79,41 @@ bool TraceController::EndTracingAsync(TraceSubscriber* subscriber) { return true; } +bool TraceController::GetTraceBufferPercentFullAsync( + TraceSubscriber* subscriber) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (!can_get_buffer_percent_full() || subscriber != subscriber_) + return false; + + maximum_bpf_ = 0.0f; + pending_bpf_ack_count_ = filters_.size() + 1; + + // Handle special case of zero child processes. + if (pending_bpf_ack_count_ == 1) { + // Ack asynchronously now, because we don't have any children to wait for. + float bpf = gpu::TraceLog::GetInstance()->GetBufferPercentFull(); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + NewRunnableMethod(this, + &TraceController::OnTraceBufferPercentFullReply, + bpf)); + } + + // Message all child processes. + for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { + it->get()->SendGetTraceBufferPercentFull(); + } + + return true; +} + void TraceController::CancelSubscriber(TraceSubscriber* subscriber) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (subscriber == subscriber_) { subscriber_ = NULL; // End tracing if necessary. - if (is_tracing_ && pending_ack_count_ == 0) + if (is_tracing_ && pending_end_ack_count_ == 0) EndTracingAsync(NULL); } } @@ -120,7 +150,10 @@ void TraceController::OnEndTracingAck() { return; } - if (--pending_ack_count_ == 0) { + if (pending_end_ack_count_ == 0) + return; + + if (--pending_end_ack_count_ == 0) { // All acks have been received. is_tracing_ = false; @@ -131,14 +164,14 @@ void TraceController::OnEndTracingAck() { gpu::TraceLog::GetInstance()->SetEnabled(false); // Trigger callback if one is set. - if (subscriber_ != NULL) { + if (subscriber_) { subscriber_->OnEndTracingComplete(); // Clear subscriber so that others can use TraceController. subscriber_ = NULL; } } - if (pending_ack_count_ == 1) { + if (pending_end_ack_count_ == 1) { // The last ack represents local trace, so we need to ack it now. Note that // this code only executes if there were child processes. BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, @@ -148,15 +181,59 @@ void TraceController::OnEndTracingAck() { void TraceController::OnTraceDataCollected(const std::string& data) { // OnTraceDataCollected may be called from any browser thread, either by the - // local event trace system or from child processes bia TraceMessageFilter. + // local event trace system or from child processes via TraceMessageFilter. if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(this, &TraceController::OnTraceDataCollected, data)); return; } - if (subscriber_) { + if (subscriber_) subscriber_->OnTraceDataCollected(data); +} + +void TraceController::OnTraceBufferFull() { + // OnTraceBufferFull may be called from any browser thread, either by the + // local event trace system or from child processes via TraceMessageFilter. + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + NewRunnableMethod(this, &TraceController::OnTraceBufferFull)); + return; + } + + // EndTracingAsync may return false if tracing is already in the process of + // being ended. That is ok. + EndTracingAsync(subscriber_); +} + +void TraceController::OnTraceBufferPercentFullReply(float percent_full) { + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + NewRunnableMethod(this, + &TraceController::OnTraceBufferPercentFullReply, + percent_full)); + return; + } + + if (pending_bpf_ack_count_ == 0) + return; + + maximum_bpf_ = (maximum_bpf_ > percent_full)? maximum_bpf_ : percent_full; + + if (--pending_bpf_ack_count_ == 0) { + // Trigger callback if one is set. + if (subscriber_) + subscriber_->OnTraceBufferPercentFullReply(maximum_bpf_); + } + + if (pending_bpf_ack_count_ == 1) { + // The last ack represents local trace, so we need to ack it now. Note that + // this code only executes if there were child processes. + float bpf = gpu::TraceLog::GetInstance()->GetBufferPercentFull(); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + NewRunnableMethod(this, + &TraceController::OnTraceBufferPercentFullReply, + bpf)); } } diff --git a/content/browser/trace_controller.h b/content/browser/trace_controller.h index ef30181..4308e82 100644 --- a/content/browser/trace_controller.h +++ b/content/browser/trace_controller.h @@ -21,6 +21,7 @@ class TraceSubscriber { public: virtual void OnEndTracingComplete() = 0; virtual void OnTraceDataCollected(const std::string& json_events) = 0; + virtual void OnTraceBufferPercentFullReply(float percent_full) {} }; // TraceController is used on the browser processes to enable/disable @@ -59,6 +60,17 @@ class TraceController { // EndTracingAsync will return false meaning it failed. bool EndTracingAsync(TraceSubscriber* subscriber); + // Get the maximum across processes of trace buffer percent full state. + // When the TraceBufferPercentFull value is determined, + // subscriber->OnTraceBufferPercentFullReply is called. + // When any child process reaches 100% full, the TraceController will end + // tracing, and call TraceSubscriber::OnEndTracingComplete. + // GetTraceBufferPercentFullAsync fails in the following conditions: + // trace is ending or disabled; + // a previous call to GetTraceBufferPercentFullAsync is pending; or + // the caller is not the current subscriber. + bool GetTraceBufferPercentFullAsync(TraceSubscriber* subscriber); + // Cancel the subscriber so that it will not be called when EndTracingAsync is // acked by all child processes. This will also call EndTracingAsync // internally if necessary. @@ -79,7 +91,14 @@ class TraceController { } bool can_end_tracing() const { - return is_tracing_ && pending_ack_count_ == 0; + return is_tracing_ && pending_end_ack_count_ == 0; + } + + // Can get Buffer Percent Full + bool can_get_buffer_percent_full() const { + return is_tracing_ && + pending_end_ack_count_ == 0 && + pending_bpf_ack_count_ == 0; } bool can_begin_tracing() const { return !is_tracing_; } @@ -92,11 +111,17 @@ class TraceController { void RemoveFilter(TraceMessageFilter* filter); void OnEndTracingAck(); void OnTraceDataCollected(const std::string& data); + void OnTraceBufferFull(); + void OnTraceBufferPercentFullReply(float percent_full); FilterMap filters_; - int pending_ack_count_; - bool is_tracing_; TraceSubscriber* subscriber_; + // Pending acks for EndTracingAsync: + int pending_end_ack_count_; + // Pending acks for GetTraceBufferPercentFullAsync: + int pending_bpf_ack_count_; + float maximum_bpf_; + bool is_tracing_; DISALLOW_COPY_AND_ASSIGN(TraceController); }; diff --git a/content/browser/trace_message_filter.cc b/content/browser/trace_message_filter.cc index 910b5eb..e23fc26 100644 --- a/content/browser/trace_message_filter.cc +++ b/content/browser/trace_message_filter.cc @@ -9,7 +9,8 @@ TraceMessageFilter::TraceMessageFilter() : - is_awaiting_ack_(false) { + is_awaiting_end_ack_(false), + is_awaiting_bpf_ack_(false) { } TraceMessageFilter::~TraceMessageFilter() { @@ -26,9 +27,12 @@ void TraceMessageFilter::OnChannelClosing() { // Always on IO thread (BrowserMessageFilter guarantee). BrowserMessageFilter::OnChannelClosing(); - if (is_awaiting_ack_) + if (is_awaiting_bpf_ack_) OnEndTracingAck(); + if (is_awaiting_end_ack_) + OnTraceBufferPercentFullReply(0.0f); + TraceController::GetInstance()->RemoveFilter(this); } @@ -40,6 +44,10 @@ bool TraceMessageFilter::OnMessageReceived(const IPC::Message& message, IPC_MESSAGE_HANDLER(ChildProcessHostMsg_EndTracingAck, OnEndTracingAck) IPC_MESSAGE_HANDLER(ChildProcessHostMsg_TraceDataCollected, OnTraceDataCollected) + IPC_MESSAGE_HANDLER(ChildProcessHostMsg_TraceBufferFull, + OnTraceBufferFull) + IPC_MESSAGE_HANDLER(ChildProcessHostMsg_TraceBufferPercentFullReply, + OnTraceBufferPercentFullReply) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP_EX() return handled; @@ -52,16 +60,23 @@ void TraceMessageFilter::SendBeginTracing() { void TraceMessageFilter::SendEndTracing() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - DCHECK(!is_awaiting_ack_); - is_awaiting_ack_ = true; + DCHECK(!is_awaiting_end_ack_); + is_awaiting_end_ack_ = true; Send(new ChildProcessMsg_EndTracing); } +void TraceMessageFilter::SendGetTraceBufferPercentFull() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(!is_awaiting_bpf_ack_); + is_awaiting_bpf_ack_ = true; + Send(new ChildProcessMsg_GetTraceBufferPercentFull); +} + void TraceMessageFilter::OnEndTracingAck() { - // is_awaiting_ack_ should always be true here, but check in case the child - // process is compromised. - if (is_awaiting_ack_) { - is_awaiting_ack_ = false; + // is_awaiting_end_ack_ should always be true here, but check in case the + // child process is compromised. + if (is_awaiting_end_ack_) { + is_awaiting_end_ack_ = false; TraceController::GetInstance()->OnEndTracingAck(); } } @@ -70,3 +85,15 @@ void TraceMessageFilter::OnTraceDataCollected(const std::string& data) { TraceController::GetInstance()->OnTraceDataCollected(data); } +void TraceMessageFilter::OnTraceBufferFull() { + TraceController::GetInstance()->OnTraceBufferFull(); +} + +void TraceMessageFilter::OnTraceBufferPercentFullReply(float percent_full) { + if (is_awaiting_bpf_ack_) { + is_awaiting_bpf_ack_ = false; + TraceController::GetInstance()->OnTraceBufferPercentFullReply( + percent_full); + } +} + diff --git a/content/browser/trace_message_filter.h b/content/browser/trace_message_filter.h index 3288094..31a62db 100644 --- a/content/browser/trace_message_filter.h +++ b/content/browser/trace_message_filter.h @@ -27,14 +27,18 @@ class TraceMessageFilter : public BrowserMessageFilter { void SendBeginTracing(); void SendEndTracing(); + void SendGetTraceBufferPercentFull(); private: // Message handlers. void OnEndTracingAck(); + void OnTraceBufferFull(); + void OnTraceBufferPercentFullReply(float percent_full); void OnTraceDataCollected(const std::string& data); - // Awaiting ack for previously sent TraceChangeStatus(false) - bool is_awaiting_ack_; + // Awaiting ack for previously sent SendEndTracing + bool is_awaiting_end_ack_; + bool is_awaiting_bpf_ack_; DISALLOW_COPY_AND_ASSIGN(TraceMessageFilter); }; diff --git a/content/common/child_process_messages.h b/content/common/child_process_messages.h index 6850da2..1d64bf6 100644 --- a/content/common/child_process_messages.h +++ b/content/common/child_process_messages.h @@ -31,6 +31,9 @@ IPC_MESSAGE_CONTROL0(ChildProcessMsg_BeginTracing) // Sent to all child processes to disable trace event recording. IPC_MESSAGE_CONTROL0(ChildProcessMsg_EndTracing) +// Sent to all child processes to get trace buffer fullness. +IPC_MESSAGE_CONTROL0(ChildProcessMsg_GetTraceBufferPercentFull) + //////////////////////////////////////////////////////////////////////////////// // Messages sent from the child process to the browser. @@ -39,10 +42,17 @@ IPC_MESSAGE_CONTROL0(ChildProcessHostMsg_ShutdownRequest) // Reply from child processes acking ChildProcessMsg_TraceChangeStatus(false). IPC_MESSAGE_CONTROL0(ChildProcessHostMsg_EndTracingAck) +// Sent if the trace buffer becomes full. +IPC_MESSAGE_CONTROL0(ChildProcessHostMsg_TraceBufferFull) + // Child processes send trace data back in JSON chunks. IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_TraceDataCollected, std::string /*json trace data*/) +// Reply to ChildProcessMsg_GetTraceBufferPercentFull. +IPC_MESSAGE_CONTROL1(ChildProcessHostMsg_TraceBufferPercentFullReply, + float /*trace buffer percent full*/) + // NaCl's 64 bit Windows build only links with a bare-minimum number of // libraries, and GURL isn't one of them. #if !defined(NACL_WIN64) diff --git a/content/common/child_trace_message_filter.cc b/content/common/child_trace_message_filter.cc index 356e423..ccc2b03 100644 --- a/content/common/child_trace_message_filter.cc +++ b/content/common/child_trace_message_filter.cc @@ -15,12 +15,15 @@ ChildTraceMessageFilter::ChildTraceMessageFilter() : channel_(NULL) { ChildTraceMessageFilter::~ChildTraceMessageFilter() { gpu::TraceLog::GetInstance()->SetOutputCallback(NULL); + gpu::TraceLog::GetInstance()->SetBufferFullCallback(NULL); } void ChildTraceMessageFilter::OnFilterAdded(IPC::Channel* channel) { channel_ = channel; gpu::TraceLog::GetInstance()->SetOutputCallback( NewCallback(this, &ChildTraceMessageFilter::OnTraceDataCollected)); + gpu::TraceLog::GetInstance()->SetBufferFullCallback( + NewCallback(this, &ChildTraceMessageFilter::OnTraceBufferFull)); } bool ChildTraceMessageFilter::OnMessageReceived(const IPC::Message& message) { @@ -28,6 +31,8 @@ bool ChildTraceMessageFilter::OnMessageReceived(const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(ChildTraceMessageFilter, message) IPC_MESSAGE_HANDLER(ChildProcessMsg_BeginTracing, OnBeginTracing) IPC_MESSAGE_HANDLER(ChildProcessMsg_EndTracing, OnEndTracing) + IPC_MESSAGE_HANDLER(ChildProcessMsg_GetTraceBufferPercentFull, + OnGetTraceBufferPercentFull) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -48,6 +53,12 @@ void ChildTraceMessageFilter::OnEndTracing() { channel_->Send(new ChildProcessHostMsg_EndTracingAck); } +void ChildTraceMessageFilter::OnGetTraceBufferPercentFull() { + float bpf = gpu::TraceLog::GetInstance()->GetBufferPercentFull(); + + channel_->Send(new ChildProcessHostMsg_TraceBufferPercentFullReply(bpf)); +} + void ChildTraceMessageFilter::OnTraceDataCollected(const std::string& data) { if (MessageLoop::current() != ChildProcess::current()->io_message_loop()) { ChildProcess::current()->io_message_loop()->PostTask(FROM_HERE, @@ -59,3 +70,13 @@ void ChildTraceMessageFilter::OnTraceDataCollected(const std::string& data) { channel_->Send(new ChildProcessHostMsg_TraceDataCollected(data)); } +void ChildTraceMessageFilter::OnTraceBufferFull() { + if (MessageLoop::current() != ChildProcess::current()->io_message_loop()) { + ChildProcess::current()->io_message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(this, &ChildTraceMessageFilter::OnTraceBufferFull)); + return; + } + + channel_->Send(new ChildProcessHostMsg_TraceBufferFull()); +} + diff --git a/content/common/child_trace_message_filter.h b/content/common/child_trace_message_filter.h index 24d5593..ae74ff5e 100644 --- a/content/common/child_trace_message_filter.h +++ b/content/common/child_trace_message_filter.h @@ -24,9 +24,11 @@ class ChildTraceMessageFilter : public IPC::ChannelProxy::MessageFilter { // Message handlers. void OnBeginTracing(); void OnEndTracing(); + void OnGetTraceBufferPercentFull(); // Callback from trace subsystem. void OnTraceDataCollected(const std::string& data); + void OnTraceBufferFull(); IPC::Channel* channel_; diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index 42e086d..b767b24 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc @@ -306,6 +306,7 @@ void GpuCommandBufferStub::OnAsyncGetState() { void GpuCommandBufferStub::OnFlush(int32 put_offset, gpu::CommandBuffer::State* state) { + GPU_TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnFlush"); *state = command_buffer_->FlushSync(put_offset); if (state->error == gpu::error::kLostContext && gfx::GLContext::LosesAllContextsOnContextLost()) @@ -313,6 +314,7 @@ void GpuCommandBufferStub::OnFlush(int32 put_offset, } void GpuCommandBufferStub::OnAsyncFlush(int32 put_offset) { + GPU_TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnAsyncFlush"); gpu::CommandBuffer::State state = command_buffer_->FlushSync(put_offset); if (state.error == gpu::error::kLostContext && gfx::GLContext::LosesAllContextsOnContextLost()) diff --git a/content/renderer/command_buffer_proxy.cc b/content/renderer/command_buffer_proxy.cc index e4d3734..95bcb4c 100644 --- a/content/renderer/command_buffer_proxy.cc +++ b/content/renderer/command_buffer_proxy.cc @@ -14,6 +14,7 @@ #include "content/renderer/plugin_channel_host.h" #include "content/renderer/render_thread.h" #include "gpu/command_buffer/common/cmd_buffer_common.h" +#include "gpu/common/gpu_trace_event.h" #include "ui/gfx/size.h" using gpu::Buffer; @@ -150,6 +151,7 @@ void CommandBufferProxy::Flush(int32 put_offset) { } gpu::CommandBuffer::State CommandBufferProxy::FlushSync(int32 put_offset) { + GPU_TRACE_EVENT0("gpu", "CommandBufferProxy::FlushSync"); // Send will flag state with lost context if IPC fails. if (last_state_.error == gpu::error::kNoError) { Send(new GpuCommandBufferMsg_Flush(route_id_, diff --git a/content/renderer/renderer_gl_context.cc b/content/renderer/renderer_gl_context.cc index f913a3b..0fea88ce 100644 --- a/content/renderer/renderer_gl_context.cc +++ b/content/renderer/renderer_gl_context.cc @@ -372,6 +372,7 @@ bool RendererGLContext::Initialize(bool onscreen, const int32* attrib_list, const GURL& active_url) { DCHECK(size.width() >= 0 && size.height() >= 0); + GPU_TRACE_EVENT0("gpu", "RendererGLContext::Initialize"); if (channel_->state() != GpuChannelHost::kConnected) return false; diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc index d3eaca1..3f7d94e 100644 --- a/gpu/command_buffer/client/cmd_buffer_helper.cc +++ b/gpu/command_buffer/client/cmd_buffer_helper.cc @@ -62,6 +62,7 @@ void CommandBufferHelper::Flush() { // Calls Flush() and then waits until the buffer is empty. Break early if the // error is set. bool CommandBufferHelper::Finish() { + GPU_TRACE_EVENT0("gpu", "CommandBufferHelper::Finish"); do { // Do not loop forever if the flush fails, meaning the command buffer reader // has shutdown. @@ -83,6 +84,7 @@ int32 CommandBufferHelper::InsertToken() { cmd::SetToken& cmd = GetCmdSpace<cmd::SetToken>(); cmd.Init(token_); if (token_ == 0) { + GPU_TRACE_EVENT0("gpu", "CommandBufferHelper::InsertToken(wrapped)"); // we wrapped Finish(); GPU_DCHECK_EQ(token_, last_token_read_); @@ -93,6 +95,7 @@ int32 CommandBufferHelper::InsertToken() { // Waits until the current token value is greater or equal to the value passed // in argument. void CommandBufferHelper::WaitForToken(int32 token) { + GPU_TRACE_EVENT0("gpu", "CommandBufferHelper::WaitForToken"); // Return immediately if corresponding InsertToken failed. if (token < 0) return; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 9e14183..db58132 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -34,6 +34,7 @@ #include "gpu/command_buffer/service/shader_manager.h" #include "gpu/command_buffer/service/shader_translator.h" #include "gpu/command_buffer/service/texture_manager.h" +#include "gpu/common/gpu_trace_event.h" #include "gpu/GLES2/gles2_command_buffer.h" #include "ui/gfx/gl/gl_context.h" #include "ui/gfx/gl/gl_implementation.h" @@ -6387,6 +6388,7 @@ error::Error GLES2DecoderImpl::HandleSwapBuffers( error::Error GLES2DecoderImpl::HandleSetLatchCHROMIUM( uint32 immediate_data_size, const gles2::SetLatchCHROMIUM& c) { + GPU_TRACE_EVENT0("gpu", "SetLatch"); // Ensure the side effects of previous commands are visible to other contexts. // There is no need to do this for ANGLE because it uses a // single D3D device for all contexts. @@ -6413,6 +6415,7 @@ error::Error GLES2DecoderImpl::HandleSetLatchCHROMIUM( error::Error GLES2DecoderImpl::HandleWaitLatchCHROMIUM( uint32 immediate_data_size, const gles2::WaitLatchCHROMIUM& c) { + GPU_TRACE_EVENT0("gpu", "WaitLatch"); int32 shm_id = gpu::kLatchSharedMemoryId; uint32 latch_id = c.latch_id; uint32 shm_offset = 0; diff --git a/gpu/common/gpu_trace_event.cc b/gpu/common/gpu_trace_event.cc index af6c16e..882b0b8 100644 --- a/gpu/common/gpu_trace_event.cc +++ b/gpu/common/gpu_trace_event.cc @@ -169,6 +169,10 @@ void TraceLog::SetEnabled(bool enabled) { } } +float TraceLog::GetBufferPercentFull() const { + return (float)((double)logged_events_.size()/(double)TRACE_EVENT_BUFFER_SIZE); +} + void TraceLog::SetOutputCallback(TraceLog::OutputCallback* cb) { AutoLock lock(lock_); if (enabled_) { @@ -177,6 +181,11 @@ void TraceLog::SetOutputCallback(TraceLog::OutputCallback* cb) { output_callback_.reset(cb); } +void TraceLog::SetBufferFullCallback(TraceLog::BufferFullCallback* cb) { + AutoLock lock(lock_); + buffer_full_callback_.reset(cb); +} + void TraceLog::AddRemotelyCollectedData(const std::string& json_events) { AutoLock lock(lock_); if (output_callback_.get()) @@ -229,6 +238,9 @@ void TraceLog::AddTraceEvent(TraceEventPhase phase, event.argNames[1] = arg2name; event.argValues[1] = arg2name ? arg2val : ""; COMPILE_ASSERT(TRACE_MAX_NUM_ARGS == 2, TraceEvent_arc_count_out_of_sync); + if (logged_events_.size() == TRACE_EVENT_BUFFER_SIZE && + buffer_full_callback_.get()) + buffer_full_callback_->Run(); } } // namespace gpu diff --git a/gpu/common/gpu_trace_event.h b/gpu/common/gpu_trace_event.h index 8e4a176..2ed9b9d 100644 --- a/gpu/common/gpu_trace_event.h +++ b/gpu/common/gpu_trace_event.h @@ -214,12 +214,20 @@ class TraceLog { // implicitly controls the global logging state. void SetEnabled(bool enabled); + float GetBufferPercentFull() const; + // When enough events are collected, they are handed (in bulk) to // the output callback. If no callback is set, the output will be // silently dropped. typedef Callback1<const std::string& /* json_events */>::Type OutputCallback; void SetOutputCallback(OutputCallback* cb); + // The trace buffer does not flush dynamically, so when it fills up, + // subsequent trace events will be dropped. This callback is generated when + // the trace buffer is full. + typedef Callback0::Type BufferFullCallback; + void SetBufferFullCallback(BufferFullCallback* cb); + // Forwards data collected by a child process to the registered // output callback. void AddRemotelyCollectedData(const std::string& json_events); @@ -253,6 +261,7 @@ class TraceLog { bool enabled_; ScopedVector<TraceCategory> categories_; scoped_ptr<OutputCallback> output_callback_; + scoped_ptr<BufferFullCallback> buffer_full_callback_; std::vector<TraceEvent> logged_events_; DISALLOW_COPY_AND_ASSIGN(TraceLog); |