Changeset 145809 in webkit
- Timestamp:
- Mar 14, 2013 6:59:41 AM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r145808 r145809 1 2013-03-12 Andrey Kosyakov <caseq@chromium.org> 2 3 Web Inspector: do not aggregate non-main thread timeline events, handle them in a generic fashion 4 https://bugs.webkit.org/show_bug.cgi?id=112172 5 6 Reviewed by Vsevolod Vlasov. 7 8 - build nested event trees for non-main thread events similar to how it's done on the main thread; 9 - drop aggregation logic for Rasterize events; 10 - extract time conversion logic so that it may be reused in TimelineTraceEventProcessor. 11 12 * English.lproj/localizedStrings.js: drive-by: drop duplicate line. 13 * inspector/InspectorTimelineAgent.cpp: 14 (WebCore::TimelineTimeConverter::reset): 15 (WebCore): 16 (WebCore::InspectorTimelineAgent::pushGCEventRecords): 17 (WebCore::InspectorTimelineAgent::start): 18 (WebCore::InspectorTimelineAgent::innerAddRecordToTimeline): 19 (WebCore::InspectorTimelineAgent::InspectorTimelineAgent): 20 (WebCore::InspectorTimelineAgent::appendRecord): 21 (WebCore::InspectorTimelineAgent::sendEvent): 22 (WebCore::InspectorTimelineAgent::timestamp): 23 * inspector/InspectorTimelineAgent.h: 24 (TimelineTimeConverter): 25 (WebCore::TimelineTimeConverter::TimelineTimeConverter): 26 (WebCore::TimelineTimeConverter::fromMonotonicallyIncreasingTime): 27 (WebCore): 28 (InspectorTimelineAgent): 29 (WebCore::InspectorTimelineAgent::timeConverter): 30 * inspector/TimelineRecordFactory.cpp: 31 (WebCore::TimelineRecordFactory::createBackgroundRecord): 32 (WebCore): 33 * inspector/TimelineRecordFactory.h: 34 (TimelineRecordFactory): 35 * inspector/TimelineTraceEventProcessor.cpp: 36 (WebCore::TimelineRecordStack::TimelineRecordStack): 37 (WebCore): 38 (WebCore::TimelineRecordStack::addScopedRecord): 39 (WebCore::TimelineRecordStack::closeScopedRecord): 40 (WebCore::TimelineRecordStack::addInstantRecord): 41 (WebCore::TimelineRecordStack::isOpenRecordOfType): 42 (WebCore::TimelineRecordStack::send): 43 (WebCore::TimelineTraceEventProcessor::TimelineTraceEventProcessor): 44 (WebCore::TimelineTraceEventProcessor::onBeginFrame): 45 (WebCore::TimelineTraceEventProcessor::onRasterTaskBegin): 46 (WebCore::TimelineTraceEventProcessor::onRasterTaskEnd): 47 (WebCore::TimelineTraceEventProcessor::createRecord): 48 * inspector/TimelineTraceEventProcessor.h: 49 (TimelineRecordStack): 50 (WebCore::TimelineRecordStack::Entry::Entry): 51 (Entry): 52 (WebCore::TimelineRecordStack::TimelineRecordStack): 53 (WebCore): 54 (WebCore::TimelineTraceEventProcessor::TimelineThreadState::TimelineThreadState): 55 (TimelineThreadState): 56 (TimelineTraceEventProcessor): 57 (WebCore::TimelineTraceEventProcessor::TraceEvent::TraceEvent): 58 (WebCore::TimelineTraceEventProcessor::TraceEvent::isNull): 59 (WebCore::TimelineTraceEventProcessor::threadState): 60 1 61 2013-03-14 Xan Lopez <xlopez@igalia.com> 2 62 -
trunk/Source/WebCore/English.lproj/localizedStrings.js
r145727 r145809 774 774 localizedStrings["Composite Layers"] = "Composite Layers"; 775 775 localizedStrings["Interval Duration"] = "Interval Duration"; 776 localizedStrings["CPU time"] = "CPU time";777 776 localizedStrings["Replay XHR"] = "Replay XHR"; 778 777 localizedStrings["[ %d - %d ]"] = "[ %d - %d ]"; -
trunk/Source/WebCore/inspector/InspectorTimelineAgent.cpp
r144756 r145809 123 123 } 124 124 125 void TimelineTimeConverter::reset() 126 { 127 m_startOffset = monotonicallyIncreasingTime() - currentTime(); 128 } 129 125 130 void InspectorTimelineAgent::pushGCEventRecords() 126 131 { … … 131 136 m_gcEvents.clear(); 132 137 for (GCEvents::iterator i = events.begin(); i != events.end(); ++i) { 133 RefPtr<InspectorObject> record = TimelineRecordFactory::createGenericRecord( timestampFromMicroseconds(i->startTime), m_maxCallStackDepth);138 RefPtr<InspectorObject> record = TimelineRecordFactory::createGenericRecord(m_timeConverter.fromMonotonicallyIncreasingTime(i->startTime), m_maxCallStackDepth); 134 139 record->setObject("data", TimelineRecordFactory::createGCEventData(i->collectedBytes)); 135 record->setNumber("endTime", timestampFromMicroseconds(i->endTime));140 record->setNumber("endTime", m_timeConverter.fromMonotonicallyIncreasingTime(i->endTime)); 136 141 addRecordToTimeline(record.release(), TimelineRecordType::GCEvent); 137 142 } … … 179 184 m_maxCallStackDepth = 5; 180 185 m_state->setLong(TimelineAgentState::timelineMaxCallStackDepth, m_maxCallStackDepth); 181 m_time stampOffset = currentTime() - monotonicallyIncreasingTime();186 m_timeConverter.reset(); 182 187 183 188 m_instrumentingAgents->setInspectorTimelineAgent(this); … … 548 553 setDOMCounters(record.get()); 549 554 550 if (m_recordStack.isEmpty()) { 551 // FIXME: runtimeCast is a hack. We do it because we can't build TimelineEvent directly now. 552 RefPtr<TypeBuilder::Timeline::TimelineEvent> recordChecked = TypeBuilder::Timeline::TimelineEvent::runtimeCast(record.release()); 553 m_frontend->eventRecorded(recordChecked.release()); 554 } else { 555 if (m_recordStack.isEmpty()) 556 sendEvent(record.release()); 557 else { 555 558 TimelineRecordEntry parent = m_recordStack.last(); 556 559 parent.children->pushObject(record.release()); … … 635 638 , m_memoryAgent(memoryAgent) 636 639 , m_frontend(0) 637 , m_timestampOffset(0)638 640 , m_id(1) 639 641 , m_maxCallStackDepth(5) … … 650 652 RefPtr<InspectorObject> record = TimelineRecordFactory::createGenericRecord(timestamp(), captureCallStack ? m_maxCallStackDepth : 0); 651 653 record->setObject("data", data); 652 record->setString("type", type);653 654 setFrameIdentifier(record.get(), frame); 654 655 addRecordToTimeline(record.release(), type); 655 656 } 656 657 657 void InspectorTimelineAgent::appendBackgroundThreadRecord(PassRefPtr<InspectorObject> data, const String& type, double startTime, double endTime, const String& threadName) 658 { 659 RefPtr<InspectorObject> record = TimelineRecordFactory::createGenericRecord(timestampFromMicroseconds(startTime), 0); 660 record->setObject("data", data); 661 record->setString("type", type); 662 record->setString("thread", threadName); 663 record->setNumber("endTime", timestampFromMicroseconds(endTime)); 664 RefPtr<TypeBuilder::Timeline::TimelineEvent> recordChecked = TypeBuilder::Timeline::TimelineEvent::runtimeCast(record.release()); 658 void InspectorTimelineAgent::sendEvent(PassRefPtr<InspectorObject> event) 659 { 660 // FIXME: runtimeCast is a hack. We do it because we can't build TimelineEvent directly now. 661 RefPtr<TypeBuilder::Timeline::TimelineEvent> recordChecked = TypeBuilder::Timeline::TimelineEvent::runtimeCast(event); 665 662 m_frontend->eventRecorded(recordChecked.release()); 666 663 } … … 701 698 double InspectorTimelineAgent::timestamp() 702 699 { 703 return timestampFromMicroseconds(WTF::monotonicallyIncreasingTime()); 704 } 705 706 double InspectorTimelineAgent::timestampFromMicroseconds(double microseconds) 707 { 708 return (microseconds + m_timestampOffset) * 1000.0; 700 return m_timeConverter.fromMonotonicallyIncreasingTime(WTF::monotonicallyIncreasingTime()); 709 701 } 710 702 -
trunk/Source/WebCore/inspector/InspectorTimelineAgent.h
r144756 r145809 68 68 }; 69 69 70 class TimelineTimeConverter { 71 public: 72 TimelineTimeConverter() 73 : m_startOffset(0) 74 { 75 } 76 double fromMonotonicallyIncreasingTime(double time) const { return (time - m_startOffset) * 1000.0; } 77 void reset(); 78 79 private: 80 double m_startOffset; 81 }; 82 70 83 class InspectorTimelineAgent 71 84 : public InspectorBaseAgent<InspectorTimelineAgent>, … … 182 195 183 196 private: 197 friend class TimelineRecordStack; 184 198 friend class TimelineTraceEventProcessor; 185 199 … … 198 212 InspectorTimelineAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorMemoryAgent*, InspectorCompositeState*, InspectorType, InspectorClient*); 199 213 200 void appendBackgroundThreadRecord(PassRefPtr<InspectorObject> data, const String& type, double startTime, double endTime, const String& threadName);214 void sendEvent(PassRefPtr<InspectorObject>); 201 215 void appendRecord(PassRefPtr<InspectorObject> data, const String& type, bool captureCallStack, Frame*); 202 216 void pushCurrentRecord(PassRefPtr<InspectorObject>, const String& type, bool captureCallStack, Frame*, bool hasLowLevelDetails = false); … … 216 230 void clearRecordStack(); 217 231 232 const TimelineTimeConverter& timeConverter() const { return m_timeConverter; } 218 233 double timestamp(); 219 double timestampFromMicroseconds(double microseconds);220 234 Page* page(); 221 235 222 236 InspectorPageAgent* m_pageAgent; 223 237 InspectorMemoryAgent* m_memoryAgent; 238 TimelineTimeConverter m_timeConverter; 224 239 225 240 InspectorFrontend::Timeline* m_frontend; -
trunk/Source/WebCore/inspector/TimelineRecordFactory.cpp
r144756 r145809 60 60 } 61 61 62 PassRefPtr<InspectorObject> TimelineRecordFactory::createBackgroundRecord(double startTime, const String& threadName) 63 { 64 RefPtr<InspectorObject> record = InspectorObject::create(); 65 record->setNumber("startTime", startTime); 66 record->setString("thread", threadName); 67 return record.release(); 68 } 69 62 70 PassRefPtr<InspectorObject> TimelineRecordFactory::createGCEventData(const size_t usedHeapSizeDelta) 63 71 { … … 214 222 } 215 223 216 PassRefPtr<InspectorObject> TimelineRecordFactory::createRasterData(double totalCPUTime, int threadsUsed)217 {218 RefPtr<InspectorObject> data = InspectorObject::create();219 data->setNumber("totalCPUTime", totalCPUTime);220 data->setNumber("threadsUsed", threadsUsed);221 return data.release();222 }223 224 224 } // namespace WebCore 225 225 -
trunk/Source/WebCore/inspector/TimelineRecordFactory.h
r144756 r145809 50 50 public: 51 51 static PassRefPtr<InspectorObject> createGenericRecord(double startTime, int maxCallStackDepth); 52 static PassRefPtr<InspectorObject> createBackgroundRecord(double startTime, const String& thread); 52 53 53 54 static PassRefPtr<InspectorObject> createGCEventData(const size_t usedHeapSizeDelta); … … 109 110 } 110 111 #endif 111 static PassRefPtr<InspectorObject> createRasterData(double totalCPUTime, int threadsUsed);112 113 112 private: 114 113 TimelineRecordFactory() { } -
trunk/Source/WebCore/inspector/TimelineTraceEventProcessor.cpp
r144154 r145809 1 1 /* 2 * Copyright (C) 201 2Google Inc. All rights reserved.2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 37 37 #include "InspectorClient.h" 38 38 #include "InspectorInstrumentation.h" 39 #include "InspectorTimelineAgent.h"40 39 #include "TimelineRecordFactory.h" 41 40 … … 105 104 106 105 } // namespce 106 107 108 TimelineRecordStack::TimelineRecordStack(WeakPtr<InspectorTimelineAgent> timelineAgent) 109 : m_timelineAgent(timelineAgent) 110 { 111 } 112 113 void TimelineRecordStack::addScopedRecord(PassRefPtr<InspectorObject> record) 114 { 115 m_stack.append(Entry(record)); 116 } 117 118 void TimelineRecordStack::closeScopedRecord(double endTime) 119 { 120 if (m_stack.isEmpty()) 121 return; 122 Entry last = m_stack.last(); 123 m_stack.removeLast(); 124 last.record->setNumber("endTime", endTime); 125 if (last.children->length()) 126 last.record->setArray("children", last.children); 127 addInstantRecord(last.record); 128 } 129 130 void TimelineRecordStack::addInstantRecord(PassRefPtr<InspectorObject> record) 131 { 132 if (m_stack.isEmpty()) 133 send(record); 134 else 135 m_stack.last().children->pushObject(record); 136 } 137 138 #ifndef NDEBUG 139 bool TimelineRecordStack::isOpenRecordOfType(const String& type) 140 { 141 String lastRecordType; 142 return m_stack.isEmpty() || (m_stack.last().record->getString("type", &lastRecordType) && type == lastRecordType); 143 } 144 #endif 145 146 void TimelineRecordStack::send(PassRefPtr<InspectorObject> record) 147 { 148 InspectorTimelineAgent* timelineAgent = m_timelineAgent.get(); 149 if (!timelineAgent) 150 return; 151 timelineAgent->sendEvent(record); 152 } 153 107 154 TimelineTraceEventProcessor::TimelineTraceEventProcessor(WeakPtr<InspectorTimelineAgent> timelineAgent, InspectorClient *client) 108 155 : m_timelineAgent(timelineAgent) 156 , m_timeConverter(timelineAgent.get()->timeConverter()) 109 157 , m_inspectorClient(client) 110 158 , m_pageId(reinterpret_cast<unsigned long long>(m_timelineAgent.get()->page())) 111 , m_firstRasterStartTime(0)112 , m_lastRasterEndTime(0)113 , m_frameRasterTime(0)114 159 , m_layerId(0) 115 160 { … … 179 224 void TimelineTraceEventProcessor::onBeginFrame(const TraceEvent&) 180 225 { 181 flushRasterizerStatistics();226 processBackgroundEvents(); 182 227 } 183 228 … … 196 241 { 197 242 unsigned long long layerId = event.asUInt(InstrumentationEventArguments::LayerId); 198 ThreadIdentifier threadIdentifier = event.threadIdentifier(); 199 ASSERT(m_rasterStartTimeByThread.get(threadIdentifier) == HashTraits<double>::emptyValue()); 200 double timestamp = m_knownLayers.contains(layerId) ? event.timestamp() : 0; 201 m_rasterStartTimeByThread.set(threadIdentifier, timestamp); 243 if (!m_knownLayers.contains(layerId)) 244 return; 245 TimelineThreadState& state = threadState(event.threadIdentifier()); 246 ASSERT(!state.inRasterizeEvent); 247 state.inRasterizeEvent = true; 248 RefPtr<InspectorObject> record = createRecord(event, TimelineRecordType::Rasterize); 249 state.recordStack.addScopedRecord(record.release()); 202 250 } 203 251 204 252 void TimelineTraceEventProcessor::onRasterTaskEnd(const TraceEvent& event) 205 253 { 206 HashMap<ThreadIdentifier, double>::iterator it = m_rasterStartTimeByThread.find(event.threadIdentifier()); 207 if (it == m_rasterStartTimeByThread.end()) 208 return; 209 double startTime = it->value; 210 double endTime = event.timestamp(); 211 if (startTime == HashTraits<double>::emptyValue()) // Rasterizing unknown layer. 212 return; 213 m_frameRasterTime += endTime - startTime; 214 it->value = HashTraits<double>::emptyValue(); 215 if (!m_firstRasterStartTime || m_firstRasterStartTime > startTime) 216 m_firstRasterStartTime = startTime; 217 m_lastRasterEndTime = endTime; 254 TimelineThreadState& state = threadState(event.threadIdentifier()); 255 if (!state.inRasterizeEvent) 256 return; 257 ASSERT(state.recordStack.isOpenRecordOfType(TimelineRecordType::Rasterize)); 258 state.recordStack.closeScopedRecord(m_timeConverter.fromMonotonicallyIncreasingTime(event.timestamp())); 259 state.inRasterizeEvent = false; 218 260 } 219 261 … … 236 278 } 237 279 238 void TimelineTraceEventProcessor::flushRasterizerStatistics() 239 { 240 processBackgroundEvents(); 241 if (m_lastRasterEndTime) { 242 RefPtr<InspectorObject> data = TimelineRecordFactory::createRasterData(m_frameRasterTime, m_rasterStartTimeByThread.size()); 243 sendTimelineRecord(data, TimelineRecordType::Rasterize, m_firstRasterStartTime, m_lastRasterEndTime, "multiple"); 244 } 245 m_firstRasterStartTime = 0; 246 m_lastRasterEndTime = 0; 247 m_frameRasterTime = 0; 248 } 249 250 void TimelineTraceEventProcessor::sendTimelineRecord(PassRefPtr<InspectorObject> data, const String& recordType, double startTime, double endTime, const String& thread) 251 { 252 ASSERT(isMainThread()); 253 InspectorTimelineAgent* timelineAgent = m_timelineAgent.get(); 254 if (!timelineAgent) 255 return; 256 timelineAgent->appendBackgroundThreadRecord(data, recordType, startTime, endTime, thread); 280 PassRefPtr<InspectorObject> TimelineTraceEventProcessor::createRecord(const TraceEvent& event, const String& recordType, PassRefPtr<InspectorObject> data) 281 { 282 double startTime = m_timeConverter.fromMonotonicallyIncreasingTime(event.timestamp()); 283 RefPtr<InspectorObject> record = TimelineRecordFactory::createBackgroundRecord(startTime, String::number(event.threadIdentifier())); 284 record->setString("type", recordType); 285 record->setObject("data", data ? data : InspectorObject::create()); 286 return record.release(); 257 287 } 258 288 -
trunk/Source/WebCore/inspector/TimelineTraceEventProcessor.h
r144154 r145809 34 34 #if ENABLE(INSPECTOR) 35 35 36 #include "InspectorTimelineAgent.h" 36 37 #include "InspectorValues.h" 37 38 … … 49 50 class InspectorTimelineAgent; 50 51 class Page; 52 53 class TimelineRecordStack { 54 private: 55 struct Entry { 56 Entry(PassRefPtr<InspectorObject> record) 57 : record(record) 58 , children(InspectorArray::create()) 59 { 60 } 61 62 RefPtr<InspectorObject> record; 63 RefPtr<InspectorArray> children; 64 }; 65 66 public: 67 TimelineRecordStack() { } 68 TimelineRecordStack(WeakPtr<InspectorTimelineAgent>); 69 70 void addScopedRecord(PassRefPtr<InspectorObject> record); 71 void closeScopedRecord(double endTime); 72 void addInstantRecord(PassRefPtr<InspectorObject> record); 73 74 #ifndef NDEBUG 75 bool isOpenRecordOfType(const String& type); 76 #endif 77 78 private: 79 void send(PassRefPtr<InspectorObject>); 80 81 WeakPtr<InspectorTimelineAgent> m_timelineAgent; 82 Vector<Entry> m_stack; 83 }; 51 84 52 85 class TimelineTraceEventProcessor : public ThreadSafeRefCounted<TimelineTraceEventProcessor> { … … 90 123 }; 91 124 125 struct TimelineThreadState { 126 TimelineThreadState() { } 127 128 TimelineThreadState(WeakPtr<InspectorTimelineAgent> timelineAgent) 129 : recordStack(timelineAgent) 130 , inRasterizeEvent(false) 131 { 132 } 133 134 TimelineRecordStack recordStack; 135 bool inRasterizeEvent; 136 }; 137 92 138 class TraceEvent { 93 139 public: 94 140 TraceEvent() 95 : m_argumentCount(0) 141 : m_name(0) 142 , m_argumentCount(0) 96 143 { 97 144 } … … 123 170 ThreadIdentifier threadIdentifier() const { return m_threadIdentifier; } 124 171 int argumentCount() const { return m_argumentCount; } 172 bool isNull() const { return !m_name; } 125 173 126 174 bool asBool(const char* name) const … … 169 217 typedef void (TimelineTraceEventProcessor::*TraceEventHandler)(const TraceEvent&); 170 218 219 TimelineThreadState& threadState(ThreadIdentifier thread) 220 { 221 ThreadStateMap::iterator it = m_threadStates.find(thread); 222 if (it != m_threadStates.end()) 223 return it->value; 224 return m_threadStates.add(thread, TimelineThreadState(m_timelineAgent)).iterator->value; 225 } 226 171 227 void processBackgroundEvents(); 172 void sendTimelineRecord(PassRefPtr<InspectorObject> data, const String& recordType, double startTime, double endTime, const String& Thread); 228 PassRefPtr<InspectorObject> createRecord(const TraceEvent&, const String& recordType, PassRefPtr<InspectorObject> data = 0); 229 230 void registerHandler(const char* name, TraceEventPhase, TraceEventHandler); 173 231 174 232 void onBeginFrame(const TraceEvent&); … … 180 238 void onPaint(const TraceEvent&); 181 239 182 void flushRasterizerStatistics();183 184 void registerHandler(const char* name, TraceEventPhase, TraceEventHandler);185 240 186 241 WeakPtr<InspectorTimelineAgent> m_timelineAgent; 242 TimelineTimeConverter m_timeConverter; 187 243 InspectorClient* m_inspectorClient; 244 unsigned long long m_pageId; 188 245 189 246 typedef HashMap<std::pair<String, int>, TraceEventHandler> HandlersMap; … … 191 248 Mutex m_backgroundEventsMutex; 192 249 Vector<TraceEvent> m_backgroundEvents; 193 unsigned long long m_pageId; 250 251 typedef HashMap<ThreadIdentifier, TimelineThreadState> ThreadStateMap; 252 ThreadStateMap m_threadStates; 194 253 195 254 HashSet<unsigned long long> m_knownLayers; 196 HashMap<ThreadIdentifier, double> m_rasterStartTimeByThread;197 double m_firstRasterStartTime;198 double m_lastRasterEndTime;199 double m_frameRasterTime;200 201 255 unsigned long long m_layerId; 202 256 };
Note: See TracChangeset
for help on using the changeset viewer.