summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 17:16:19 +0000
committerjbates@chromium.org <jbates@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 17:16:19 +0000
commitc8867ff8d91f5be838ddb179bd08261807cc8cb2 (patch)
treeab0a2efb19bcb8a30a7b6dcbee1d743aa8f22a83
parentacf25bc074f81f41b0373c5c8ebe5ac599b2dcf0 (diff)
downloadchromium_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.js36
-rw-r--r--chrome/browser/ui/webui/gpu_internals_ui.cc17
-rw-r--r--content/browser/trace_controller.cc101
-rw-r--r--content/browser/trace_controller.h31
-rw-r--r--content/browser/trace_message_filter.cc43
-rw-r--r--content/browser/trace_message_filter.h8
-rw-r--r--content/common/child_process_messages.h10
-rw-r--r--content/common/child_trace_message_filter.cc21
-rw-r--r--content/common/child_trace_message_filter.h2
-rw-r--r--content/common/gpu/gpu_command_buffer_stub.cc2
-rw-r--r--content/renderer/command_buffer_proxy.cc2
-rw-r--r--content/renderer/renderer_gl_context.cc1
-rw-r--r--gpu/command_buffer/client/cmd_buffer_helper.cc3
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc3
-rw-r--r--gpu/common/gpu_trace_event.cc12
-rw-r--r--gpu/common/gpu_trace_event.h9
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);