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/debug/trace_event_impl.h" | 5 #include "base/debug/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 14 matching lines...) Expand all Loading... | |
25 #include "base/strings/string_tokenizer.h" | 25 #include "base/strings/string_tokenizer.h" |
26 #include "base/strings/string_util.h" | 26 #include "base/strings/string_util.h" |
27 #include "base/strings/stringprintf.h" | 27 #include "base/strings/stringprintf.h" |
28 #include "base/strings/utf_string_conversions.h" | 28 #include "base/strings/utf_string_conversions.h" |
29 #include "base/synchronization/cancellation_flag.h" | 29 #include "base/synchronization/cancellation_flag.h" |
30 #include "base/synchronization/waitable_event.h" | 30 #include "base/synchronization/waitable_event.h" |
31 #include "base/sys_info.h" | 31 #include "base/sys_info.h" |
32 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 32 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
33 #include "base/threading/platform_thread.h" | 33 #include "base/threading/platform_thread.h" |
34 #include "base/threading/thread_id_name_manager.h" | 34 #include "base/threading/thread_id_name_manager.h" |
35 #include "base/threading/worker_pool.h" | |
35 #include "base/time/time.h" | 36 #include "base/time/time.h" |
36 | 37 |
37 #if defined(OS_WIN) | 38 #if defined(OS_WIN) |
38 #include "base/debug/trace_event_win.h" | 39 #include "base/debug/trace_event_win.h" |
39 #endif | 40 #endif |
40 | 41 |
41 class DeleteTraceLogForTesting { | 42 class DeleteTraceLogForTesting { |
42 public: | 43 public: |
43 static void Delete() { | 44 static void Delete() { |
44 Singleton<base::debug::TraceLog, | 45 Singleton<base::debug::TraceLog, |
(...skipping 21 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 kTraceEventBufferSize = 10 * 1024 * 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 1645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1732 FROM_HERE, | 1733 FROM_HERE, |
1733 Bind(&TraceLog::OnFlushTimeout, Unretained(this), generation), | 1734 Bind(&TraceLog::OnFlushTimeout, Unretained(this), generation), |
1734 TimeDelta::FromMilliseconds(kThreadFlushTimeoutMs)); | 1735 TimeDelta::FromMilliseconds(kThreadFlushTimeoutMs)); |
1735 return; | 1736 return; |
1736 } | 1737 } |
1737 | 1738 |
1738 FinishFlush(generation); | 1739 FinishFlush(generation); |
1739 } | 1740 } |
1740 | 1741 |
1741 void TraceLog::ConvertTraceEventsToTraceFormat( | 1742 void TraceLog::ConvertTraceEventsToTraceFormat( |
1742 scoped_ptr<TraceBuffer> logged_events, | |
1743 const TraceLog::OutputCallback& flush_output_callback) { | 1743 const TraceLog::OutputCallback& flush_output_callback) { |
1744 | 1744 |
1745 if (flush_output_callback.is_null()) | 1745 scoped_ptr<TraceBuffer> events_for_serialization; |
1746 return; | 1746 { |
1747 | 1747 AutoLock lock(lock_); |
1748 events_for_serialization.swap(previous_logged_events_); | |
1749 } | |
1748 // 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 |
1749 // to let the caller know the completion of flush. | 1751 // to let the caller know the completion of flush. |
1750 bool has_more_events = true; | 1752 bool has_more_events = true; |
1751 do { | 1753 do { |
1752 scoped_refptr<RefCountedString> json_events_str_ptr = | 1754 scoped_refptr<RefCountedString> json_events_str_ptr = new RefCountedString; |
1753 new RefCountedString(); | |
1754 | 1755 |
1755 for (size_t i = 0; i < kTraceEventBatchChunks; ++i) { | 1756 while (json_events_str_ptr->size() < kTraceEventBufferSize) { |
1756 const TraceBufferChunk* chunk = logged_events->NextChunk(); | 1757 const TraceBufferChunk* chunk = events_for_serialization->NextChunk(); |
1757 if (!chunk) { | 1758 has_more_events = chunk; |
1758 has_more_events = false; | 1759 if (!chunk) |
1759 break; | 1760 break; |
1760 } | |
1761 for (size_t j = 0; j < chunk->size(); ++j) { | 1761 for (size_t j = 0; j < chunk->size(); ++j) { |
1762 if (i > 0 || j > 0) | 1762 if (json_events_str_ptr->size()) |
1763 json_events_str_ptr->data().append(","); | 1763 json_events_str_ptr->data().append(","); |
1764 chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data())); | 1764 chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data())); |
1765 } | 1765 } |
1766 } | 1766 } |
1767 | |
1768 flush_output_callback.Run(json_events_str_ptr, has_more_events); | 1767 flush_output_callback.Run(json_events_str_ptr, has_more_events); |
1769 } while (has_more_events); | 1768 } while (has_more_events); |
1770 } | 1769 } |
1771 | 1770 |
1772 void TraceLog::FinishFlush(int generation) { | 1771 void TraceLog::FinishFlush(int generation) { |
1773 scoped_ptr<TraceBuffer> previous_logged_events; | |
1774 OutputCallback flush_output_callback; | 1772 OutputCallback flush_output_callback; |
1773 bool async_task_started = false; | |
1775 | 1774 |
1776 if (!CheckGeneration(generation)) | 1775 if (!CheckGeneration(generation)) |
1777 return; | 1776 return; |
1778 | 1777 |
1779 { | 1778 { |
1780 AutoLock lock(lock_); | 1779 AutoLock lock(lock_); |
1781 | 1780 |
1782 previous_logged_events.swap(logged_events_); | 1781 previous_logged_events_.swap(logged_events_); |
1783 UseNextTraceBuffer(); | 1782 UseNextTraceBuffer(); |
1784 thread_message_loops_.clear(); | 1783 thread_message_loops_.clear(); |
1785 | 1784 |
1786 flush_message_loop_proxy_ = NULL; | 1785 flush_message_loop_proxy_ = NULL; |
1787 flush_output_callback = flush_output_callback_; | 1786 flush_output_callback = flush_output_callback_; |
1788 flush_output_callback_.Reset(); | 1787 flush_output_callback_.Reset(); |
1788 | |
1789 async_task_started = WorkerPool::PostTask( | |
Sami
2014/12/05 16:33:01
Is there any reason to expect this to fail in prac
loislo
2014/12/05 21:38:45
As far as I see it has different behavior on the P
Sami
2014/12/08 14:35:36
Interesting. Looks like QueueUserWorkItem can fail
| |
1790 FROM_HERE, | |
1791 Bind(&TraceLog::ConvertTraceEventsToTraceFormat, | |
1792 Unretained(this), | |
1793 flush_output_callback), | |
1794 true); | |
1789 } | 1795 } |
1790 | 1796 if (!async_task_started) |
1791 ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(), | 1797 ConvertTraceEventsToTraceFormat(flush_output_callback); |
1792 flush_output_callback); | |
1793 } | 1798 } |
1794 | 1799 |
1795 // Run in each thread holding a local event buffer. | 1800 // Run in each thread holding a local event buffer. |
1796 void TraceLog::FlushCurrentThread(int generation) { | 1801 void TraceLog::FlushCurrentThread(int generation) { |
1797 { | 1802 { |
1798 AutoLock lock(lock_); | 1803 AutoLock lock(lock_); |
1799 if (!CheckGeneration(generation) || !flush_message_loop_proxy_.get()) { | 1804 if (!CheckGeneration(generation) || !flush_message_loop_proxy_.get()) { |
1800 // This is late. The corresponding flush has finished. | 1805 // This is late. The corresponding flush has finished. |
1801 return; | 1806 return; |
1802 } | 1807 } |
(...skipping 29 matching lines...) Expand all Loading... | |
1832 thread_message_loops_.begin(); | 1837 thread_message_loops_.begin(); |
1833 it != thread_message_loops_.end(); ++it) { | 1838 it != thread_message_loops_.end(); ++it) { |
1834 LOG(WARNING) << "Thread: " << (*it)->thread_name(); | 1839 LOG(WARNING) << "Thread: " << (*it)->thread_name(); |
1835 } | 1840 } |
1836 } | 1841 } |
1837 FinishFlush(generation); | 1842 FinishFlush(generation); |
1838 } | 1843 } |
1839 | 1844 |
1840 void TraceLog::FlushButLeaveBufferIntact( | 1845 void TraceLog::FlushButLeaveBufferIntact( |
1841 const TraceLog::OutputCallback& flush_output_callback) { | 1846 const TraceLog::OutputCallback& flush_output_callback) { |
1842 scoped_ptr<TraceBuffer> previous_logged_events; | |
1843 { | 1847 { |
1844 AutoLock lock(lock_); | 1848 AutoLock lock(lock_); |
1845 AddMetadataEventsWhileLocked(); | 1849 AddMetadataEventsWhileLocked(); |
1846 if (thread_shared_chunk_) { | 1850 if (thread_shared_chunk_) { |
1847 // Return the chunk to the main buffer to flush the sampling data. | 1851 // Return the chunk to the main buffer to flush the sampling data. |
1848 logged_events_->ReturnChunk(thread_shared_chunk_index_, | 1852 logged_events_->ReturnChunk(thread_shared_chunk_index_, |
1849 thread_shared_chunk_.Pass()); | 1853 thread_shared_chunk_.Pass()); |
1850 } | 1854 } |
1851 previous_logged_events = logged_events_->CloneForIteration().Pass(); | 1855 previous_logged_events_ = logged_events_->CloneForIteration().Pass(); |
1852 } // release lock | 1856 } // release lock |
1853 | 1857 ConvertTraceEventsToTraceFormat(flush_output_callback); |
1854 ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(), | |
1855 flush_output_callback); | |
1856 } | 1858 } |
1857 | 1859 |
1858 void TraceLog::UseNextTraceBuffer() { | 1860 void TraceLog::UseNextTraceBuffer() { |
1859 logged_events_.reset(CreateTraceBuffer()); | 1861 logged_events_.reset(CreateTraceBuffer()); |
1860 subtle::NoBarrier_AtomicIncrement(&generation_, 1); | 1862 subtle::NoBarrier_AtomicIncrement(&generation_, 1); |
1861 thread_shared_chunk_.reset(); | 1863 thread_shared_chunk_.reset(); |
1862 thread_shared_chunk_index_ = 0; | 1864 thread_shared_chunk_index_ = 0; |
1863 } | 1865 } |
1864 | 1866 |
1865 TraceEventHandle TraceLog::AddTraceEvent( | 1867 TraceEventHandle TraceLog::AddTraceEvent( |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2572 } | 2574 } |
2573 | 2575 |
2574 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { | 2576 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { |
2575 if (*category_group_enabled_) { | 2577 if (*category_group_enabled_) { |
2576 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, | 2578 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, |
2577 name_, event_handle_); | 2579 name_, event_handle_); |
2578 } | 2580 } |
2579 } | 2581 } |
2580 | 2582 |
2581 } // namespace trace_event_internal | 2583 } // namespace trace_event_internal |
OLD | NEW |