LayoutTests/ChangeLog

 12019-01-24 Joseph Pecoraro <pecoraro@apple.com>
 2
 3 Web Inspector: CPU Usage Timeline
 4 https://bugs.webkit.org/show_bug.cgi?id=193730
 5 <rdar://problem/46797201>
 6
 7 Reviewed by Devin Rousso.
 8
 9 * inspector/cpu-profiler/tracking-expected.txt: Added.
 10 * inspector/cpu-profiler/tracking.html: Added.
 11 Test the CPUProfiler domain emits events.
 12
 13 * inspector/heap/tracking-expected.txt:
 14 * inspector/heap/tracking.html:
 15 * inspector/memory/tracking-expected.txt:
 16 * inspector/memory/tracking.html:
 17 * inspector/script-profiler/tracking-expected.txt:
 18 * inspector/script-profiler/tracking.html:
 19 Update test naming.
 20
 21 * platform/win/TestExpectations:
 22 Skip on platforms without RESOURCE_USAGE.
 23
1242019-01-23 Eric Liang <ericliang@apple.com>
225
326 AX: [GTK] Layout test accessibility/set-selected-editable.html is failing

LayoutTests/inspector/cpu-profiler/tracking-expected.txt

 1Tests that CPUProfiler.startTracking and CPUProfiler.stopTracking trigger trackingStart, trackingUpdate, and trackingComplete events with expected data.
 2
 3
 4== Running test suite: CPUProfiler.Tracking
 5-- Running test case: CPUProfiler.Tracking.StartAndStopTrackingWithEvent
 6CPUProfiler.trackingStart
 7PASS: Should have a timestamp when starting.
 8CPUProfiler.trackingUpdate
 9PASS: Should have an event object.
 10PASS: Event should have a timestamp.
 11PASS: Event should have a usage.
 12PASS: usage should be greater than or equal to zero.
 13CPUProfiler.trackingComplete
 14

LayoutTests/inspector/cpu-profiler/tracking.html

 1<!DOCTYPE html>
 2<html>
 3<head>
 4<script src="../../http/tests/inspector/resources/protocol-test.js"></script>
 5<script>
 6function test()
 7{
 8 let suite = ProtocolTest.createAsyncSuite("CPUProfiler.Tracking");
 9
 10 suite.addTestCase({
 11 name: "CPUProfiler.Tracking.StartAndStopTrackingWithEvent",
 12 test(resolve, reject) {
 13 InspectorProtocol.awaitEvent({event: "CPUProfiler.trackingStart"}).then((messageObject) => {
 14 ProtocolTest.log("CPUProfiler.trackingStart");
 15 ProtocolTest.expectThat(typeof messageObject.params.timestamp === "number", "Should have a timestamp when starting.");
 16 });
 17
 18 InspectorProtocol.awaitEvent({event: "CPUProfiler.trackingUpdate"}).then((messageObject) => {
 19 ProtocolTest.log("CPUProfiler.trackingUpdate");
 20 ProtocolTest.expectThat(typeof messageObject.params.event === "object", "Should have an event object.");
 21 ProtocolTest.expectThat(typeof messageObject.params.event.timestamp === "number", "Event should have a timestamp.");
 22 ProtocolTest.expectThat(typeof messageObject.params.event.usage === "number", "Event should have a usage.");
 23 ProtocolTest.expectThat(messageObject.params.event.usage >= 0, "usage should be greater than or equal to zero.");
 24
 25 InspectorProtocol.sendCommand("CPUProfiler.stopTracking", {});
 26 });
 27
 28 InspectorProtocol.awaitEvent({event: "CPUProfiler.trackingComplete"}).then((messageObject) => {
 29 ProtocolTest.log("CPUProfiler.trackingComplete");
 30 resolve();
 31 });
 32
 33 InspectorProtocol.sendCommand("CPUProfiler.startTracking", {});
 34 }
 35 });
 36
 37 suite.runTestCasesAndFinish();
 38}
 39</script>
 40</head>
 41<body onload="runTest()">
 42<p>Tests that CPUProfiler.startTracking and CPUProfiler.stopTracking trigger trackingStart, trackingUpdate, and trackingComplete events with expected data.</p>
 43</body>
 44</html>

LayoutTests/inspector/heap/tracking-expected.txt

11Tests that Heap.startTracking and Heap.stopTracking trigger trackingStart and trackingComplete events with expected data.
22
33
4 == Running test suite: Heap.startTracking and Heap.stopTracking
5 -- Running test case: StartAndStopTrackingIncludeSnapshots
 4== Running test suite: Heap.Tracking
 5-- Running test case: Heap.Tracking.StartAndStopTrackingIncludeSnapshots
66Heap.trackingStart
77PASS: Should have a timestamp when starting.
88PASS: Should have snapshotData when starting.

LayoutTests/inspector/heap/tracking.html

