diff options
author | loislo <loislo@chromium.org> | 2014-12-17 02:21:30 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-12-17 10:22:20 +0000 |
commit | d58e06aafd6572e681f9d30f313bf5393db9f2bc (patch) | |
tree | d449dffe0d7b5fda8ccb1eb512a4e81b3b27b9f8 /base | |
parent | 8074902d32c9f36d3be05610229f4041d1bc5b80 (diff) | |
download | chromium_src-d58e06aafd6572e681f9d30f313bf5393db9f2bc.zip chromium_src-d58e06aafd6572e681f9d30f313bf5393db9f2bc.tar.gz chromium_src-d58e06aafd6572e681f9d30f313bf5393db9f2bc.tar.bz2 |
DevTools: Parallelize trace messages serialization.
Move serialization into a worker thread. As a result
IO thread will be able to send messages to the browser.
The original implementation did serialization on IO thread
and was not able to send the messages because ipc had
is_blocked_on_write_ = true and had no chance to check
the actual state of the channel. So the messages were
collected in output_queue. Also the messages could be quite
big and could block the IO thread for a long time.
BUG=
Review URL: https://codereview.chromium.org/750183008
Cr-Commit-Position: refs/heads/master@{#308773}
Diffstat (limited to 'base')
-rw-r--r-- | base/debug/trace_event_impl.cc | 31 | ||||
-rw-r--r-- | base/debug/trace_event_impl.h | 10 |
2 files changed, 29 insertions, 12 deletions
diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc index 4591286..47baf0b 100644 --- a/base/debug/trace_event_impl.cc +++ b/base/debug/trace_event_impl.cc @@ -32,6 +32,7 @@ #include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/threading/platform_thread.h" #include "base/threading/thread_id_name_manager.h" +#include "base/threading/worker_pool.h" #include "base/time/time.h" #if defined(OS_WIN) @@ -73,7 +74,7 @@ const size_t kTraceEventVectorBigBufferChunks = 512000000 / kTraceBufferChunkSize; const size_t kTraceEventVectorBufferChunks = 256000 / kTraceBufferChunkSize; const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4; -const size_t kTraceEventBatchChunks = 1000 / kTraceBufferChunkSize; +const size_t kTraceEventBufferSizeInBytes = 10 * 1024 * 1024; // Can store results for 30 seconds with 1 ms sampling interval. const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize; // ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events. @@ -1211,7 +1212,8 @@ TraceLog::TraceLog() event_callback_category_filter_( CategoryFilter::kDefaultCategoryFilterString), thread_shared_chunk_index_(0), - generation_(0) { + generation_(0), + use_worker_thread_(false) { // Trace is enabled or disabled on one thread while other threads are // accessing the enabled flag. We don't care whether edge-case events are // traced or not, so we allow races on the enabled flag to keep the trace @@ -1684,7 +1686,9 @@ void TraceLog::SetEventCallbackDisabled() { // - The message loop will be removed from thread_message_loops_; // If this is the last message loop, finish the flush; // 4. If any thread hasn't finish its flush in time, finish the flush. -void TraceLog::Flush(const TraceLog::OutputCallback& cb) { +void TraceLog::Flush(const TraceLog::OutputCallback& cb, + bool use_worker_thread) { + use_worker_thread_ = use_worker_thread; if (IsEnabled()) { // Can't flush when tracing is enabled because otherwise PostTask would // - generate more trace events; @@ -1738,6 +1742,7 @@ void TraceLog::Flush(const TraceLog::OutputCallback& cb) { FinishFlush(generation); } +// Usually it runs on a different thread. void TraceLog::ConvertTraceEventsToTraceFormat( scoped_ptr<TraceBuffer> logged_events, const TraceLog::OutputCallback& flush_output_callback) { @@ -1752,19 +1757,17 @@ void TraceLog::ConvertTraceEventsToTraceFormat( scoped_refptr<RefCountedString> json_events_str_ptr = new RefCountedString(); - for (size_t i = 0; i < kTraceEventBatchChunks; ++i) { + while (json_events_str_ptr->size() < kTraceEventBufferSizeInBytes) { const TraceBufferChunk* chunk = logged_events->NextChunk(); - if (!chunk) { - has_more_events = false; + has_more_events = chunk != NULL; + if (!chunk) break; - } for (size_t j = 0; j < chunk->size(); ++j) { - if (i > 0 || j > 0) + if (json_events_str_ptr->size()) json_events_str_ptr->data().append(","); chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data())); } } - flush_output_callback.Run(json_events_str_ptr, has_more_events); } while (has_more_events); } @@ -1788,6 +1791,16 @@ void TraceLog::FinishFlush(int generation) { flush_output_callback_.Reset(); } + if (use_worker_thread_ && + WorkerPool::PostTask( + FROM_HERE, + Bind(&TraceLog::ConvertTraceEventsToTraceFormat, + Passed(&previous_logged_events), + flush_output_callback), + true)) { + return; + } + ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(), flush_output_callback); } diff --git a/base/debug/trace_event_impl.h b/base/debug/trace_event_impl.h index c80826c..77a9ada 100644 --- a/base/debug/trace_event_impl.h +++ b/base/debug/trace_event_impl.h @@ -538,10 +538,11 @@ class BASE_EXPORT TraceLog { // Due to the implementation of thread-local buffers, flush can't be // done when tracing is enabled. If called when tracing is enabled, the // callback will be called directly with (empty_string, false) to indicate - // the end of this unsuccessful flush. + // the end of this unsuccessful flush. Flush does the serialization + // on the same thread if the caller doesn't set use_worker_thread explicitly. typedef base::Callback<void(const scoped_refptr<base::RefCountedString>&, bool has_more_events)> OutputCallback; - void Flush(const OutputCallback& cb); + void Flush(const OutputCallback& cb, bool use_worker_thread = false); void FlushButLeaveBufferIntact(const OutputCallback& flush_output_callback); // Called by TRACE_EVENT* macros, don't call this directly. @@ -710,7 +711,9 @@ class BASE_EXPORT TraceLog { // |generation| is used in the following callbacks to check if the callback // is called for the flush of the current |logged_events_|. void FlushCurrentThread(int generation); - void ConvertTraceEventsToTraceFormat(scoped_ptr<TraceBuffer> logged_events, + // Usually it runs on a different thread. + static void ConvertTraceEventsToTraceFormat( + scoped_ptr<TraceBuffer> logged_events, const TraceLog::OutputCallback& flush_output_callback); void FinishFlush(int generation); void OnFlushTimeout(int generation); @@ -804,6 +807,7 @@ class BASE_EXPORT TraceLog { OutputCallback flush_output_callback_; scoped_refptr<MessageLoopProxy> flush_message_loop_proxy_; subtle::AtomicWord generation_; + bool use_worker_thread_; DISALLOW_COPY_AND_ASSIGN(TraceLog); }; |