OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/trace_event/trace_event_impl.h" | 5 #include "base/trace_event/trace_event_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/base_switches.h" | 9 #include "base/base_switches.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "base/strings/string_tokenizer.h" | 23 #include "base/strings/string_tokenizer.h" |
24 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
25 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
26 #include "base/strings/utf_string_conversions.h" | 26 #include "base/strings/utf_string_conversions.h" |
27 #include "base/synchronization/cancellation_flag.h" | 27 #include "base/synchronization/cancellation_flag.h" |
28 #include "base/synchronization/waitable_event.h" | 28 #include "base/synchronization/waitable_event.h" |
29 #include "base/sys_info.h" | 29 #include "base/sys_info.h" |
30 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 30 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
31 #include "base/threading/platform_thread.h" | 31 #include "base/threading/platform_thread.h" |
32 #include "base/threading/thread_id_name_manager.h" | 32 #include "base/threading/thread_id_name_manager.h" |
| 33 #include "base/threading/worker_pool.h" |
33 #include "base/time/time.h" | 34 #include "base/time/time.h" |
34 #include "base/trace_event/trace_event.h" | 35 #include "base/trace_event/trace_event.h" |
35 #include "base/trace_event/trace_event_synthetic_delay.h" | 36 #include "base/trace_event/trace_event_synthetic_delay.h" |
36 | 37 |
37 #if defined(OS_WIN) | 38 #if defined(OS_WIN) |
38 #include "base/trace_event/trace_event_win.h" | 39 #include "base/trace_event/trace_event_win.h" |
39 #endif | 40 #endif |
40 | 41 |
41 class DeleteTraceLogForTesting { | 42 class DeleteTraceLogForTesting { |
42 public: | 43 public: |
(...skipping 23 matching lines...) Expand all Loading... |
66 const char kEnableSampling[] = "enable-sampling"; | 67 const char kEnableSampling[] = "enable-sampling"; |
67 const char kEnableSystrace[] = "enable-systrace"; | 68 const char kEnableSystrace[] = "enable-systrace"; |
68 | 69 |
69 // Controls the number of trace events we will buffer in-memory | 70 // Controls the number of trace events we will buffer in-memory |
70 // before throwing them away. | 71 // before throwing them away. |
71 const size_t kTraceBufferChunkSize = TraceBufferChunk::kTraceBufferChunkSize; | 72 const size_t kTraceBufferChunkSize = TraceBufferChunk::kTraceBufferChunkSize; |
72 const size_t kTraceEventVectorBigBufferChunks = | 73 const size_t kTraceEventVectorBigBufferChunks = |
73 512000000 / kTraceBufferChunkSize; | 74 512000000 / kTraceBufferChunkSize; |
74 const size_t kTraceEventVectorBufferChunks = 256000 / kTraceBufferChunkSize; | 75 const size_t kTraceEventVectorBufferChunks = 256000 / kTraceBufferChunkSize; |
75 const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4; | 76 const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4; |
76 const size_t kTraceEventBatchChunks = 1000 / kTraceBufferChunkSize; | 77 const size_t kTraceEventBufferSizeInBytes = 100 * 1024; |
77 // Can store results for 30 seconds with 1 ms sampling interval. | 78 // Can store results for 30 seconds with 1 ms sampling interval. |
78 const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize; | 79 const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize; |
79 // ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events. | 80 // ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events. |
80 const size_t kEchoToConsoleTraceEventBufferChunks = 256; | 81 const size_t kEchoToConsoleTraceEventBufferChunks = 256; |
81 | 82 |
82 const int kThreadFlushTimeoutMs = 3000; | 83 const int kThreadFlushTimeoutMs = 3000; |
83 | 84 |
84 #if !defined(OS_NACL) | 85 #if !defined(OS_NACL) |
85 // These categories will cause deadlock when ECHO_TO_CONSOLE. crbug.com/325575. | 86 // These categories will cause deadlock when ECHO_TO_CONSOLE. crbug.com/325575. |
86 const char kEchoToConsoleCategoryFilter[] = "-ipc,-task"; | 87 const char kEchoToConsoleCategoryFilter[] = "-ipc,-task"; |
(...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1201 process_sort_index_(0), | 1202 process_sort_index_(0), |
1202 process_id_hash_(0), | 1203 process_id_hash_(0), |
1203 process_id_(0), | 1204 process_id_(0), |
1204 watch_category_(0), | 1205 watch_category_(0), |
1205 trace_options_(kInternalRecordUntilFull), | 1206 trace_options_(kInternalRecordUntilFull), |
1206 sampling_thread_handle_(0), | 1207 sampling_thread_handle_(0), |
1207 category_filter_(CategoryFilter::kDefaultCategoryFilterString), | 1208 category_filter_(CategoryFilter::kDefaultCategoryFilterString), |
1208 event_callback_category_filter_( | 1209 event_callback_category_filter_( |
1209 CategoryFilter::kDefaultCategoryFilterString), | 1210 CategoryFilter::kDefaultCategoryFilterString), |
1210 thread_shared_chunk_index_(0), | 1211 thread_shared_chunk_index_(0), |
1211 generation_(0) { | 1212 generation_(0), |
| 1213 use_worker_thread_(false) { |
1212 // Trace is enabled or disabled on one thread while other threads are | 1214 // Trace is enabled or disabled on one thread while other threads are |
1213 // accessing the enabled flag. We don't care whether edge-case events are | 1215 // accessing the enabled flag. We don't care whether edge-case events are |
1214 // traced or not, so we allow races on the enabled flag to keep the trace | 1216 // traced or not, so we allow races on the enabled flag to keep the trace |
1215 // macros fast. | 1217 // macros fast. |
1216 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots: | 1218 // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots: |
1217 // ANNOTATE_BENIGN_RACE_SIZED(g_category_group_enabled, | 1219 // ANNOTATE_BENIGN_RACE_SIZED(g_category_group_enabled, |
1218 // sizeof(g_category_group_enabled), | 1220 // sizeof(g_category_group_enabled), |
1219 // "trace_event category enabled"); | 1221 // "trace_event category enabled"); |
1220 for (int i = 0; i < MAX_CATEGORY_GROUPS; ++i) { | 1222 for (int i = 0; i < MAX_CATEGORY_GROUPS; ++i) { |
1221 ANNOTATE_BENIGN_RACE(&g_category_group_enabled[i], | 1223 ANNOTATE_BENIGN_RACE(&g_category_group_enabled[i], |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1674 // Flush() works as the following: | 1676 // Flush() works as the following: |
1675 // 1. Flush() is called in threadA whose message loop is saved in | 1677 // 1. Flush() is called in threadA whose message loop is saved in |
1676 // flush_message_loop_proxy_; | 1678 // flush_message_loop_proxy_; |
1677 // 2. If thread_message_loops_ is not empty, threadA posts task to each message | 1679 // 2. If thread_message_loops_ is not empty, threadA posts task to each message |
1678 // loop to flush the thread local buffers; otherwise finish the flush; | 1680 // loop to flush the thread local buffers; otherwise finish the flush; |
1679 // 3. FlushCurrentThread() deletes the thread local event buffer: | 1681 // 3. FlushCurrentThread() deletes the thread local event buffer: |
1680 // - The last batch of events of the thread are flushed into the main buffer; | 1682 // - The last batch of events of the thread are flushed into the main buffer; |
1681 // - The message loop will be removed from thread_message_loops_; | 1683 // - The message loop will be removed from thread_message_loops_; |
1682 // If this is the last message loop, finish the flush; | 1684 // If this is the last message loop, finish the flush; |
1683 // 4. If any thread hasn't finish its flush in time, finish the flush. | 1685 // 4. If any thread hasn't finish its flush in time, finish the flush. |
1684 void TraceLog::Flush(const TraceLog::OutputCallback& cb) { | 1686 void TraceLog::Flush(const TraceLog::OutputCallback& cb, |
| 1687 bool use_worker_thread) { |
| 1688 use_worker_thread_ = use_worker_thread; |
1685 if (IsEnabled()) { | 1689 if (IsEnabled()) { |
1686 // Can't flush when tracing is enabled because otherwise PostTask would | 1690 // Can't flush when tracing is enabled because otherwise PostTask would |
1687 // - generate more trace events; | 1691 // - generate more trace events; |
1688 // - deschedule the calling thread on some platforms causing inaccurate | 1692 // - deschedule the calling thread on some platforms causing inaccurate |
1689 // timing of the trace events. | 1693 // timing of the trace events. |
1690 scoped_refptr<RefCountedString> empty_result = new RefCountedString; | 1694 scoped_refptr<RefCountedString> empty_result = new RefCountedString; |
1691 if (!cb.is_null()) | 1695 if (!cb.is_null()) |
1692 cb.Run(empty_result, false); | 1696 cb.Run(empty_result, false); |
1693 LOG(WARNING) << "Ignored TraceLog::Flush called when tracing is enabled"; | 1697 LOG(WARNING) << "Ignored TraceLog::Flush called when tracing is enabled"; |
1694 return; | 1698 return; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1728 flush_message_loop_proxy_->PostDelayedTask( | 1732 flush_message_loop_proxy_->PostDelayedTask( |
1729 FROM_HERE, | 1733 FROM_HERE, |
1730 Bind(&TraceLog::OnFlushTimeout, Unretained(this), generation), | 1734 Bind(&TraceLog::OnFlushTimeout, Unretained(this), generation), |
1731 TimeDelta::FromMilliseconds(kThreadFlushTimeoutMs)); | 1735 TimeDelta::FromMilliseconds(kThreadFlushTimeoutMs)); |
1732 return; | 1736 return; |
1733 } | 1737 } |
1734 | 1738 |
1735 FinishFlush(generation); | 1739 FinishFlush(generation); |
1736 } | 1740 } |
1737 | 1741 |
| 1742 // Usually it runs on a different thread. |
1738 void TraceLog::ConvertTraceEventsToTraceFormat( | 1743 void TraceLog::ConvertTraceEventsToTraceFormat( |
1739 scoped_ptr<TraceBuffer> logged_events, | 1744 scoped_ptr<TraceBuffer> logged_events, |
1740 const TraceLog::OutputCallback& flush_output_callback) { | 1745 const TraceLog::OutputCallback& flush_output_callback) { |
1741 | 1746 |
1742 if (flush_output_callback.is_null()) | 1747 if (flush_output_callback.is_null()) |
1743 return; | 1748 return; |
1744 | 1749 |
1745 // The callback need to be called at least once even if there is no events | 1750 // The callback need to be called at least once even if there is no events |
1746 // to let the caller know the completion of flush. | 1751 // to let the caller know the completion of flush. |
1747 bool has_more_events = true; | 1752 bool has_more_events = true; |
1748 do { | 1753 do { |
1749 scoped_refptr<RefCountedString> json_events_str_ptr = | 1754 scoped_refptr<RefCountedString> json_events_str_ptr = |
1750 new RefCountedString(); | 1755 new RefCountedString(); |
1751 | 1756 |
1752 for (size_t i = 0; i < kTraceEventBatchChunks; ++i) { | 1757 while (json_events_str_ptr->size() < kTraceEventBufferSizeInBytes) { |
1753 const TraceBufferChunk* chunk = logged_events->NextChunk(); | 1758 const TraceBufferChunk* chunk = logged_events->NextChunk(); |
1754 if (!chunk) { | 1759 has_more_events = chunk != NULL; |
1755 has_more_events = false; | 1760 if (!chunk) |
1756 break; | 1761 break; |
1757 } | |
1758 for (size_t j = 0; j < chunk->size(); ++j) { | 1762 for (size_t j = 0; j < chunk->size(); ++j) { |
1759 if (i > 0 || j > 0) | 1763 if (json_events_str_ptr->size()) |
1760 json_events_str_ptr->data().append(",\n"); | 1764 json_events_str_ptr->data().append(",\n"); |
1761 chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data())); | 1765 chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data())); |
1762 } | 1766 } |
1763 } | 1767 } |
1764 | |
1765 flush_output_callback.Run(json_events_str_ptr, has_more_events); | 1768 flush_output_callback.Run(json_events_str_ptr, has_more_events); |
1766 } while (has_more_events); | 1769 } while (has_more_events); |
1767 } | 1770 } |
1768 | 1771 |
1769 void TraceLog::FinishFlush(int generation) { | 1772 void TraceLog::FinishFlush(int generation) { |
1770 scoped_ptr<TraceBuffer> previous_logged_events; | 1773 scoped_ptr<TraceBuffer> previous_logged_events; |
1771 OutputCallback flush_output_callback; | 1774 OutputCallback flush_output_callback; |
1772 | 1775 |
1773 if (!CheckGeneration(generation)) | 1776 if (!CheckGeneration(generation)) |
1774 return; | 1777 return; |
1775 | 1778 |
1776 { | 1779 { |
1777 AutoLock lock(lock_); | 1780 AutoLock lock(lock_); |
1778 | 1781 |
1779 previous_logged_events.swap(logged_events_); | 1782 previous_logged_events.swap(logged_events_); |
1780 UseNextTraceBuffer(); | 1783 UseNextTraceBuffer(); |
1781 thread_message_loops_.clear(); | 1784 thread_message_loops_.clear(); |
1782 | 1785 |
1783 flush_message_loop_proxy_ = NULL; | 1786 flush_message_loop_proxy_ = NULL; |
1784 flush_output_callback = flush_output_callback_; | 1787 flush_output_callback = flush_output_callback_; |
1785 flush_output_callback_.Reset(); | 1788 flush_output_callback_.Reset(); |
1786 } | 1789 } |
1787 | 1790 |
| 1791 if (use_worker_thread_ && |
| 1792 WorkerPool::PostTask( |
| 1793 FROM_HERE, |
| 1794 Bind(&TraceLog::ConvertTraceEventsToTraceFormat, |
| 1795 Passed(&previous_logged_events), |
| 1796 flush_output_callback), |
| 1797 true)) { |
| 1798 return; |
| 1799 } |
| 1800 |
1788 ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(), | 1801 ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(), |
1789 flush_output_callback); | 1802 flush_output_callback); |
1790 } | 1803 } |
1791 | 1804 |
1792 // Run in each thread holding a local event buffer. | 1805 // Run in each thread holding a local event buffer. |
1793 void TraceLog::FlushCurrentThread(int generation) { | 1806 void TraceLog::FlushCurrentThread(int generation) { |
1794 { | 1807 { |
1795 AutoLock lock(lock_); | 1808 AutoLock lock(lock_); |
1796 if (!CheckGeneration(generation) || !flush_message_loop_proxy_.get()) { | 1809 if (!CheckGeneration(generation) || !flush_message_loop_proxy_.get()) { |
1797 // This is late. The corresponding flush has finished. | 1810 // This is late. The corresponding flush has finished. |
(...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2602 } | 2615 } |
2603 | 2616 |
2604 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { | 2617 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { |
2605 if (*category_group_enabled_) { | 2618 if (*category_group_enabled_) { |
2606 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, | 2619 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, |
2607 name_, event_handle_); | 2620 name_, event_handle_); |
2608 } | 2621 } |
2609 } | 2622 } |
2610 | 2623 |
2611 } // namespace trace_event_internal | 2624 } // namespace trace_event_internal |
OLD | NEW |