55<script>
66function test()
77{
8  let suite = ProtocolTest.createAsyncSuite("Heap.startTracking and Heap.stopTracking");
 8 let suite = ProtocolTest.createAsyncSuite("Heap.Tracking");
99
1010 suite.addTestCase({
11  name: "StartAndStopTrackingIncludeSnapshots",
 11 name: "Heap.Tracking.StartAndStopTrackingIncludeSnapshots",
1212 test(resolve, reject) {
1313 InspectorProtocol.awaitEvent({event: "Heap.trackingStart"}).then((messageObject) => {
1414 ProtocolTest.log("Heap.trackingStart");

LayoutTests/inspector/memory/tracking-expected.txt

11Tests that Memory.startTracking and Memory.stopTracking trigger trackingStart, trackingUpdate, and trackingComplete events with expected data.
22
33
4 == Running test suite: Memory.startTracking and Memory.stopTracking
5 -- Running test case: StartAndStopTrackingWithEvent
 4== Running test suite: Memory.Tracking
 5-- Running test case: Memory.Tracking.StartAndStopTrackingWithEvent
66Memory.trackingStart
77PASS: Should have a timestamp when starting.
88Memory.trackingUpdate

LayoutTests/inspector/memory/tracking.html

55<script>
66function test()
77{
8  let suite = ProtocolTest.createAsyncSuite("Memory.startTracking and Memory.stopTracking");
 8 let suite = ProtocolTest.createAsyncSuite("Memory.Tracking");
99
1010 suite.addTestCase({
11  name: "StartAndStopTrackingWithEvent",
 11 name: "Memory.Tracking.StartAndStopTrackingWithEvent",
1212 test(resolve, reject) {
1313 InspectorProtocol.awaitEvent({event: "Memory.trackingStart"}).then((messageObject) => {
1414 ProtocolTest.log("Memory.trackingStart");

LayoutTests/inspector/script-profiler/tracking-expected.txt

11Tests that ScriptProfiler.startTracking and ScriptProfiler.stopTracking trigger trackingStart and trackingComplete events.
22
33
4 == Running test suite: ScriptProfiler.startTracking and ScriptProfiler.stopTracking
5 -- Running test case: StartAndStopTracking
 4== Running test suite: ScriptProfiler.Tracking
 5-- Running test case: ScriptProfiler.Tracking.StartAndStopTracking
66ScriptProfiler.trackingStart
77PASS: Should have a timestamp when starting.
88ScriptProfiler.trackingComplete

LayoutTests/inspector/script-profiler/tracking.html

55<script>
66function test()
77{
8  let suite = ProtocolTest.createAsyncSuite("ScriptProfiler.startTracking and ScriptProfiler.stopTracking");
 8 let suite = ProtocolTest.createAsyncSuite("ScriptProfiler.Tracking");
99
1010 suite.addTestCase({
11  name: "StartAndStopTracking",
 11 name: "ScriptProfiler.Tracking.StartAndStopTracking",
1212 description: "Start and stop the ScriptProfiler should cause trackingStart and trackingComplete events.",
1313 test(resolve, reject) {
1414 InspectorProtocol.awaitEvent({event: "ScriptProfiler.trackingStart"}).then((messageObject) => {

LayoutTests/platform/win/TestExpectations

@@webkit.org/b/137157 http/tests/inspector [ Skip ]
23972397
23982398# Requires ENABLE(RESOURCE_USAGE).
23992399inspector/memory [ Skip ]
 2400inspector/cpu-profiler [ Skip ]
24002401
24012402# webkit.org/b/143548 inspector/console [ Skip ]
24022403# webkit.org/b/137157 inspector/css [ Skip ]

Source/JavaScriptCore/CMakeLists.txt

@@endif ()
10961096
10971097if (ENABLE_RESOURCE_USAGE)
10981098 list(APPEND JavaScriptCore_INSPECTOR_DOMAINS
 1099 ${JAVASCRIPTCORE_DIR}/inspector/protocol/CPUProfiler.json
10991100 ${JAVASCRIPTCORE_DIR}/inspector/protocol/Memory.json
11001101 )
11011102endif ()

Source/JavaScriptCore/ChangeLog

 12019-01-24 Joseph Pecoraro <pecoraro@apple.com>
 2
 3 Web Inspector: CPU Usage Timeline
 4 https://bugs.webkit.org/show_bug.cgi?id=193730
 5 <rdar://problem/46797201>
 6
 7 Reviewed by Devin Rousso.
 8
 9 * CMakeLists.txt:
 10 * DerivedSources-input.xcfilelist:
 11 * DerivedSources.make:
 12 New files.
 13
 14 * inspector/protocol/CPUProfiler.json: Added.
 15 New domain that follows the pattern of Memory/ScriptProfiler.
 16
 17 * inspector/protocol/Timeline.json:
 18 New enum to auto-start a CPU instrument in the backend.
 19
1202019-01-23 David Kilzer <ddkilzer@apple.com>
221
322 [JSC] Duplicate global variables: JSC::opcodeLengths

Source/JavaScriptCore/DerivedSources-input.xcfilelist

@@$(PROJECT_DIR)/generator/main.rb
7777$(PROJECT_DIR)/inspector/InjectedScriptSource.js
7878$(PROJECT_DIR)/inspector/protocol/ApplicationCache.json
7979$(PROJECT_DIR)/inspector/protocol/Audit.json
 80$(PROJECT_DIR)/inspector/protocol/CPUProfiler.json
8081$(PROJECT_DIR)/inspector/protocol/CSS.json
8182$(PROJECT_DIR)/inspector/protocol/Canvas.json
8283$(PROJECT_DIR)/inspector/protocol/Console.json

Source/JavaScriptCore/DerivedSources.make

@@ifeq ($(findstring ENABLE_INDEXED_DATABASE,$(FEATURE_DEFINES)), ENABLE_INDEXED_D
258258endif
259259
260260ifeq ($(findstring ENABLE_RESOURCE_USAGE,$(FEATURE_DEFINES)), ENABLE_RESOURCE_USAGE)
 261 INSPECTOR_DOMAINS := $(INSPECTOR_DOMAINS) $(JavaScriptCore)/inspector/protocol/CPUProfiler.json
261262 INSPECTOR_DOMAINS := $(INSPECTOR_DOMAINS) $(JavaScriptCore)/inspector/protocol/Memory.json
262263endif
263264

Source/JavaScriptCore/inspector/protocol/CPUProfiler.json

 1{
 2 "domain": "CPUProfiler",
 3 "description": "CPUProfiler domain exposes cpu usage tracking.",
 4 "featureGuard": "ENABLE(RESOURCE_USAGE)",
 5 "availability": ["web"],
 6 "types": [
 7 {
 8 "id": "Event",
 9 "type": "object",
 10 "properties": [
 11 { "name": "timestamp", "type": "number" },
 12 { "name": "usage", "type": "number", "description": "Percent of total cpu usage. If there are multiple cores the usage may be greater than 100%." }
 13 ]
 14 }
 15 ],
 16 "commands": [
 17 {
 18 "name": "startTracking",
 19 "description": "Start tracking cpu usage."
 20 },
 21 {
 22 "name": "stopTracking",
 23 "description": "Stop tracking cpu usage. This will produce a `trackingComplete` event."
 24 }
 25 ],
 26 "events": [
 27 {
 28 "name": "trackingStart",
 29 "description": "Tracking started.",
 30 "parameters": [
 31 { "name": "timestamp", "type": "number" }
 32 ]
 33 },
 34 {
 35 "name": "trackingUpdate",
 36 "description": "Periodic tracking updates with event data.",
 37 "parameters": [
 38 { "name": "event", "$ref": "Event" }
 39 ]
 40 },
 41 {
 42 "name": "trackingComplete",
 43 "description": "Tracking stopped. Includes any buffered data during tracking, such as profiling information."
 44 }
 45 ]
 46}

Source/JavaScriptCore/inspector/protocol/Timeline.json

3939 "enum": [
4040 "ScriptProfiler",
4141 "Timeline",
 42 "CPU",
4243 "Memory",
4344 "Heap"
4445 ]

Source/WebCore/ChangeLog

 12019-01-24 Joseph Pecoraro <pecoraro@apple.com>
 2
 3 Web Inspector: CPU Usage Timeline
 4 https://bugs.webkit.org/show_bug.cgi?id=193730
 5 <rdar://problem/46797201>
 6
 7 Reviewed by Devin Rousso.
 8
 9 Test: inspector/cpu-profiler/tracking.html
 10
 11 * Sources.txt:
 12 * UnifiedSources-input.xcfilelist:
 13 * WebCore.xcodeproj/project.pbxproj:
 14 New files.
 15
 16 * inspector/InspectorController.cpp:
 17 (WebCore::InspectorController::createLazyAgents):
 18 * inspector/InstrumentingAgents.cpp:
 19 (WebCore::InstrumentingAgents::reset):
 20 * inspector/InstrumentingAgents.h:
 21 (WebCore::InstrumentingAgents::inspectorCPUProfilerAgent const):
 22 (WebCore::InstrumentingAgents::setInspectorCPUProfilerAgent):
 23 Create and track the CPUProfilerAgent.
 24
 25 * inspector/agents/InspectorTimelineAgent.cpp:
 26 (WebCore::InspectorTimelineAgent::toggleInstruments):
 27 (WebCore::InspectorTimelineAgent::toggleCPUInstrument):
 28 Handle backend auto-start of the CPU instrument / timeline.
 29
 30 * inspector/agents/InspectorCPUProfilerAgent.h:
 31 * inspector/agents/InspectorCPUProfilerAgent.cpp: Added.
 32 (WebCore::InspectorCPUProfilerAgent::InspectorCPUProfilerAgent):
 33 (WebCore::InspectorCPUProfilerAgent::didCreateFrontendAndBackend):
 34 (WebCore::InspectorCPUProfilerAgent::willDestroyFrontendAndBackend):
 35 (WebCore::InspectorCPUProfilerAgent::startTracking):
 36 (WebCore::InspectorCPUProfilerAgent::stopTracking):
 37 (WebCore::InspectorCPUProfilerAgent::collectSample):
 38 CPUProfilerAgent uses the ResourceUsageThread to get CPU data.
 39
 40 * inspector/agents/InspectorTimelineAgent.h:
 41 * inspector/agents/InspectorMemoryAgent.cpp:
 42 (WebCore::InspectorMemoryAgent::startTracking):
 43 (WebCore::InspectorMemoryAgent::collectSample):
 44 Update the MemoryAgent to collect only Memory data and use a more accurate sample timestamp.
 45
 46 * page/ResourceUsageData.h:
 47 * page/ResourceUsageThread.cpp:
 48 (WebCore::ResourceUsageThread::addObserver):
 49 (WebCore::ResourceUsageThread::removeObserver):
 50 (WebCore::ResourceUsageThread::notifyObservers):
 51 (WebCore::ResourceUsageThread::recomputeCollectionMode):
 52 (WebCore::ResourceUsageThread::threadBody):
 53 * page/ResourceUsageThread.h:
 54 * page/cocoa/ResourceUsageOverlayCocoa.mm:
 55 (WebCore::ResourceUsageOverlay::platformInitialize):
 56 * page/cocoa/ResourceUsageThreadCocoa.mm:
 57 (WebCore::ResourceUsageThread::platformCollectCPUData):
 58 (WebCore::ResourceUsageThread::platformCollectMemoryData):
 59 (WebCore::ResourceUsageThread::platformThreadBody): Deleted.
 60 * page/linux/ResourceUsageOverlayLinux.cpp:
 61 (WebCore::ResourceUsageOverlay::platformInitialize):
 62 * page/linux/ResourceUsageThreadLinux.cpp:
 63 (WebCore::ResourceUsageThread::platformCollectCPUData):
 64 (WebCore::ResourceUsageThread::platformCollectMemoryData):
 65 (WebCore::ResourceUsageThread::platformThreadBody):
 66 Give each observer their own collection mode. The ResourceUsageThread
 67 will then collect data that is the union of all of the active observers.
 68 This allows collecting CPU and Memory data separately, reducing the cost
 69 of each when gathered individually.
 70
1712019-01-23 David Kilzer <ddkilzer@apple.com>
272
373 REGRESSION (r240292): Attempt to fix WinCairo build

Source/WebCore/Sources.txt

@@inspector/WorkerInspectorController.cpp
12861286inspector/WorkerScriptDebugServer.cpp
12871287
12881288inspector/agents/InspectorApplicationCacheAgent.cpp
 1289inspector/agents/InspectorCPUProfilerAgent.cpp
12891290inspector/agents/InspectorCSSAgent.cpp
12901291inspector/agents/InspectorCanvasAgent.cpp
12911292inspector/agents/InspectorDOMAgent.cpp

Source/WebCore/UnifiedSources-input.xcfilelist

@@$(SRCROOT)/inspector/WebInjectedScriptManager.cpp
22012201$(SRCROOT)/inspector/WorkerInspectorController.cpp
22022202$(SRCROOT)/inspector/WorkerScriptDebugServer.cpp
22032203$(SRCROOT)/inspector/agents/InspectorApplicationCacheAgent.cpp
 2204$(SRCROOT)/inspector/agents/InspectorCPUProfilerAgent.cpp
22042205$(SRCROOT)/inspector/agents/InspectorCSSAgent.cpp
22052206$(SRCROOT)/inspector/agents/InspectorCanvasAgent.cpp
22062207$(SRCROOT)/inspector/agents/InspectorDOMAgent.cpp

Source/WebCore/WebCore.xcodeproj/project.pbxproj

31163116 A58C59D11E382EAE0047859C /* JSPerformanceMark.h in Headers */ = {isa = PBXBuildFile; fileRef = A58C59CD1E382EA90047859C /* JSPerformanceMark.h */; };
31173117 A58C59D31E382EB20047859C /* JSPerformanceMeasure.h in Headers */ = {isa = PBXBuildFile; fileRef = A58C59CF1E382EA90047859C /* JSPerformanceMeasure.h */; };
31183118 A593CF8B1840535200BFCE27 /* InspectorWebAgentBase.h in Headers */ = {isa = PBXBuildFile; fileRef = A593CF8A1840535200BFCE27 /* InspectorWebAgentBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
 3119 A59C230A21F29206004EC939 /* InspectorCPUProfilerAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A59C230821F29206004EC939 /* InspectorCPUProfilerAgent.h */; };
31193120 A5A2AF0C1829734300DE1729 /* PageDebuggable.h in Headers */ = {isa = PBXBuildFile; fileRef = A5A2AF0A1829734300DE1729 /* PageDebuggable.h */; };
31203121 A5A7AA43132F0ECC00D3A3C2 /* AutocapitalizeTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = A5A7AA42132F0ECC00D3A3C2 /* AutocapitalizeTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
31213122 A5A9933D1E37FB19005B5E4D /* PerformanceObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = A5A993361E37FAFD005B5E4D /* PerformanceObserver.h */; };

1145311454 A58C59CE1E382EA90047859C /* JSPerformanceMeasure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPerformanceMeasure.cpp; sourceTree = "<group>"; };
1145411455 A58C59CF1E382EA90047859C /* JSPerformanceMeasure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPerformanceMeasure.h; sourceTree = "<group>"; };
1145511456 A593CF8A1840535200BFCE27 /* InspectorWebAgentBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorWebAgentBase.h; sourceTree = "<group>"; };
 11457 A59C230621F29205004EC939 /* InspectorCPUProfilerAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorCPUProfilerAgent.cpp; sourceTree = "<group>"; };
 11458 A59C230821F29206004EC939 /* InspectorCPUProfilerAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorCPUProfilerAgent.h; sourceTree = "<group>"; };
1145611459 A5A2AF091829734300DE1729 /* PageDebuggable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageDebuggable.cpp; sourceTree = "<group>"; };
1145711460 A5A2AF0A1829734300DE1729 /* PageDebuggable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageDebuggable.h; sourceTree = "<group>"; };
1145811461 A5A7AA42132F0ECC00D3A3C2 /* AutocapitalizeTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutocapitalizeTypes.h; sourceTree = "<group>"; };

2247522478 A5B81C971FAA44260037D1E6 /* InspectorApplicationCacheAgent.h */,
2247622479 A5B81C961FAA44260037D1E6 /* InspectorCanvasAgent.cpp */,
2247722480 A5B81C911FAA44260037D1E6 /* InspectorCanvasAgent.h */,
 22481 A59C230621F29205004EC939 /* InspectorCPUProfilerAgent.cpp */,
 22482 A59C230821F29206004EC939 /* InspectorCPUProfilerAgent.h */,
2247822483 A5B81C921FAA44260037D1E6 /* InspectorCSSAgent.cpp */,
2247922484 A5B81CA11FAA44270037D1E6 /* InspectorCSSAgent.h */,
2248022485 A5B81CA51FAA44270037D1E6 /* InspectorDatabaseAgent.cpp */,

2955229557 F55B3DC21251F12D003EF269 /* ImageInputType.h in Headers */,
2955329558 089582560E857A7E00F82C83 /* ImageLoader.h in Headers */,
2955429559 BC7F44A80B9E324E00A9D081 /* ImageObserver.h in Headers */,
 29560 A59C230A21F29206004EC939 /* InspectorCPUProfilerAgent.h in Headers */,
2955529561 2D5A5931152525D00036EE51 /* ImageOrientation.h in Headers */,
2955629562 B51A2F3F17D7D3AE0072517A /* ImageQualityController.h in Headers */,
2955729563 49291E4B134172C800E753DE /* ImageRenderingMode.h in Headers */,

Source/WebCore/inspector/InspectorController.cpp

3939#include "Frame.h"
4040#include "GraphicsContext.h"
4141#include "InspectorApplicationCacheAgent.h"
 42#include "InspectorCPUProfilerAgent.h"
4243#include "InspectorCSSAgent.h"
4344#include "InspectorCanvasAgent.h"
4445#include "InspectorClient.h"

@@void InspectorController::createLazyAgents()
205206 m_agents.append(std::make_unique<InspectorIndexedDBAgent>(pageContext, m_pageAgent));
206207#endif
207208#if ENABLE(RESOURCE_USAGE)
 209 m_agents.append(std::make_unique<InspectorCPUProfilerAgent>(pageContext));
208210 m_agents.append(std::make_unique<InspectorMemoryAgent>(pageContext));
209211#endif
210212 m_agents.append(std::make_unique<PageAuditAgent>(pageContext));

Source/WebCore/inspector/InstrumentingAgents.cpp

@@void InstrumentingAgents::reset()
5757 m_persistentInspectorTimelineAgent = nullptr;
5858 m_inspectorDOMStorageAgent = nullptr;
5959#if ENABLE(RESOURCE_USAGE)
 60 m_inspectorCPUProfilerAgent = nullptr;
6061 m_inspectorMemoryAgent = nullptr;
6162#endif
6263 m_inspectorDatabaseAgent = nullptr;

Source/WebCore/inspector/InstrumentingAgents.h

@@class InspectorDebuggerAgent;
4444namespace WebCore {
4545
4646class InspectorApplicationCacheAgent;
47 class InspectorCanvasAgent;
 47class InspectorCPUProfilerAgent;
4848class InspectorCSSAgent;
 49class InspectorCanvasAgent;
4950class InspectorDOMAgent;
5051class InspectorDOMDebuggerAgent;
5152class InspectorDOMStorageAgent;
5253class InspectorDatabaseAgent;
5354class InspectorLayerTreeAgent;
54 class InspectorWorkerAgent;
5555class InspectorMemoryAgent;
5656class InspectorNetworkAgent;
5757class InspectorPageAgent;
5858class InspectorTimelineAgent;
 59class InspectorWorkerAgent;
5960class Page;
6061class PageDebuggerAgent;
6162class PageHeapAgent;

@@public:
111112 void setInspectorDOMStorageAgent(InspectorDOMStorageAgent* agent) { m_inspectorDOMStorageAgent = agent; }
112113
113114#if ENABLE(RESOURCE_USAGE)
 115 InspectorCPUProfilerAgent* inspectorCPUProfilerAgent() const { return m_inspectorCPUProfilerAgent; }
 116 void setInspectorCPUProfilerAgent(InspectorCPUProfilerAgent* agent) { m_inspectorCPUProfilerAgent = agent; }
 117
114118 InspectorMemoryAgent* inspectorMemoryAgent() const { return m_inspectorMemoryAgent; }
115119 void setInspectorMemoryAgent(InspectorMemoryAgent* agent) { m_inspectorMemoryAgent = agent; }
116120#endif

@@private:
157161 InspectorTimelineAgent* m_persistentInspectorTimelineAgent { nullptr };
158162 InspectorDOMStorageAgent* m_inspectorDOMStorageAgent { nullptr };
159163#if ENABLE(RESOURCE_USAGE)
 164 InspectorCPUProfilerAgent* m_inspectorCPUProfilerAgent { nullptr };
160165 InspectorMemoryAgent* m_inspectorMemoryAgent { nullptr };
161166#endif
162167 InspectorDatabaseAgent* m_inspectorDatabaseAgent { nullptr };

Source/WebCore/inspector/agents/InspectorCPUProfilerAgent.cpp

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "InspectorCPUProfilerAgent.h"
 28
 29#if ENABLE(RESOURCE_USAGE)
 30
 31#include "InstrumentingAgents.h"
 32#include "ResourceUsageThread.h"
 33#include <JavaScriptCore/InspectorEnvironment.h>
 34#include <wtf/Stopwatch.h>
 35
 36namespace WebCore {
 37
 38using namespace Inspector;
 39
 40InspectorCPUProfilerAgent::InspectorCPUProfilerAgent(PageAgentContext& context)
 41 : InspectorAgentBase("CPUProfiler"_s, context)
 42 , m_frontendDispatcher(std::make_unique<Inspector::CPUProfilerFrontendDispatcher>(context.frontendRouter))
 43 , m_backendDispatcher(Inspector::CPUProfilerBackendDispatcher::create(context.backendDispatcher, this))
 44{
 45}
 46
 47void InspectorCPUProfilerAgent::didCreateFrontendAndBackend(FrontendRouter*, BackendDispatcher*)
 48{
 49 m_instrumentingAgents.setInspectorCPUProfilerAgent(this);
 50}
 51
 52void InspectorCPUProfilerAgent::willDestroyFrontendAndBackend(DisconnectReason)
 53{
 54 m_instrumentingAgents.setInspectorCPUProfilerAgent(nullptr);
 55}
 56
 57void InspectorCPUProfilerAgent::startTracking(ErrorString&)
 58{
 59 if (m_tracking)
 60 return;
 61
 62 ResourceUsageThread::addObserver(this, CPU, [this] (const ResourceUsageData& data) {
 63 collectSample(data);
 64 });
 65
 66 m_tracking = true;
 67
 68 m_frontendDispatcher->trackingStart(m_environment.executionStopwatch()->elapsedTime().seconds());
 69}
 70
 71void InspectorCPUProfilerAgent::stopTracking(ErrorString&)
 72{
 73 if (!m_tracking)
 74 return;
 75
 76 ResourceUsageThread::removeObserver(this);
 77
 78 m_tracking = false;
 79
 80 m_frontendDispatcher->trackingComplete();
 81}
 82
 83void InspectorCPUProfilerAgent::collectSample(const ResourceUsageData& data)
 84{
 85 auto event = Protocol::CPUProfiler::Event::create()
 86 .setTimestamp(m_environment.executionStopwatch()->elapsedTimeSince(data.timestamp).seconds())
 87 .setUsage(data.cpu)
 88 .release();
 89
 90 m_frontendDispatcher->trackingUpdate(WTFMove(event));
 91}
 92
 93} // namespace WebCore
 94
 95#endif // ENABLE(RESOURCE_USAGE)

Source/WebCore/inspector/agents/InspectorCPUProfilerAgent.h

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#pragma once
 27
 28#if ENABLE(RESOURCE_USAGE)
 29
 30#include "InspectorWebAgentBase.h"
 31#include "ResourceUsageData.h"
 32#include <JavaScriptCore/InspectorBackendDispatchers.h>
 33#include <JavaScriptCore/InspectorFrontendDispatchers.h>
 34
 35namespace WebCore {
 36
 37typedef String ErrorString;
 38
 39class InspectorCPUProfilerAgent final : public InspectorAgentBase, public Inspector::CPUProfilerBackendDispatcherHandler {
 40 WTF_MAKE_NONCOPYABLE(InspectorCPUProfilerAgent);
 41 WTF_MAKE_FAST_ALLOCATED;
 42public:
 43 InspectorCPUProfilerAgent(PageAgentContext&);
 44 virtual ~InspectorCPUProfilerAgent() = default;
 45
 46 void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override;
 47 void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
 48
 49 // CPUProfilerBackendDispatcherHandler
 50 void startTracking(ErrorString&) override;
 51 void stopTracking(ErrorString&) override;
 52
 53private:
 54 void collectSample(const ResourceUsageData&);
 55
 56 std::unique_ptr<Inspector::CPUProfilerFrontendDispatcher> m_frontendDispatcher;
 57 RefPtr<Inspector::CPUProfilerBackendDispatcher> m_backendDispatcher;
 58 bool m_tracking { false };
 59};
 60
 61} // namespace WebCore
 62
 63#endif // ENABLE(RESOURCE_USAGE)

Source/WebCore/inspector/agents/InspectorMemoryAgent.cpp

@@void InspectorMemoryAgent::startTracking(ErrorString&)
7474 if (m_tracking)
7575 return;
7676
77  ResourceUsageThread::addObserver(this, [this] (const ResourceUsageData& data) {
 77 ResourceUsageThread::addObserver(this, Memory, [this] (const ResourceUsageData& data) {
7878 collectSample(data);
7979 });
8080

@@void InspectorMemoryAgent::collectSample(const ResourceUsageData& data)
145145 categories->addItem(WTFMove(otherCategory));
146146
147147 auto event = Protocol::Memory::Event::create()
148  .setTimestamp(m_environment.executionStopwatch()->elapsedTime().seconds())
 148 .setTimestamp(m_environment.executionStopwatch()->elapsedTimeSince(data.timestamp).seconds())
149149 .setCategories(WTFMove(categories))
150150 .release();
151151
152152 m_frontendDispatcher->trackingUpdate(WTFMove(event));
153153}
154154
155 } // namespace Inspector
 155} // namespace WebCore
156156
157157#endif // ENABLE(RESOURCE_USAGE)

Source/WebCore/inspector/agents/InspectorTimelineAgent.cpp

3636#include "DOMWindow.h"
3737#include "Event.h"
3838#include "Frame.h"
 39#include "InspectorCPUProfilerAgent.h"
3940#include "InspectorMemoryAgent.h"
4041#include "InspectorPageAgent.h"
4142#include "InstrumentingAgents.h"

@@void InspectorTimelineAgent::toggleInstruments(InstrumentState state)
514515 toggleHeapInstrument(state);
515516 break;
516517 }
 518 case Inspector::Protocol::Timeline::Instrument::CPU: {
 519 toggleCPUInstrument(state);
 520 break;
 521 }
517522 case Inspector::Protocol::Timeline::Instrument::Memory: {
518523 toggleMemoryInstrument(state);
519524 break;

@@void InspectorTimelineAgent::toggleHeapInstrument(InstrumentState state)
549554 }
550555}
551556
 557void InspectorTimelineAgent::toggleCPUInstrument(InstrumentState state)
 558{
 559#if ENABLE(RESOURCE_USAGE)
 560 if (InspectorCPUProfilerAgent* cpuProfilerAgent = m_instrumentingAgents.inspectorCPUProfilerAgent()) {
 561 ErrorString unused;
 562 if (state == InstrumentState::Start)
 563 cpuProfilerAgent->startTracking(unused);
 564 else
 565 cpuProfilerAgent->stopTracking(unused);
 566 }
 567#else
 568 UNUSED_PARAM(state);
 569#endif
 570}
 571
552572void InspectorTimelineAgent::toggleMemoryInstrument(InstrumentState state)
553573{
554574#if ENABLE(RESOURCE_USAGE)

Source/WebCore/inspector/agents/InspectorTimelineAgent.h

@@private:
164164 void toggleInstruments(InstrumentState);
165165 void toggleScriptProfilerInstrument(InstrumentState);
166166 void toggleHeapInstrument(InstrumentState);
 167 void toggleCPUInstrument(InstrumentState);
167168 void toggleMemoryInstrument(InstrumentState);
168169 void toggleTimelineInstrument(InstrumentState);
169170 void disableBreakpoints();

Source/WebCore/page/ResourceUsageData.h

@@struct ResourceUsageData {
8282WEBCORE_EACH_MEMORY_CATEGORIES(WEBCORE_DEFINE_MEMORY_CATEGORY)
8383#undef WEBCORE_DEFINE_MEMORY_CATEGORY
8484 } };
 85 MonotonicTime timestamp { MonotonicTime::now() };
8586 MonotonicTime timeOfNextEdenCollection { MonotonicTime::nan() };
8687 MonotonicTime timeOfNextFullCollection { MonotonicTime::nan() };
8788};

Source/WebCore/page/ResourceUsageThread.cpp

@@ResourceUsageThread& ResourceUsageThread::singleton()
4646 return resourceUsageThread;
4747}
4848
49 void ResourceUsageThread::addObserver(void* key, std::function<void (const ResourceUsageData&)> function)
 49void ResourceUsageThread::addObserver(void* key, ResourceUsageCollectionMode mode, std::function<void (const ResourceUsageData&)> function)
5050{
5151 auto& resourceUsageThread = ResourceUsageThread::singleton();
5252 resourceUsageThread.createThreadIfNeeded();

@@void ResourceUsageThread::addObserver(void* key, std::function<void (const Resou
5454 {
5555 LockHolder locker(resourceUsageThread.m_lock);
5656 bool wasEmpty = resourceUsageThread.m_observers.isEmpty();
57  resourceUsageThread.m_observers.set(key, function);
 57 resourceUsageThread.m_observers.set(key, std::make_pair(mode, function));
 58
 59 resourceUsageThread.recomputeCollectionMode();
5860
5961 if (wasEmpty)
6062 resourceUsageThread.m_condition.notifyAll();

@@void ResourceUsageThread::removeObserver(void* key)
6870 {
6971 LockHolder locker(resourceUsageThread.m_lock);
7072 resourceUsageThread.m_observers.remove(key);
 73
 74 resourceUsageThread.recomputeCollectionMode();
7175 }
7276}
7377

@@void ResourceUsageThread::waitUntilObservers()
8185void ResourceUsageThread::notifyObservers(ResourceUsageData&& data)
8286{
8387 callOnMainThread([data = WTFMove(data)]() mutable {
84  Vector<std::function<void (const ResourceUsageData&)>> functions;
85 
 88 Vector<std::pair<ResourceUsageCollectionMode, std::function<void (const ResourceUsageData&)>>> pairs;
 89
8690 {
8791 auto& resourceUsageThread = ResourceUsageThread::singleton();
8892 LockHolder locker(resourceUsageThread.m_lock);
89  functions = copyToVector(resourceUsageThread.m_observers.values());
 93 pairs = copyToVector(resourceUsageThread.m_observers.values());
9094 }
9195
92  for (auto& function : functions)
93  function(data);
 96 for (auto& pair : pairs)
 97 pair.second(data);
9498 });
9599}
96100
 101void ResourceUsageThread::recomputeCollectionMode()
 102{
 103 m_collectionMode = None;
 104
 105 for (auto& pair : m_observers.values())
 106 m_collectionMode = static_cast<ResourceUsageCollectionMode>(m_collectionMode | pair.first);
 107}
 108
97109void ResourceUsageThread::createThreadIfNeeded()
98110{
99111 if (m_thread)

@@NO_RETURN void ResourceUsageThread::threadBody()
114126 auto start = WallTime::now();
115127
116128 ResourceUsageData data;
117  platformThreadBody(m_vm, data);
 129 ResourceUsageCollectionMode mode = m_collectionMode;
 130 if (mode & CPU)
 131 platformCollectCPUData(m_vm, data);
 132 if (mode & Memory)
 133 platformCollectMemoryData(m_vm, data);
 134
118135 notifyObservers(WTFMove(data));
119136
 137 // NOTE: Web Inspector expects this interval to be 500ms (CPU / Memory timelines),
 138 // so if this interval changes Web Inspector may need to change.
120139 auto duration = WallTime::now() - start;
121140 auto difference = 500_ms - duration;
122141 WTF::sleep(difference);

Source/WebCore/page/ResourceUsageThread.h

@@class VM;
4343
4444namespace WebCore {
4545
 46enum ResourceUsageCollectionMode {
 47 None = 0,
 48 CPU = 1 << 0,
 49 Memory = 1 << 1,
 50 All = CPU | Memory,
 51};
 52
4653class ResourceUsageThread {
4754 WTF_MAKE_NONCOPYABLE(ResourceUsageThread);
4855
4956public:
50  static void addObserver(void* key, std::function<void (const ResourceUsageData&)>);
 57 static void addObserver(void* key, ResourceUsageCollectionMode, std::function<void (const ResourceUsageData&)>);
5158 static void removeObserver(void* key);
5259
5360private:

@@private:
5865 void waitUntilObservers();
5966 void notifyObservers(ResourceUsageData&&);
6067
 68 void recomputeCollectionMode();
 69
6170 void createThreadIfNeeded();
6271 void threadBody();
63  void platformThreadBody(JSC::VM*, ResourceUsageData&);
 72
 73 void platformCollectCPUData(JSC::VM*, ResourceUsageData&);
 74 void platformCollectMemoryData(JSC::VM*, ResourceUsageData&);
6475
6576 RefPtr<Thread> m_thread;
6677 Lock m_lock;
6778 Condition m_condition;
68  HashMap<void*, std::function<void (const ResourceUsageData&)>> m_observers;
 79 HashMap<void*, std::pair<ResourceUsageCollectionMode, std::function<void (const ResourceUsageData&)>>> m_observers;
 80 ResourceUsageCollectionMode m_collectionMode { None };
6981
7082 // Platforms may need to access some data from the common VM.
7183 // They should ensure their use of the VM is thread safe.

Source/WebCore/page/cocoa/ResourceUsageOverlayCocoa.mm

@@void ResourceUsageOverlay::platformInitialize()
229229
230230 overlay().layer().setContentsToPlatformLayer(m_layer.get(), GraphicsLayer::ContentsLayerPurpose::None);
231231
232  ResourceUsageThread::addObserver(this, [this] (const ResourceUsageData& data) {
 232 ResourceUsageThread::addObserver(this, All, [this] (const ResourceUsageData& data) {
233233 appendDataToHistory(data);
234234
235235 // FIXME: It shouldn't be necessary to update the bounds on every single thread loop iteration,

Source/WebCore/page/cocoa/ResourceUsageThreadCocoa.mm

@@static unsigned categoryForVMTag(unsigned tag)
205205 }
206206}
207207
208 void ResourceUsageThread::platformThreadBody(JSC::VM* vm, ResourceUsageData& data)
 208void ResourceUsageThread::platformCollectCPUData(JSC::VM*, ResourceUsageData& data)
209209{
210210 data.cpu = cpuUsage();
 211}
211212
 213void ResourceUsageThread::platformCollectMemoryData(JSC::VM* vm, ResourceUsageData& data)
 214{
212215 auto tags = pagesPerVMTag();
213216 std::array<TagInfo, MemoryCategory::NumberOfCategories> pagesPerCategory;
214217 size_t totalDirtyPages = 0;

@@void ResourceUsageThread::platformThreadBody(JSC::VM* vm, ResourceUsageData& dat
248251
249252 data.totalExternalSize = currentGCOwnedExternal;
250253
251  auto now = MonotonicTime::now();
252  data.timeOfNextEdenCollection = now + vm->heap.edenActivityCallback()->timeUntilFire().valueOr(Seconds(std::numeric_limits<double>::infinity()));
253  data.timeOfNextFullCollection = now + vm->heap.fullActivityCallback()->timeUntilFire().valueOr(Seconds(std::numeric_limits<double>::infinity()));
 254 data.timeOfNextEdenCollection = data.timestamp + vm->heap.edenActivityCallback()->timeUntilFire().valueOr(Seconds(std::numeric_limits<double>::infinity()));
 255 data.timeOfNextFullCollection = data.timestamp + vm->heap.fullActivityCallback()->timeUntilFire().valueOr(Seconds(std::numeric_limits<double>::infinity()));
254256}
255257
256258}

Source/WebCore/page/linux/ResourceUsageOverlayLinux.cpp

@@void ResourceUsageOverlay::platformInitialize()
139139 m_paintLayer->setDrawsContent(true);
140140 overlay().layer().addChild(*m_paintLayer);
141141
142  ResourceUsageThread::addObserver(this, [this] (const ResourceUsageData& data) {
 142 ResourceUsageThread::addObserver(this, All, [this] (const ResourceUsageData& data) {
143143 gData = data;
144144 m_paintLayer->setNeedsDisplay();
145145 });

Source/WebCore/page/linux/ResourceUsageThreadLinux.cpp

@@static float cpuUsage()
150150 return clampTo<float>(usage, 0, 100);
151151}
152152
153 void ResourceUsageThread::platformThreadBody(JSC::VM* vm, ResourceUsageData& data)
 153void ResourceUsageThread::platformCollectCPUData(JSC::VM*, ResourceUsageData& data)
154154{
155155 data.cpu = cpuUsage();
 156}
156157
 158void ResourceUsageThread::platformCollectMemoryData(JSC::VM* vm, ResourceUsageData& data)
 159{
157160 ProcessMemoryStatus memoryStatus;
158161 currentProcessMemoryStatus(memoryStatus);
159162 data.totalDirtySize = memoryStatus.resident - memoryStatus.shared;

@@void ResourceUsageThread::platformThreadBody(JSC::VM* vm, ResourceUsageData& dat
169172
170173 data.totalExternalSize = currentGCOwnedExternal;
171174
172  auto now = MonotonicTime::now();
173  data.timeOfNextEdenCollection = now + vm->heap.edenActivityCallback()->timeUntilFire().valueOr(Seconds(std::numeric_limits<double>::infinity()));
174  data.timeOfNextFullCollection = now + vm->heap.fullActivityCallback()->timeUntilFire().valueOr(Seconds(std::numeric_limits<double>::infinity()));
 175 data.timeOfNextEdenCollection = data.timestamp + vm->heap.edenActivityCallback()->timeUntilFire().valueOr(Seconds(std::numeric_limits<double>::infinity()));
 176 data.timeOfNextFullCollection = data.timestamp + vm->heap.fullActivityCallback()->timeUntilFire().valueOr(Seconds(std::numeric_limits<double>::infinity()));
175177}
176178
177179} // namespace WebCore

Source/WebInspectorUI/ChangeLog

 12019-01-24 Joseph Pecoraro <pecoraro@apple.com>
 2
 3 Web Inspector: CPU Usage Timeline
 4 https://bugs.webkit.org/show_bug.cgi?id=193730
 5 <rdar://problem/46797201>
 6
 7 Reviewed by Devin Rousso.
 8
 9 CPU Usage is gathered in the backend twice a second, the frequency of the
 10 ResourceUsageThread in WebCore. The frontend displays cpu usage in a few
 11 ways in the Timeline.
 12
 13 We use a column chart in the timeline overview to display the frequency and
 14 relative distance of samples. This helps show if the samples were close
 15 together or far apart, which indicates how meaningful they will be at a
 16 particular scale.
 17
 18 We use a line chart in the timeline detail view which will be easier to see
 19 the changes over a particular time range selection.
 20
 21 * Localizations/en.lproj/localizedStrings.js:
 22 New strings.
 23
 24 * UserInterface/Main.html:
 25 * UserInterface/Base/Main.js:
 26 (WI.loaded):
 27 * UserInterface/Test.html:
 28 * UserInterface/Test/Test.js:
 29 (WI.loaded):
 30 * UserInterface/Protocol/CPUProfilerObserver.js:
 31 (WI.CPUProfilerObserver.prototype.trackingStart):
 32 (WI.CPUProfilerObserver.prototype.trackingUpdate):
 33 (WI.CPUProfilerObserver.prototype.trackingComplete):
 34 (WI.CPUProfilerObserver):
 35 New files and default registration.
 36
 37 * UserInterface/Protocol/Target.js:
 38 (WI.Target.prototype.get CPUProfilerAgent):
 39 New Agent.
 40
 41 * UserInterface/Controllers/TimelineManager.js:
 42 (WI.TimelineManager.availableTimelineTypes):
 43 (WI.TimelineManager.prototype.cpuProfilerTrackingStarted):
 44 (WI.TimelineManager.prototype.cpuProfilerTrackingUpdated):
 45 (WI.TimelineManager.prototype.cpuProfilerTrackingCompleted):
 46 (WI.TimelineManager.prototype._updateAutoCaptureInstruments):
 47 (WI.TimelineManager.prototype.memoryTrackingStart): Renamed.
 48 (WI.TimelineManager.prototype.memoryTrackingUpdate): Renamed.
 49 (WI.TimelineManager.prototype.memoryTrackingComplete): Renamed.
 50 * UserInterface/Models/CPUInstrument.js:
 51 (WI.CPUInstrument):
 52 (WI.CPUInstrument.supported):
 53 (WI.CPUInstrument.prototype.get timelineRecordType):
 54 (WI.CPUInstrument.prototype.startInstrumentation):
 55 (WI.CPUInstrument.prototype.stopInstrumentation):
 56 * UserInterface/Models/CPUTimelineRecord.js:
 57 (WI.CPUTimelineRecord):
 58 (WI.CPUTimelineRecord.prototype.get timestamp):
 59 (WI.CPUTimelineRecord.prototype.get usage):
 60 * UserInterface/Models/Instrument.js:
 61 (WI.Instrument.createForTimelineType):
 62 * UserInterface/Models/TimelineRecord.js:
 63 * UserInterface/Models/TimelineRecording.js:
 64 (WI.TimelineRecording.prototype.addRecord):
 65 Expose a new CPU instrument and timeline.
 66
 67 * UserInterface/Views/ColumnChart.js: Added.
 68 (WI.ColumnChart):
 69 (WI.ColumnChart.prototype.get element):
 70 (WI.ColumnChart.prototype.get bars):
 71 (WI.ColumnChart.prototype.get size):
 72 (WI.ColumnChart.prototype.set size):
 73 (WI.ColumnChart.prototype.addBar):
 74 (WI.ColumnChart.prototype.clear):
 75 (WI.ColumnChart.prototype.needsLayout):
 76 (WI.ColumnChart.prototype.updateLayout):
 77 View that will draw vertical bars with independent widths.
 78 This is meant to be used similiar to WI.LineChart.
 79
 80 * UserInterface/Images/CPUInstrument.svg: Added.
 81 * UserInterface/Views/Variables.css:
 82 (:root):
 83 CPU timeline colors and icon.
 84
 85 * UserInterface/Views/CPUTimelineOverviewGraph.css:
 86 (body .sidebar > .panel.navigation.timeline > .timelines-content li.item.cpu,):
 87 (.timeline-overview-graph.cpu):
 88 (.timeline-overview-graph.cpu > .legend):
 89 (body[dir=ltr] .timeline-overview-graph.cpu > .legend):
 90 (body[dir=rtl] .timeline-overview-graph.cpu > .legend):
 91 (.timeline-overview-graph:nth-child(even) > .legend):
 92 (body[dir=rtl] .timeline-overview-graph.cpu > .bar-chart):
 93 (.timeline-overview-graph.cpu > .bar-chart > svg > g > rect):
 94 * UserInterface/Views/CPUTimelineOverviewGraph.js: Added.
 95 (WI.CPUTimelineOverviewGraph):
 96 (WI.CPUTimelineOverviewGraph.prototype.get height):
 97 (WI.CPUTimelineOverviewGraph.prototype.reset):
 98 (WI.CPUTimelineOverviewGraph.prototype.layout.xScale):
 99 (WI.CPUTimelineOverviewGraph.prototype.layout.yScale):
 100 (WI.CPUTimelineOverviewGraph.prototype.layout.yScaleForRecord):
 101 (WI.CPUTimelineOverviewGraph.prototype.layout):
 102 (WI.CPUTimelineOverviewGraph.prototype._updateLegend):
 103 (WI.CPUTimelineOverviewGraph.prototype._cpuTimelineRecordAdded):
 104 * UserInterface/Views/CPUTimelineView.css:
 105 (.timeline-view.cpu):
 106 (.timeline-view.cpu > .content):
 107 (.timeline-view.cpu > .content .subtitle):
 108 (.timeline-view.cpu > .content > .details):
 109 (.timeline-view.cpu > .content > .details > .timeline-ruler):
 110 (body[dir=ltr] .timeline-view.cpu > .content > .details > .timeline-ruler):
 111 (body[dir=rtl] .timeline-view.cpu > .content > .details > .timeline-ruler):
 112 (.timeline-view.cpu > .content > .details > .subtitle):
 113 (.cpu-usage-view .line-chart > svg > path):
 114 (.timeline-view.cpu .legend > .row > .swatch.current):
 115 * UserInterface/Views/CPUTimelineView.js: Added.
 116 (WI.CPUTimelineView):
 117 (WI.CPUTimelineView.prototype.shown):
 118 (WI.CPUTimelineView.prototype.hidden):
 119 (WI.CPUTimelineView.prototype.closed):
 120 (WI.CPUTimelineView.prototype.reset):
 121 (WI.CPUTimelineView.prototype.get scrollableElements):
 122 (WI.CPUTimelineView.prototype.get showsFilterBar):
 123 (WI.CPUTimelineView.prototype.layout.layoutView):
 124 (WI.CPUTimelineView.prototype.layout.xScale):
 125 (WI.CPUTimelineView.prototype.layout.yScale):
 126 (WI.CPUTimelineView.prototype.layout):
 127 (WI.CPUTimelineView.prototype._cpuTimelineRecordAdded):
 128 * UserInterface/Views/CPUUsageView.css:
 129 (.cpu-usage-view):
 130 (.cpu-usage-view > .details):
 131 (body[dir=ltr] .cpu-usage-view > .details):
 132 (body[dir=rtl] .cpu-usage-view > .details):
 133 (.cpu-usage-view > .graph):
 134 (body[dir=rtl] .cpu-usage-view > .graph):
 135 * UserInterface/Views/CPUUsageView.js:
 136 (WI.CPUUsageView):
 137 (WI.CPUUsageView.prototype.get element):
 138 (WI.CPUUsageView.prototype.clear):
 139 (WI.CPUUsageView.prototype.layoutWithDataPoints):
 140 (WI.CPUUsageView.prototype._updateDetails):
 141 * UserInterface/Views/ContentView.js:
 142 (WI.ContentView.createFromRepresentedObject):
 143 * UserInterface/Views/TimelineIcons.css:
 144 (.cpu-icon .icon):
 145 * UserInterface/Views/TimelineOverviewGraph.js:
 146 (WI.TimelineOverviewGraph.createForTimeline):
 147 * UserInterface/Views/TimelineTabContentView.js:
 148 (WI.TimelineTabContentView.displayNameForTimelineType):
 149 (WI.TimelineTabContentView.iconClassNameForTimelineType):
 150 (WI.TimelineTabContentView.genericClassNameForTimelineType):
 151 (WI.TimelineTabContentView.iconClassNameForRecord):
 152 (WI.TimelineTabContentView.displayNameForRecord):
 153 Timeline views for CPU usage.
 154
 155 * UserInterface/Views/MemoryCategoryView.js:
 156 (WI.MemoryCategoryView):
 157 * UserInterface/Views/MemoryTimelineView.js:
 158 (WI.MemoryTimelineView.createChartContainer):
 159 (WI.MemoryTimelineView):
 160 (WI.MemoryTimelineView.prototype._clearMaxComparisonLegend):
 161 Minor updates to style and comments.
 162
11632019-01-23 Devin Rousso <drousso@apple.com>
2164
3165 WebInspector: Confusingly nested events in the timeline for Mutation Observers

Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

@@localizedStrings["Auto Increment"] = "Auto Increment";
139139localizedStrings["Automatically continue after evaluating"] = "Automatically continue after evaluating";
140140localizedStrings["Available Style Sheets"] = "Available Style Sheets";
141141localizedStrings["Average Time"] = "Average Time";
 142localizedStrings["Average: %s"] = "Average: %s";
142143localizedStrings["Back (%s)"] = "Back (%s)";
143144localizedStrings["Backtrace"] = "Backtrace";
144145localizedStrings["Basic"] = "Basic";

@@localizedStrings["Busy"] = "Busy";
162163localizedStrings["Byte Range %s\u2013%s"] = "Byte Range %s\u2013%s";
163164localizedStrings["Bytes Received"] = "Bytes Received";
164165localizedStrings["Bytes Sent"] = "Bytes Sent";
 166localizedStrings["CPU"] = "CPU";
 167localizedStrings["CPU Usage"] = "CPU Usage";
165168localizedStrings["CSP Hash"] = "CSP Hash";
166169localizedStrings["CSS"] = "CSS";
167170localizedStrings["CSS Canvas"] = "CSS Canvas";

@@localizedStrings["Mass"] = "Mass";
578581localizedStrings["Matching"] = "Matching";
579582localizedStrings["Max Comparison"] = "Max Comparison";
580583localizedStrings["Maximum"] = "Maximum";
 584localizedStrings["Maximum CPU Usage: %s"] = "Maximum CPU Usage: %s";
581585localizedStrings["Maximum Size: %s"] = "Maximum Size: %s";
582586localizedStrings["Maximum maximum memory size in this recording"] = "Maximum maximum memory size in this recording";
583587localizedStrings["Media"] = "Media";

Source/WebInspectorUI/UserInterface/Base/Main.js

@@WI.loaded = function()
7575 InspectorBackend.registerDOMStorageDispatcher(new WI.DOMStorageObserver);
7676 if (InspectorBackend.registerApplicationCacheDispatcher)
7777 InspectorBackend.registerApplicationCacheDispatcher(new WI.ApplicationCacheObserver);
 78 if (InspectorBackend.registerCPUProfilerDispatcher)
 79 InspectorBackend.registerCPUProfilerDispatcher(new WI.CPUProfilerObserver);
7880 if (InspectorBackend.registerScriptProfilerDispatcher)
7981 InspectorBackend.registerScriptProfilerDispatcher(new WI.ScriptProfilerObserver);
8082 if (InspectorBackend.registerTimelineDispatcher)

Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js

@@WI.TimelineManager = class TimelineManager extends WI.Object
117117 if (WI.sharedApp.debuggableType === WI.DebuggableType.JavaScript || WI.sharedApp.debuggableType === WI.DebuggableType.ServiceWorker)
118118 return types;
119119
 120 if (WI.CPUInstrument.supported())
 121 types.push(WI.TimelineRecord.Type.CPU);
 122
120123 if (WI.MemoryInstrument.supported())
121124 types.push(WI.TimelineRecord.Type.Memory);
122125

@@WI.TimelineManager = class TimelineManager extends WI.Object
449452 this._stopAutoRecordingSoon();
450453 }
451454
452  memoryTrackingStart(timestamp)
 455 cpuProfilerTrackingStarted(timestamp)
 456 {
 457 // Called from WI.CPUProfilerObserver.
 458
 459 this.capturingStarted(timestamp);
 460 }
 461
 462 cpuProfilerTrackingUpdated(event)
 463 {
 464 // Called from WI.CPUProfilerObserver.
 465
 466 if (!this._isCapturing)
 467 return;
 468
 469 this._addRecord(new WI.CPUTimelineRecord(event.timestamp, event.usage));
 470 }
 471
 472 cpuProfilerTrackingCompleted()
 473 {
 474 // Called from WI.CPUProfilerObserver.
 475 }
 476
 477 memoryTrackingStarted(timestamp)
453478 {
454479 // Called from WI.MemoryObserver.
455480
456481 this.capturingStarted(timestamp);
457482 }
458483
459  memoryTrackingUpdate(event)
 484 memoryTrackingUpdated(event)
460485 {
461486 // Called from WI.MemoryObserver.
462487

@@WI.TimelineManager = class TimelineManager extends WI.Object
466491 this._addRecord(new WI.MemoryTimelineRecord(event.timestamp, event.categories));
467492 }
468493
469  memoryTrackingComplete()
 494 memoryTrackingCompleted()
470495 {
471496 // Called from WI.MemoryObserver.
472497 }

@@WI.TimelineManager = class TimelineManager extends WI.Object
11411166 case WI.TimelineRecord.Type.Media:
11421167 instrumentSet.add(target.TimelineAgent.Instrument.Timeline);
11431168 break;
 1169 case WI.TimelineRecord.Type.CPU:
 1170 instrumentSet.add(target.TimelineAgent.Instrument.CPU);
 1171 break;
11441172 case WI.TimelineRecord.Type.Memory:
11451173 instrumentSet.add(target.TimelineAgent.Instrument.Memory);
11461174 break;

Source/WebInspectorUI/UserInterface/Debug/UncaughtExceptionReporter.css

3737.uncaught-exception-sheet {
3838 min-width: 400px;
3939 padding: 50px 0;
40  font-family: '-webkit-system-font';
 40 font-family: -webkit-system-font, sans-serif;
4141 font-size: 11pt;
4242 color: hsl(0, 0%, 40%);
4343

Source/WebInspectorUI/UserInterface/Images/CPUInstrument.svg

 1<?xml version="1.0" encoding="utf-8"?>
 2<!-- Copyright © 2019 Apple Inc. All rights reserved. -->
 3<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16">
 4 <circle stroke="hsl(118, 33%, 42%)" fill="hsl(118, 43%, 55%)" cx="8" cy="8" r="7.5"/>
 5 <rect stroke="hsl(118, 33%, 42%)" stroke-width="2" x="4" y="4" width="2" height="8" rx="0.25"/>
 6 <rect stroke="hsl(118, 33%, 42%)" stroke-width="2" x="7" y="4" width="2" height="8" rx="0.25"/>
 7 <rect stroke="hsl(118, 33%, 42%)" stroke-width="2" x="10" y="4" width="2" height="8" rx="0.25"/>
 8 <rect fill="white" x="4" y="4" width="2" height="8" rx="0.25"/>
 9 <rect fill="white" x="7" y="4" width="2" height="8" rx="0.25"/>
 10 <rect fill="white" x="10" y="4" width="2" height="8" rx="0.25"/>
 11 <rect stroke="hsl(118, 33%, 42%)" stroke-width="2" x="3" y="6" width="10" height="4" rx="0.25"/>
 12 <rect fill="white" x="3" y="6" width="10" height="4" rx="0.25"/>
 13</svg>

Source/WebInspectorUI/UserInterface/Main.html

4343 <link rel="stylesheet" href="Views/BreakpointTreeElement.css">
4444 <link rel="stylesheet" href="Views/ButtonNavigationItem.css">
4545 <link rel="stylesheet" href="Views/ButtonToolbarItem.css">
 46 <link rel="stylesheet" href="Views/CPUTimelineOverviewGraph.css">
 47 <link rel="stylesheet" href="Views/CPUTimelineView.css">
 48 <link rel="stylesheet" href="Views/CPUUsageView.css">
4649 <link rel="stylesheet" href="Views/CallFrameIcons.css">
4750 <link rel="stylesheet" href="Views/CallFrameTreeElement.css">
4851 <link rel="stylesheet" href="Views/CallFrameView.css">

9093 <link rel="stylesheet" href="Views/DetailsSection.css">
9194 <link rel="stylesheet" href="Views/DividerNavigationItem.css">
9295 <link rel="stylesheet" href="Views/Editing.css">
 96 <link rel="stylesheet" href="Views/ErrorObjectView.css">
9397 <link rel="stylesheet" href="Views/EventBreakpointPopover.css">
9498 <link rel="stylesheet" href="Views/EventBreakpointTreeElement.css">
9599 <link rel="stylesheet" href="Views/EventListenerSectionGroup.css">
96  <link rel="stylesheet" href="Views/ErrorObjectView.css">
97100 <link rel="stylesheet" href="Views/FilterBar.css">
98101 <link rel="stylesheet" href="Views/FindBanner.css">
99102 <link rel="stylesheet" href="Views/FlexibleSpaceNavigationItem.css">

307310 <script src="Protocol/WorkerTarget.js"></script>
308311
309312 <script src="Protocol/ApplicationCacheObserver.js"></script>
 313 <script src="Protocol/CPUProfilerObserver.js"></script>
310314 <script src="Protocol/CSSObserver.js"></script>
311315 <script src="Protocol/CanvasObserver.js"></script>
312316 <script src="Protocol/ConsoleObserver.js"></script>

344348 <script src="Models/BackForwardEntry.js"></script>
345349 <script src="Models/Branch.js"></script>
346350 <script src="Models/Breakpoint.js"></script>
347  <script src="Models/CallingContextTree.js"></script>
348  <script src="Models/CallingContextTreeNode.js"></script>
 351 <script src="Models/CPUInstrument.js"></script>
 352 <script src="Models/CPUTimelineRecord.js"></script>
349353 <script src="Models/CSSCompletions.js"></script>
350354 <script src="Models/CSSKeywordCompletions.js"></script>
351355 <script src="Models/CSSMedia.js"></script>

355359 <script src="Models/CSSStyleDeclaration.js"></script>
356360 <script src="Models/CSSStyleSheet.js"></script>
357361 <script src="Models/CallFrame.js"></script>
 362 <script src="Models/CallingContextTree.js"></script>
 363 <script src="Models/CallingContextTreeNode.js"></script>
358364 <script src="Models/Canvas.js"></script>
359365 <script src="Models/Collection.js"></script>
360366 <script src="Models/CollectionEntry.js"></script>

560566 <script src="Views/SettingsGroup.js"></script>
561567 <script src="Views/SettingsView.js"></script>
562568
 569 <script src="Views/AuditTestContentView.js"></script>
563570 <script src="Views/CollectionContentView.js"></script>
564571
565572 <script src="Views/ActivateButtonNavigationItem.js"></script>

569576 <script src="Views/ApplicationCacheFrameTreeElement.js"></script>
570577 <script src="Views/ApplicationCacheManifestTreeElement.js"></script>
571578 <script src="Views/AuditNavigationSidebarPanel.js"></script>
572  <script src="Views/AuditTestContentView.js"></script>
573579 <script src="Views/AuditTestCaseContentView.js"></script>
574580 <script src="Views/AuditTestGroupContentView.js"></script>
575581 <script src="Views/AuditTreeElement.js"></script>

578584 <script src="Views/BreakpointActionView.js"></script>
579585 <script src="Views/BreakpointTreeElement.js"></script>
580586 <script src="Views/ButtonToolbarItem.js"></script>
 587 <script src="Views/CPUTimelineOverviewGraph.js"></script>
 588 <script src="Views/CPUTimelineView.js"></script>
 589 <script src="Views/CPUUsageView.js"></script>
581590 <script src="Views/CSSStyleSheetTreeElement.js"></script>
582591 <script src="Views/CallFrameTreeElement.js"></script>
583592 <script src="Views/CallFrameView.js"></script>

597606 <script src="Views/CodeMirrorTextMarkers.js"></script>
598607 <script src="Views/ColorPicker.js"></script>
599608 <script src="Views/ColorWheel.js"></script>
 609 <script src="Views/ColumnChart.js"></script>
600610 <script src="Views/CompletionSuggestionsView.js"></script>
601611 <script src="Views/ComputedStyleDetailsPanel.js"></script>
602612 <script src="Views/ComputedStyleSection.js"></script>

Source/WebInspectorUI/UserInterface/Models/CPUInstrument.js

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WI.CPUInstrument = class CPUInstrument extends WI.Instrument
 27{
 28 constructor()
 29 {
 30 super();
 31
 32 console.assert(WI.CPUInstrument.supported());
 33 }
 34
 35 // Static
 36
 37 static supported()
 38 {
 39 // COMPATIBILITY (iOS 12): CPUProfiler domain did not exist.
 40 return InspectorBackend.domains.CPUProfiler;
 41 }
 42
 43 // Protected
 44
 45 get timelineRecordType()
 46 {
 47 return WI.TimelineRecord.Type.CPU;
 48 }
 49
 50 startInstrumentation(initiatedByBackend)
 51 {
 52 if (!initiatedByBackend)
 53 CPUProfilerAgent.startTracking();
 54 }
 55
 56 stopInstrumentation(initiatedByBackend)
 57 {
 58 if (!initiatedByBackend)
 59 CPUProfilerAgent.stopTracking();
 60 }
 61};

Source/WebInspectorUI/UserInterface/Models/CPUTimelineRecord.js

 1/*
 2 * Copyright (C) 2016 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WI.CPUTimelineRecord = class CPUTimelineRecord extends WI.TimelineRecord
 27{
 28 constructor(timestamp, usage)
 29 {
 30 super(WI.TimelineRecord.Type.CPU, timestamp, timestamp);
 31
 32 console.assert(typeof timestamp === "number");
 33 console.assert(typeof usage === "number");
 34 console.assert(usage >= 0);
 35
 36 this._timestamp = timestamp;
 37 this._usage = usage;
 38 }
 39
 40 // Public
 41
 42 get timestamp() { return this._timestamp; }
 43 get usage() { return this._usage; }
 44};

Source/WebInspectorUI/UserInterface/Models/Instrument.js

@@WI.Instrument = class Instrument
3838 return new WI.ScriptInstrument;
3939 case WI.TimelineRecord.Type.RenderingFrame:
4040 return new WI.FPSInstrument;
 41 case WI.TimelineRecord.Type.CPU:
 42 return new WI.CPUInstrument;
4143 case WI.TimelineRecord.Type.Memory:
4244 return new WI.MemoryInstrument;
4345 case WI.TimelineRecord.Type.HeapAllocations:

Source/WebInspectorUI/UserInterface/Models/TimelineRecord.js

@@WI.TimelineRecord.Type = {
158158 Layout: "timeline-record-type-layout",
159159 Script: "timeline-record-type-script",
160160 RenderingFrame: "timeline-record-type-rendering-frame",
 161 CPU: "timeline-record-type-cpu",
161162 Memory: "timeline-record-type-memory",
162163 HeapAllocations: "timeline-record-type-heap-allocations",
163164 Media: "timeline-record-type-media",

Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js

@@WI.TimelineRecording = class TimelineRecording extends WI.Object
211211 // Some records don't have source code timelines.
212212 if (record.type === WI.TimelineRecord.Type.Network
213213 || record.type === WI.TimelineRecord.Type.RenderingFrame
 214 || record.type === WI.TimelineRecord.Type.CPU
214215 || record.type === WI.TimelineRecord.Type.Memory
215216 || record.type === WI.TimelineRecord.Type.HeapAllocations
216217 || record.type === WI.TimelineRecord.Type.Media)

Source/WebInspectorUI/UserInterface/Protocol/CPUProfilerObserver.js

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WI.CPUProfilerObserver = class CPUProfilerObserver
 27{
 28 // Events defined by the "CPUProfiler" domain.
 29
 30 trackingStart(timestamp)
 31 {
 32 WI.timelineManager.cpuProfilerTrackingStarted(timestamp);
 33 }
 34
 35 trackingUpdate(event)
 36 {
 37 WI.timelineManager.cpuProfilerTrackingUpdated(event);
 38 }
 39
 40 trackingComplete(samples)
 41 {
 42 WI.timelineManager.cpuProfilerTrackingCompleted(samples);
 43 }
 44};

Source/WebInspectorUI/UserInterface/Protocol/MemoryObserver.js

@@WI.MemoryObserver = class MemoryObserver
3434
3535 trackingStart(timestamp)
3636 {
37  WI.timelineManager.memoryTrackingStart(timestamp);
 37 WI.timelineManager.memoryTrackingStarted(timestamp);
3838 }
3939
4040 trackingUpdate(event)
4141 {
42  WI.timelineManager.memoryTrackingUpdate(event);
 42 WI.timelineManager.memoryTrackingUpdated(event);
4343 }
4444
4545 trackingComplete()
4646 {
47  WI.timelineManager.memoryTrackingComplete();
 47 WI.timelineManager.memoryTrackingCompleted();
4848 }
4949};

Source/WebInspectorUI/UserInterface/Protocol/Target.js

@@WI.Target = class Target extends WI.Object
111111
112112 get AuditAgent() { return this._agents.Audit; }
113113 get ApplicationCacheAgent() { return this._agents.ApplicationCache; }
 114 get CPUProfilerAgent() { return this._agents.CPUProfiler; }
114115 get CSSAgent() { return this._agents.CSS; }
115116 get CanvasAgent() { return this._agents.Canvas; }
116117 get ConsoleAgent() { return this._agents.Console; }

Source/WebInspectorUI/UserInterface/Test.html

8080 <script src="Protocol/WorkerTarget.js"></script>
8181
8282 <script src="Protocol/InspectorObserver.js"></script>
 83 <script src="Protocol/CPUProfilerObserver.js"></script>
8384 <script src="Protocol/CSSObserver.js"></script>
8485 <script src="Protocol/CanvasObserver.js"></script>
8586 <script src="Protocol/ConsoleObserver.js"></script>

113114 <script src="Models/LocalScript.js"></script>
114115
115116 <script src="Models/Breakpoint.js"></script>
 117 <script src="Models/CPUInstrument.js"></script>
 118 <script src="Models/CPUTimelineRecord.js"></script>
116119 <script src="Models/CSSCompletions.js"></script>
117120 <script src="Models/CSSKeywordCompletions.js"></script>
118121 <script src="Models/CSSMedia.js"></script>

Source/WebInspectorUI/UserInterface/Test/Test.js

@@WI.loaded = function()
3838 InspectorBackend.registerMemoryDispatcher(new WI.MemoryObserver);
3939 InspectorBackend.registerDOMStorageDispatcher(new WI.DOMStorageObserver);
4040 InspectorBackend.registerScriptProfilerDispatcher(new WI.ScriptProfilerObserver);
 41 InspectorBackend.registerCPUProfilerDispatcher(new WI.CPUProfilerObserver);
4142 InspectorBackend.registerTimelineDispatcher(new WI.TimelineObserver);
4243 InspectorBackend.registerCSSDispatcher(new WI.CSSObserver);
4344 InspectorBackend.registerLayerTreeDispatcher(new WI.LayerTreeObserver);

Source/WebInspectorUI/UserInterface/Views/CPUTimelineOverviewGraph.css

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26body .sidebar > .panel.navigation.timeline > .timelines-content li.item.cpu,
 27body .timeline-overview > .graphs-container > .timeline-overview-graph.cpu {
 28 height: 72px;
 29}
 30
 31.timeline-overview-graph.cpu {
 32 position: relative;
 33}
 34
 35.timeline-overview-graph.cpu > .legend {
 36 position: absolute;
 37 top: 0;
 38 padding: 2px;
 39 font-size: 8px;
 40 color: hsl(0, 0%, 50%);
 41 background-color: white;
 42 pointer-events: none;
 43
 44 --cpu-timeline-overview-graph-legend-offset-end: 0;
 45}
 46
 47body[dir=ltr] .timeline-overview-graph.cpu > .legend {
 48 right: var(--cpu-timeline-overview-graph-legend-offset-end);
 49}
 50
 51body[dir=rtl] .timeline-overview-graph.cpu > .legend {
 52 left: var(--cpu-timeline-overview-graph-legend-offset-end);
 53}
 54
 55.timeline-overview-graph:nth-child(even) > .legend {
 56 background-color: hsl(0, 0%, 96%);
 57}
 58
 59body[dir=rtl] .timeline-overview-graph.cpu > .bar-chart {
 60 transform: scaleX(-1);
 61}
 62
 63.timeline-overview-graph.cpu > .bar-chart > svg > rect {
 64 stroke: var(--cpu-stroke-color);
 65 fill: var(--cpu-fill-color);
 66}

Source/WebInspectorUI/UserInterface/Views/CPUTimelineOverviewGraph.js

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WI.CPUTimelineOverviewGraph = class CPUTimelineOverviewGraph extends WI.TimelineOverviewGraph
 27{
 28 constructor(timeline, timelineOverview)
 29 {
 30 console.assert(timeline instanceof WI.Timeline);
 31 console.assert(timeline.type === WI.TimelineRecord.Type.CPU, timeline);
 32
 33 super(timelineOverview);
 34
 35 this.element.classList.add("cpu");
 36
 37 this._cpuTimeline = timeline;
 38 this._cpuTimeline.addEventListener(WI.Timeline.Event.RecordAdded, this._cpuTimelineRecordAdded, this);
 39
 40 let size = new WI.Size(0, this.height);
 41 this._chart = new WI.ColumnChart(size);
 42 this.element.appendChild(this._chart.element);
 43
 44 this._legendElement = this.element.appendChild(document.createElement("div"));
 45 this._legendElement.classList.add("legend");
 46
 47 this.reset();
 48 }
 49
 50 // Protected
 51
 52 get height()
 53 {
 54 return 72;
 55 }
 56
 57 reset()
 58 {
 59 super.reset();
 60
 61 this._maxUsage = 0;
 62 this._cachedMaxUsage = undefined;
 63
 64 this._updateLegend();
 65 this._chart.clear();
 66 this._chart.needsLayout();
 67 }
 68
 69 layout()
 70 {
 71 if (!this.visible)
 72 return;
 73
 74 this._updateLegend();
 75 this._chart.clear();
 76
 77 let graphWidth = this.timelineOverview.scrollContainerWidth;
 78 if (isNaN(graphWidth))
 79 return;
 80
 81 if (this._chart.size.width !== graphWidth || this._chart.size.height !== this.height)
 82 this._chart.size = new WI.Size(graphWidth, this.height);
 83
 84 let graphStartTime = this.startTime;
 85 let visibleEndTime = Math.min(this.endTime, this.currentTime);
 86 let secondsPerPixel = this.timelineOverview.secondsPerPixel;
 87 let maxCapacity = Math.max(20, this._maxUsage * 1.05); // Add 5% for padding.
 88
 89 // 500ms. This matches the ResourceUsageThread sampling frequency in the backend.
 90 const samplingRatePerSecond = 0.5;
 91
 92 function xScale(time) {
 93 return (time - graphStartTime) / secondsPerPixel;
 94 }
 95
 96 let height = this.height;
 97 function yScale(size) {
 98 return (size / maxCapacity) * height;
 99 }
 100
 101 const includeRecordBeforeStart = true;
 102 let visibleRecords = this._cpuTimeline.recordsInTimeRange(graphStartTime, visibleEndTime + (samplingRatePerSecond / 2), includeRecordBeforeStart);
 103 if (!visibleRecords.length)
 104 return;
 105
 106 function yScaleForRecord(record) {
 107 return yScale(record.usage);
 108 }
 109
 110 let intervalWidth = (samplingRatePerSecond / secondsPerPixel);
 111 const minimumDisplayHeight = 2;
 112
 113 // Bars for each record.
 114 for (let record of visibleRecords) {
 115 let w = intervalWidth;
 116 let h = Math.max(minimumDisplayHeight, yScale(record.usage));
 117 let x = xScale(record.startTime - (samplingRatePerSecond / 2));
 118 let y = height - h;
 119 this._chart.addBar(x, y, w, h);
 120 }
 121
 122 this._chart.updateLayout();
 123 }
 124
 125 // Private
 126
 127 _updateLegend()
 128 {
 129 if (this._cachedMaxUsage === this._maxUsage)
 130 return;
 131
 132 this._cachedMaxUsage = this._maxUsage;
 133
 134 if (!this._maxUsage) {
 135 this._legendElement.hidden = true;
 136 this._legendElement.textContent = "";
 137 } else {
 138 this._legendElement.hidden = false;
 139 this._legendElement.textContent = WI.UIString("Maximum CPU Usage: %s").format(Number.percentageString(this._maxUsage / 100));
 140 }
 141 }
 142
 143 _cpuTimelineRecordAdded(event)
 144 {
 145 let cpuTimelineRecord = event.data.record;
 146
 147 this._maxUsage = Math.max(this._maxUsage, cpuTimelineRecord.usage);
 148
 149 this.needsLayout();
 150 }
 151};

Source/WebInspectorUI/UserInterface/Views/CPUTimelineView.css

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26.timeline-view.cpu {
 27 overflow: scroll;
 28}
 29
 30.timeline-view.cpu > .content {
 31 width: 970px;
 32 margin: 10px auto;
 33}
 34
 35.timeline-view.cpu > .content .subtitle {
 36 font-family: -webkit-system-font, sans-serif;
 37 font-size: 14px;
 38}
 39
 40.timeline-view.cpu > .content > .details {
 41 position: relative;
 42}
 43
 44.timeline-view.cpu > .content > .details > .timeline-ruler {
 45 position: absolute;
 46 top: 5px;
 47 bottom: 0;
 48 right: 0;
 49 left: 0;
 50
 51 --cpu-timeline-view-details-timeline-ruler-offset-start: 150px;
 52}
 53
 54body[dir=ltr] .timeline-view.cpu > .content > .details > .timeline-ruler {
 55 left: var(--cpu-timeline-view-details-timeline-ruler-offset-start);
 56}
 57
 58body[dir=rtl] .timeline-view.cpu > .content > .details > .timeline-ruler {
 59 right: var(--cpu-timeline-view-details-timeline-ruler-offset-start);
 60}
 61
 62.timeline-view.cpu > .content > .details > .subtitle {
 63 padding: 0 10px 10px;
 64 border-bottom: 1px solid var(--border-color);
 65}
 66
 67.cpu-usage-view .line-chart > svg > path {
 68 stroke: var(--cpu-stroke-color);
 69 fill: var(--cpu-fill-color);
 70}
 71
 72.timeline-view.cpu .legend > .row > .swatch.current {
 73 border: 1px solid var(--cpu-max-comparison-stroke-color);
 74 background: var(--cpu-max-comparison-fill-color);
 75}

Source/WebInspectorUI/UserInterface/Views/CPUTimelineView.js

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WI.CPUTimelineView = class CPUTimelineView extends WI.TimelineView
 27{
 28 constructor(timeline, extraArguments)
 29 {
 30 console.assert(timeline.type === WI.TimelineRecord.Type.CPU, timeline);
 31
 32 super(timeline, extraArguments);
 33
 34 this._recording = extraArguments.recording;
 35 this._maxUsage = -Infinity;
 36
 37 this.element.classList.add("cpu");
 38
 39 let contentElement = this.element.appendChild(document.createElement("div"));
 40 contentElement.classList.add("content");
 41
 42 // FIXME: Overview with charts.
 43
 44 let detailsContainerElement = this._detailsContainerElement = contentElement.appendChild(document.createElement("div"));
 45 detailsContainerElement.classList.add("details");
 46
 47 this._timelineRuler = new WI.TimelineRuler;
 48 this.addSubview(this._timelineRuler);
 49 detailsContainerElement.appendChild(this._timelineRuler.element);
 50
 51 let detailsSubtitleElement = detailsContainerElement.appendChild(document.createElement("div"));
 52 detailsSubtitleElement.classList.add("subtitle");
 53 detailsSubtitleElement.textContent = WI.UIString("CPU Usage");
 54
 55 this._cpuUsageView = new WI.CPUUsageView;
 56 this._detailsContainerElement.appendChild(this._cpuUsageView.element);
 57
 58 timeline.addEventListener(WI.Timeline.Event.RecordAdded, this._cpuTimelineRecordAdded, this);
 59 }
 60
 61 // Public
 62
 63 shown()
 64 {
 65 super.shown();
 66
 67 this._timelineRuler.updateLayout(WI.View.LayoutReason.Resize);
 68 }
 69
 70 closed()
 71 {
 72 console.assert(this.representedObject instanceof WI.Timeline);
 73 this.representedObject.removeEventListener(null, null, this);
 74 }
 75
 76 reset()
 77 {
 78 super.reset();
 79
 80 this._maxUsage = -Infinity;
 81
 82 this._cpuUsageView.clear();
 83 }
 84
 85 get scrollableElements()
 86 {
 87 return [this.element];
 88 }
 89
 90 // Protected
 91
 92 get showsFilterBar() { return false; }
 93
 94 layout()
 95 {
 96 // Always update timeline ruler.
 97 this._timelineRuler.zeroTime = this.zeroTime;
 98 this._timelineRuler.startTime = this.startTime;
 99 this._timelineRuler.endTime = this.endTime;
 100
 101 let graphStartTime = this.startTime;
 102 let graphEndTime = this.endTime;
 103 let visibleEndTime = Math.min(this.endTime, this.currentTime);
 104
 105 let discontinuities = this._recording.discontinuitiesInTimeRange(graphStartTime, visibleEndTime);
 106
 107 // Don't include the record before the graph start if the graph start is within a gap.
 108 let includeRecordBeforeStart = !discontinuities.length || discontinuities[0].startTime > graphStartTime;
 109 let visibleRecords = this.representedObject.recordsInTimeRange(graphStartTime, visibleEndTime, includeRecordBeforeStart);
 110 if (!visibleRecords.length)
 111 return;
 112
 113 // Update total usage chart with the last record's data.
 114 let lastRecord = visibleRecords.lastValue;
 115
 116 // FIXME: Left chart.
 117 // FIXME: Right chart.
 118
 119 // FIXME: <https://webkit.org/b/153758> Web Inspector: Memory / CPU Timeline Views should be responsive / resizable
 120 const cpuUsageViewWidth = 800;
 121 const cpuUsageViewHeight = 150;
 122
 123 let secondsPerPixel = (graphEndTime - graphStartTime) / cpuUsageViewWidth;
 124
 125 let dataPoints = [];
 126 let max = -Infinity;
 127 let min = Infinity;
 128 let average = 0;
 129
 130 for (let record of visibleRecords) {
 131 let time = record.startTime;
 132 let usage = record.usage;
 133
 134 if (discontinuities.length && discontinuities[0].endTime < time) {
 135 let discontinuity = discontinuities.shift();
 136 dataPoints.push({time: discontinuity.startTime, size: 0});
 137 dataPoints.push({time: discontinuity.endTime, size: 0});
 138 dataPoints.push({time: discontinuity.endTime, size: usage});
 139 }
 140
 141 dataPoints.push({time, size: usage});
 142 max = Math.max(max, usage);
 143 min = Math.min(min, usage);
 144 average += usage;
 145 }
 146
 147 average /= visibleRecords.length;
 148
 149 // If the graph end time is inside a gap, the last data point should
 150 // only be extended to the start of the discontinuity.
 151 if (discontinuities.length)
 152 visibleEndTime = discontinuities[0].startTime;
 153
 154 function layoutView(view, {dataPoints, min, max, average}) {
 155 if (min === Infinity)
 156 min = 0;
 157 if (max === -Infinity)
 158 max = 0;
 159
 160 // Zoom in to the top of each graph to accentuate small changes.
 161 let graphMin = min * 0.95;
 162 let graphMax = (max * 1.05) - graphMin;
 163
 164 function xScale(time) {
 165 return (time - graphStartTime) / secondsPerPixel;
 166 }
 167 function yScale(size) {
 168 return cpuUsageViewHeight - (((size - graphMin) / graphMax) * cpuUsageViewHeight);
 169 }
 170
 171 view.layoutWithDataPoints(dataPoints, visibleEndTime, min, max, average, xScale, yScale);
 172 }
 173
 174 layoutView(this._cpuUsageView, {dataPoints, min, max, average});
 175 }
 176
 177 // Private
 178
 179 _cpuTimelineRecordAdded(event)
 180 {
 181 let cpuTimelineRecord = event.data.record;
 182 console.assert(cpuTimelineRecord instanceof WI.CPUTimelineRecord);
 183
 184 this._maxUsage = Math.max(this._maxUsage, cpuTimelineRecord.usage);
 185
 186 if (cpuTimelineRecord.startTime >= this.startTime && cpuTimelineRecord.endTime <= this.endTime)
 187 this.needsLayout();
 188 }
 189};

Source/WebInspectorUI/UserInterface/Views/CPUUsageView.css

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26.cpu-usage-view {
 27 display: flex;
 28 border-bottom: 1px solid var(--border-color);
 29}
 30
 31.cpu-usage-view > .details {
 32 width: 150px;
 33 padding-top: 10px;
 34 font-family: -webkit-system-font, sans-serif;
 35 font-size: 12px;
 36 color: hsl(0, 0%, 70%);
 37 -webkit-padding-start: 15px;
 38
 39 --cpu-usage-view-details-border-end: 1px solid var(--border-color);
 40}
 41
 42body[dir=ltr] .cpu-usage-view > .details {
 43 border-right: var(--cpu-usage-view-details-border-end);
 44}
 45
 46body[dir=rtl] .cpu-usage-view > .details {
 47 border-left: var(--cpu-usage-view-details-border-end);
 48}
 49
 50.cpu-usage-view > .graph {
 51 position: relative;
 52 bottom: -3px;
 53}
 54
 55body[dir=rtl] .cpu-usage-view > .graph {
 56 transform: scaleX(-1);
 57}

Source/WebInspectorUI/UserInterface/Views/CPUUsageView.js

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26WI.CPUUsageView = class CPUUsageView
 27{
 28 constructor()
 29 {
 30 this._element = document.createElement("div");
 31 this._element.classList.add("cpu-usage-view");
 32
 33 this._detailsElement = this._element.appendChild(document.createElement("div"));
 34 this._detailsElement.classList.add("details");
 35
 36 this._detailsAverageElement = this._detailsElement.appendChild(document.createElement("span"));
 37 this._detailsElement.appendChild(document.createElement("br"));
 38 this._detailsMaxElement = this._detailsElement.appendChild(document.createElement("span"));
 39 this._detailsElement.appendChild(document.createElement("br"));
 40 this._detailsMinElement = this._detailsElement.appendChild(document.createElement("span"));
 41 this._updateDetails(NaN, NaN);
 42
 43 this._graphElement = this._element.appendChild(document.createElement("div"));
 44 this._graphElement.classList.add("graph");
 45
 46 // FIXME: <https://webkit.org/b/153758> Web Inspector: Memory / CPU Timeline Views should be responsive / resizable
 47 let size = new WI.Size(800, 150);
 48 this._chart = new WI.LineChart(size);
 49 this._graphElement.appendChild(this._chart.element);
 50 }
 51
 52 // Public
 53
 54 get element() { return this._element; }
 55
 56 clear()
 57 {
 58 this._cachedAverageSize = undefined;
 59 this._cachedMinSize = undefined;
 60 this._cachedMaxSize = undefined;
 61 this._updateDetails(NaN, NaN);
 62
 63 this._chart.clear();
 64 this._chart.needsLayout();
 65 }
 66
 67 layoutWithDataPoints(dataPoints, lastTime, minSize, maxSize, averageSize, xScale, yScale)
 68 {
 69 console.assert(minSize >= 0);
 70 console.assert(maxSize >= 0);
 71 console.assert(minSize <= maxSize);
 72
 73 this._updateDetails(minSize, maxSize, averageSize);
 74 this._chart.clear();
 75
 76 if (!dataPoints.length)
 77 return;
 78
 79 // Ensure an empty graph is empty.
 80 if (!maxSize)
 81 return;
 82
 83 // Extend the first data point to the start so it doesn't look like we originate at zero size.
 84 let firstX = 0;
 85 let firstY = yScale(dataPoints[0].size);
 86 this._chart.addPoint(firstX, firstY);
 87
 88 // Points for data points.
 89 for (let dataPoint of dataPoints) {
 90 let x = xScale(dataPoint.time);
 91 let y = yScale(dataPoint.size);
 92 this._chart.addPoint(x, y);
 93 }
 94
 95 // Extend the last data point to the end time.
 96 let lastDataPoint = dataPoints.lastValue;
 97 let lastX = Math.floor(xScale(lastTime));
 98 let lastY = yScale(lastDataPoint.size);
 99 this._chart.addPoint(lastX, lastY);
 100
 101 this._chart.updateLayout();
 102 }
 103
 104 // Private
 105
 106 _updateDetails(minSize, maxSize, averageSize)
 107 {
 108 if (this._cachedMinSize === minSize && this._cachedMaxSize === maxSize && this._cachedAverageSize === averageSize)
 109 return;
 110
 111 this._cachedAverageSize = averageSize;
 112 this._cachedMinSize = minSize;
 113 this._cachedMaxSize = maxSize;
 114
 115 this._detailsAverageElement.textContent = WI.UIString("Average: %s").format(Number.isFinite(maxSize) ? Number.percentageString(averageSize / 100) : emDash);
 116 this._detailsMaxElement.textContent = WI.UIString("Highest: %s").format(Number.isFinite(maxSize) ? Number.percentageString(maxSize / 100) : emDash);
 117 this._detailsMinElement.textContent = WI.UIString("Lowest: %s").format(Number.isFinite(minSize) ? Number.percentageString(minSize / 100) : emDash);
 118 }
 119};

Source/WebInspectorUI/UserInterface/Views/ColumnChart.js

 1/*
 2 * Copyright (C) 2019 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 23 * THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26// ColumnChart creates a single filled line chart.
 27//
 28// Initialize the chart with a size. You can then include a new bar
 29// in the bar chart by providing an (x, y, w, h) via `addBar`.
 30//
 31// SVG:
 32//
 33// - There is a single rect for each bar.
 34//
 35// <div class="line-chart">
 36// <svg width="800" height="75" viewbox="0 0 800 75">
 37// <rect width="<w>" height="<h>" transform="translate(<x>, <y>)" />
 38// <rect width="<w>" height="<h>" transform="translate(<x>, <y>)" />
 39// </svg>
 40// </div>
 41
 42WI.ColumnChart = class ColumnChart
 43{
 44 constructor(size)
 45 {
 46 this._element = document.createElement("div");
 47 this._element.classList.add("bar-chart");
 48
 49 this._svgElement = this._element.appendChild(createSVGElement("svg"));
 50
 51 this._bars = [];
 52 this.size = size;
 53 }
 54
 55 // Public
 56
 57 get element() { return this._element; }
 58 get bars() { return this._bars; }
 59
 60 get size()
 61 {
 62 return this._size;
 63 }
 64
 65 set size(size)
 66 {
 67 this._size = size;
 68
 69 this._svgElement.setAttribute("width", size.width);
 70 this._svgElement.setAttribute("height", size.height);
 71 this._svgElement.setAttribute("viewbox", `0 0 ${size.width} ${size.height}`);
 72 }
 73
 74 addBar(x, y, width, height)
 75 {
 76 this._bars.push({x, y, width, height});
 77 }
 78
 79 clear()
 80 {
 81 this._bars = [];
 82 }
 83
 84 needsLayout()
 85 {
 86 if (this._scheduledLayoutUpdateIdentifier)
 87 return;
 88
 89 this._scheduledLayoutUpdateIdentifier = requestAnimationFrame(this.updateLayout.bind(this));
 90 }
 91
 92 updateLayout()
 93 {
 94 if (this._scheduledLayoutUpdateIdentifier) {
 95 cancelAnimationFrame(this._scheduledLayoutUpdateIdentifier);
 96 this._scheduledLayoutUpdateIdentifier = undefined;
 97 }
 98
 99 this._svgElement.removeChildren();
 100
 101 for (let {x, y, width, height} of this._bars) {
 102 let rect = this._svgElement.appendChild(createSVGElement("rect"));
 103 rect.setAttribute("width", width);
 104 rect.setAttribute("height", height);
 105 rect.setAttribute("transform", `translate(${x}, ${y})`);
 106 }
 107 }
 108};

Source/WebInspectorUI/UserInterface/Views/ContentView.js

@@WI.ContentView = class ContentView extends WI.View
8383 if (timelineType === WI.TimelineRecord.Type.RenderingFrame)
8484 return new WI.RenderingFrameTimelineView(representedObject, extraArguments);
8585
 86 if (timelineType === WI.TimelineRecord.Type.CPU)
 87 return new WI.CPUTimelineView(representedObject, extraArguments);
 88
8689 if (timelineType === WI.TimelineRecord.Type.Memory)
8790 return new WI.MemoryTimelineView(representedObject, extraArguments);
8891

Source/WebInspectorUI/UserInterface/Views/MemoryCategoryView.css

3131.memory-category-view > .details {
3232 width: 150px;
3333 padding-top: 10px;
34  font-family: '-webkit-system-font';
 34 font-family: -webkit-system-font, sans-serif;
3535 font-size: 12px;
3636 color: hsl(0, 0%, 70%);
 37 -webkit-padding-start: 15px;
3738
38  --memory-category-view-details-padding-start: 15px;
3939 --memory-category-view-details-border-end: 1px solid var(--border-color);
4040}
4141
4242body[dir=ltr] .memory-category-view > .details {
43  padding-left: var(--memory-category-view-details-padding-start);
4443 border-right: var(--memory-category-view-details-border-end);
4544}
4645
4746body[dir=rtl] .memory-category-view > .details {
48  padding-right: var(--memory-category-view-details-padding-start);
4947 border-left: var(--memory-category-view-details-border-end);
5048}
5149

Source/WebInspectorUI/UserInterface/Views/MemoryCategoryView.js

2323 * THE POSSIBILITY OF SUCH DAMAGE.
2424 */
2525
26 WI.MemoryCategoryView = class MemoryCategoryView extends WI.Object
 26WI.MemoryCategoryView = class MemoryCategoryView
2727{
2828 constructor(category, displayName)
2929 {
30  super();
31 
3230 console.assert(typeof category === "string");
3331
3432 this._category = category;

@@WI.MemoryCategoryView = class MemoryCategoryView extends WI.Object
5149 this._graphElement = this._element.appendChild(document.createElement("div"));
5250 this._graphElement.classList.add("graph");
5351
54  // FIXME: <https://webkit.org/b/153758> Web Inspector: Memory Timeline View should be responsive / resizable
 52 // FIXME: <https://webkit.org/b/153758> Web Inspector: Memory / CPU Timeline Views should be responsive / resizable
5553 let size = new WI.Size(800, 75);
5654 this._chart = new WI.LineChart(size);
5755 this._graphElement.appendChild(this._chart.element);

@@WI.MemoryCategoryView = class MemoryCategoryView extends WI.Object
6664 {
6765 this._cachedMinSize = undefined;
6866 this._cachedMaxSize = undefined;
 67 this._updateDetails(NaN, NaN);
6968
7069 this._chart.clear();
7170 this._chart.needsLayout();

Source/WebInspectorUI/UserInterface/Views/MemoryTimelineOverviewGraph.js

@@WI.MemoryTimelineOverviewGraph = class MemoryTimelineOverviewGraph extends WI.Ti
2727{
2828 constructor(timeline, timelineOverview)
2929 {
 30 console.assert(timeline instanceof WI.MemoryTimeline);
 31
3032 super(timelineOverview);
3133
3234 this.element.classList.add("memory");
3335
34  console.assert(timeline instanceof WI.MemoryTimeline);
35 
3636 this._memoryTimeline = timeline;
3737 this._memoryTimeline.addEventListener(WI.Timeline.Event.RecordAdded, this._memoryTimelineRecordAdded, this);
3838 this._memoryTimeline.addEventListener(WI.MemoryTimeline.Event.MemoryPressureEventAdded, this._memoryTimelineMemoryPressureEventAdded, this);

Source/WebInspectorUI/UserInterface/Views/MemoryTimelineView.css

3939}
4040
4141.timeline-view.memory > .content .subtitle {
42  font-family: '-webkit-system-font';
 42 font-family: -webkit-system-font, sans-serif;
4343 font-size: 14px;
4444}
4545

Source/WebInspectorUI/UserInterface/Views/MemoryTimelineView.js

@@WI.MemoryTimelineView = class MemoryTimelineView extends WI.TimelineView
4141 let overviewElement = contentElement.appendChild(document.createElement("div"));
4242 overviewElement.classList.add("overview");
4343
44  function createChartContainer(parentElement, subtitle, tooltip)
45  {
 44 function createChartContainer(parentElement, subtitle, tooltip) {
4645 let chartElement = parentElement.appendChild(document.createElement("div"));
4746 chartElement.classList.add("chart");
4847

@@WI.MemoryTimelineView = class MemoryTimelineView extends WI.TimelineView
120119 this._timelineRuler.updateLayout(WI.View.LayoutReason.Resize);
121120 }
122121
123  hidden()
124  {
125  super.hidden();
126  }
127 
128122 closed()
129123 {
130124 console.assert(this.representedObject instanceof WI.Timeline);

@@WI.MemoryTimelineView = class MemoryTimelineView extends WI.TimelineView
200194 this._maxComparisonCircleChart.updateLayout();
201195 this._updateMaxComparisonLegend(lastRecord.totalSize);
202196
203  // FIXME: <https://webkit.org/b/153758> Web Inspector: Memory Timeline View should be responsive / resizable
 197 // FIXME: <https://webkit.org/b/153758> Web Inspector: Memory / CPU Timeline Views should be responsive / resizable
204198 const categoryViewWidth = 800;
205199 const categoryViewHeight = 75;
206200

@@WI.MemoryTimelineView = class MemoryTimelineView extends WI.TimelineView
310304
311305 _clearMaxComparisonLegend()
312306 {
313  this._maxComparisonMaximumSizeElement.textContent = emDash;
314  this._maxComparisonCurrentSizeElement.textContent = emDash;
 307 if (this._maxComparisonMaximumSizeElement)
 308 this._maxComparisonMaximumSizeElement.textContent = emDash;
 309 if (this._maxComparisonCurrentSizeElement)
 310 this._maxComparisonCurrentSizeElement.textContent = emDash;
315311
316312 let totalElement = this._maxComparisonCircleChart.centerElement.firstChild;
317313 if (totalElement)

Source/WebInspectorUI/UserInterface/Views/ResourceSizesContentView.css

2424 */
2525
2626.resource-sizes {
27  font-family: '-webkit-system-font';
 27 font-family: -webkit-system-font, sans-serif;
2828}
2929
3030.resource-sizes > .content {

Source/WebInspectorUI/UserInterface/Views/TimelineIcons.css

3131 content: url(../Images/ScriptsInstrument.svg);
3232}
3333
 34.cpu-icon .icon {
 35 content: url(../Images/CPUInstrument.svg);
 36}
 37
3438.memory-icon .icon {
3539 content: url(../Images/MemoryInstrument.svg);
3640}

Source/WebInspectorUI/UserInterface/Views/TimelineOverviewGraph.js

@@WI.TimelineOverviewGraph = class TimelineOverviewGraph extends WI.View
6363 if (timelineType === WI.TimelineRecord.Type.RenderingFrame)
6464 return new WI.RenderingFrameTimelineOverviewGraph(timeline, timelineOverview);
6565
 66 if (timelineType === WI.TimelineRecord.Type.CPU)
 67 return new WI.CPUTimelineOverviewGraph(timeline, timelineOverview);
 68
6669 if (timelineType === WI.TimelineRecord.Type.Memory)
6770 return new WI.MemoryTimelineOverviewGraph(timeline, timelineOverview);
6871

Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js

@@WI.TimelineTabContentView = class TimelineTabContentView extends WI.ContentBrows
116116 return WI.UIString("JavaScript & Events");
117117 case WI.TimelineRecord.Type.RenderingFrame:
118118 return WI.UIString("Rendering Frames");
 119 case WI.TimelineRecord.Type.CPU:
 120 return WI.UIString("CPU");
119121 case WI.TimelineRecord.Type.Memory:
120122 return WI.UIString("Memory");
121123 case WI.TimelineRecord.Type.HeapAllocations:

@@WI.TimelineTabContentView = class TimelineTabContentView extends WI.ContentBrows
136138 return "network-icon";
137139 case WI.TimelineRecord.Type.Layout:
138140 return "layout-icon";
 141 case WI.TimelineRecord.Type.CPU:
 142 return "cpu-icon";
139143 case WI.TimelineRecord.Type.Memory:
140144 return "memory-icon";
141145 case WI.TimelineRecord.Type.HeapAllocations:

@@WI.TimelineTabContentView = class TimelineTabContentView extends WI.ContentBrows
160164 return "network";
161165 case WI.TimelineRecord.Type.Layout:
162166 return "colors";
 167 case WI.TimelineRecord.Type.CPU:
 168 return "cpu";
163169 case WI.TimelineRecord.Type.Memory:
164170 return "memory";
165171 case WI.TimelineRecord.Type.HeapAllocations:

@@WI.TimelineTabContentView = class TimelineTabContentView extends WI.ContentBrows
248254
249255 break;
250256
 257 case WI.TimelineRecord.Type.CPU:
251258 case WI.TimelineRecord.Type.Memory:
252259 // Not used. Fall through to error just in case.
253260

@@WI.TimelineTabContentView = class TimelineTabContentView extends WI.ContentBrows
275282 return WI.UIString("Snapshot %d").format(timelineRecord.heapSnapshot.identifier);
276283 case WI.TimelineRecord.Type.Media:
277284 return timelineRecord.displayName;
 285 case WI.TimelineRecord.Type.CPU:
278286 case WI.TimelineRecord.Type.Memory:
279287 // Not used. Fall through to error just in case.
280288 default:

Source/WebInspectorUI/UserInterface/Views/Variables.css

116116 --memory-max-comparison-fill-color: hsl(220, 10%, 75%);
117117 --memory-max-comparison-stroke-color: hsl(220, 10%, 55%);
118118
 119 --cpu-stroke-color: hsl(118, 33%, 42%);
 120 --cpu-fill-color: hsl(118, 43%, 55%);
 121
119122 --network-header-color: hsl(204, 52%, 55%);
120123 --network-system-color: hsl(79, 32%, 50%);
121124 --network-pseudo-header-color: hsl(312, 35%, 51%);