├── .eslintignore ├── .gitignore ├── .travis.yml ├── lib ├── third_party │ └── tracing │ │ ├── base │ │ ├── guid.js │ │ ├── units │ │ │ ├── scalar.js │ │ │ ├── time_stamp.js │ │ │ └── time_display_mode.js │ │ ├── category_util.js │ │ ├── extension_registry.js │ │ ├── math.js │ │ ├── event.js │ │ ├── extension_registry_base.js │ │ ├── utils.js │ │ ├── extension_registry_basic.js │ │ └── rect.js │ │ ├── extras │ │ ├── importer │ │ │ ├── jszip.js │ │ │ ├── zip_importer.js │ │ │ ├── linux_perf │ │ │ │ ├── drm_parser.js │ │ │ │ ├── clock_parser.js │ │ │ │ ├── bus_parser.js │ │ │ │ ├── parser.js │ │ │ │ ├── kfunc_parser.js │ │ │ │ ├── workqueue_parser.js │ │ │ │ ├── sched_parser.js │ │ │ │ ├── cpufreq_parser.js │ │ │ │ ├── sync_parser.js │ │ │ │ └── exynos_parser.js │ │ │ ├── trace_code_entry.js │ │ │ └── trace_code_map.js │ │ ├── rail │ │ │ ├── idle_interaction_record.js │ │ │ ├── response_interaction_record.js │ │ │ ├── load_interaction_record.js │ │ │ ├── animation_interaction_record.js │ │ │ └── rail_score.js │ │ └── chrome │ │ │ ├── chrome_gpu_helper.js │ │ │ ├── chrome_renderer_helper.js │ │ │ ├── chrome_process_helper.js │ │ │ ├── chrome_model_helper.js │ │ │ └── chrome_browser_helper.js │ │ ├── ui │ │ ├── annotations │ │ │ ├── annotation_view.js │ │ │ ├── x_marker_annotation_view.js │ │ │ ├── rect_annotation_view.js │ │ │ └── comment_box_annotation_view.js │ │ └── base │ │ │ ├── utils.js │ │ │ └── deep_utils.js │ │ ├── importer │ │ ├── empty_importer.js │ │ ├── simple_line_reader.js │ │ └── importer.js │ │ ├── model │ │ ├── event_info.js │ │ ├── compound_event_selection_state.js │ │ ├── x_marker_annotation.js │ │ ├── source_info │ │ │ ├── source_info.js │ │ │ └── js_source_info.js │ │ ├── model_indices.js │ │ ├── alert.js │ │ ├── event.js │ │ ├── selectable_item.js │ │ ├── comment_box_annotation.js │ │ ├── timed_event.js │ │ ├── power_sample.js │ │ ├── flow_event.js │ │ ├── cpu_slice.js │ │ ├── rect_annotation.js │ │ ├── sample.js │ │ ├── thread_slice.js │ │ ├── heap_dump.js │ │ ├── selection_state.js │ │ ├── annotation.js │ │ ├── instant_event.js │ │ ├── container_memory_dump.js │ │ ├── interaction_record.js │ │ ├── frame.js │ │ ├── device.js │ │ ├── counter_sample.js │ │ ├── stack_frame.js │ │ ├── object_snapshot.js │ │ ├── event_registry.js │ │ ├── ir_coverage.js │ │ ├── power_series.js │ │ ├── counter_series.js │ │ ├── event_container.js │ │ ├── memory_allocator_dump.js │ │ ├── kernel.js │ │ └── async_slice.js │ │ └── core │ │ ├── auditor.js │ │ └── filter.js ├── tracing-config.js └── global-config.js ├── index.js ├── package.json ├── CONTRIBUTING.md ├── .eslintrc └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | lib/third_party/tracing/ 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.pyc 3 | .DS_Store 4 | dist 5 | init.sh 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - 'stable' 5 | - '0.12' 6 | -------------------------------------------------------------------------------- /lib/third_party/tracing/base/guid.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./base.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.b', function() { 12 | var nextGUID = 1; 13 | var GUID = { 14 | allocate: function() { 15 | return nextGUID++; 16 | }, 17 | 18 | getLastGuid: function() { 19 | return nextGUID - 1; 20 | } 21 | }; 22 | 23 | return { 24 | GUID: GUID 25 | }; 26 | }); 27 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/jszip.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../base/base.js"); 8 | 9 | 'use strict'; 10 | // Workaround for JSzip requiring window. 11 | if (tr.isHeadless) { 12 | /** 13 | * Hack. 14 | */ 15 | global.window = {}; 16 | } 17 | 18 | 'use strict'; 19 | // Workaround for JSzip requiring window. 20 | if (tr.isHeadless) { 21 | /** 22 | * Hack. 23 | */ 24 | global.JSZip = global.window.JSZip; 25 | global.window = undefined; 26 | } 27 | -------------------------------------------------------------------------------- /lib/third_party/tracing/base/units/scalar.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./time_display_mode.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.b.u', function() { 12 | /** 13 | * Scalar wrapper, representing a scalar value and its unit. 14 | */ 15 | function Scalar(value, unit) { 16 | this.value = value; 17 | this.unit = unit; 18 | }; 19 | 20 | Scalar.prototype = { 21 | toString: function() { 22 | return this.unit.format(this.value); 23 | } 24 | }; 25 | 26 | return { 27 | Scalar: Scalar 28 | }; 29 | }); 30 | -------------------------------------------------------------------------------- /lib/third_party/tracing/ui/annotations/annotation_view.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../base/base.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.ui.annotations', function() { 12 | /** 13 | * A base class for all annotation views. 14 | * @constructor 15 | */ 16 | function AnnotationView(viewport, annotation) { 17 | } 18 | 19 | AnnotationView.prototype = { 20 | draw: function(ctx) { 21 | throw new Error('Not implemented'); 22 | } 23 | }; 24 | 25 | return { 26 | AnnotationView: AnnotationView 27 | }; 28 | }); 29 | -------------------------------------------------------------------------------- /lib/third_party/tracing/base/units/time_stamp.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./scalar.js"); 8 | require("./time_display_mode.js"); 9 | 10 | 'use strict'; 11 | 12 | global.tr.exportTo('tr.b.u', function() { 13 | /** 14 | * Float wrapper, representing a time stamp, capable of pretty-printing. 15 | */ 16 | function TimeStamp(timestamp) { 17 | tr.b.u.Scalar.call(this, timestamp, tr.b.u.Units.timeStampInMs); 18 | }; 19 | 20 | TimeStamp.prototype = { 21 | __proto__: tr.b.u.Scalar.prototype, 22 | 23 | get timestamp() { 24 | return this.value; 25 | } 26 | }; 27 | 28 | TimeStamp.format = function(timestamp) { 29 | return tr.b.u.Units.timeStampInMs.format(timestamp); 30 | }; 31 | 32 | return { 33 | TimeStamp: TimeStamp 34 | }; 35 | }); 36 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2015 Google Inc. All Rights Reserved. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | 'use strict'; 19 | 20 | var processor = require('./lib/processor'); 21 | 22 | module.exports = { 23 | 24 | RESPONSE: processor.RESPONSE, 25 | ANIMATION: processor.ANIMATION, 26 | LOAD: processor.LOAD, 27 | 28 | analyze: function (traceContents, opts) { 29 | return processor.analyzeTrace(traceContents, opts); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bigrig", 3 | "version": "1.3.0", 4 | "description": "A CLI and node module for parsing trace (timeline) files from Chrome.", 5 | "main": "index.js", 6 | "bin": { 7 | "bigrig": "bigrig.js" 8 | }, 9 | "engines": { 10 | "node": ">=4.0.0" 11 | }, 12 | "dependencies": { 13 | "cli-color": "^1.1.0", 14 | "mkdirp": "^0.5.1", 15 | "yargs": "^3.29.0" 16 | }, 17 | "devDependencies": { 18 | "babel-eslint": "^4.1.3", 19 | "chai": "^3.4.0", 20 | "eslint": "^1.8.0", 21 | "mocha": "^2.3.3" 22 | }, 23 | "scripts": { 24 | "test": "eslint . && mocha test/*.js --timeout 60000" 25 | }, 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/GoogleChrome/node-big-rig.git" 29 | }, 30 | "keywords": [ 31 | "chrome", 32 | "trace", 33 | "cli" 34 | ], 35 | "author": "Paul Lewis (Google)", 36 | "license": "Apache-2.0", 37 | "bugs": { 38 | "url": "https://github.com/GoogleChrome/node-big-rig/issues" 39 | }, 40 | "homepage": "https://github.com/GoogleChrome/node-big-rig#readme" 41 | } 42 | -------------------------------------------------------------------------------- /lib/tracing-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2015 Google Inc. All Rights Reserved. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* global tr */ 19 | 20 | // Sets up a few stubs for tracing, particularly for the HTML Elements it 21 | // expects to exist, which won't because this is running in Node. 22 | tr.isHeadless = false; 23 | tr.ui.b.Overlay = function () { 24 | return { 25 | title: '', 26 | msgEl: { 27 | style: { 28 | margin: '' 29 | } 30 | }, 31 | appendChild: function () { 32 | } 33 | }; 34 | }; 35 | -------------------------------------------------------------------------------- /lib/third_party/tracing/importer/empty_importer.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/base.js"); 8 | require("./importer.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview Base class for trace data importers. 14 | */ 15 | global.tr.exportTo('tr.importer', function() { 16 | /** 17 | * Importer for empty strings and arrays. 18 | * @constructor 19 | */ 20 | function EmptyImporter(events) { 21 | this.importPriority = 0; 22 | }; 23 | 24 | EmptyImporter.canImport = function(eventData) { 25 | if (eventData instanceof Array && eventData.length == 0) 26 | return true; 27 | if (typeof(eventData) === 'string' || eventData instanceof String) { 28 | return eventData.length == 0; 29 | } 30 | return false; 31 | }; 32 | 33 | EmptyImporter.prototype = { 34 | __proto__: tr.importer.Importer.prototype 35 | }; 36 | 37 | tr.importer.Importer.register(EmptyImporter); 38 | 39 | return { 40 | EmptyImporter: EmptyImporter 41 | }; 42 | }); 43 | -------------------------------------------------------------------------------- /lib/third_party/tracing/base/category_util.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./base.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Helper code for working with tracing categories. 13 | * 14 | */ 15 | global.tr.exportTo('tr.b', function() { 16 | 17 | // Cached values for getCategoryParts. 18 | var categoryPartsFor = {}; 19 | 20 | /** 21 | * Categories are stored in comma-separated form, e.g: 'a,b' meaning 22 | * that the event is part of the a and b category. 23 | * 24 | * This function returns the category split by string, caching the 25 | * array for performance. 26 | * 27 | * Do not mutate the returned array!!!! 28 | */ 29 | function getCategoryParts(category) { 30 | var parts = categoryPartsFor[category]; 31 | if (parts !== undefined) 32 | return parts; 33 | parts = category.split(','); 34 | categoryPartsFor[category] = parts; 35 | return parts; 36 | } 37 | 38 | return { 39 | getCategoryParts: getCategoryParts 40 | }; 41 | }); 42 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/rail/idle_interaction_record.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./rail_interaction_record.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Base class for trace data Auditors. 13 | */ 14 | global.tr.exportTo('tr.e.rail', function() { 15 | function IdleInteractionRecord(parentModel, start, duration) { 16 | tr.e.rail.RAILInteractionRecord.call( 17 | this, parentModel, 'Idle', 'rail_idle', 18 | start, duration); 19 | } 20 | 21 | IdleInteractionRecord.prototype = { 22 | __proto__: tr.e.rail.RAILInteractionRecord.prototype, 23 | 24 | get normalizedUserComfort() { 25 | return 1; 26 | }, 27 | 28 | // Unlike during active IRs, while the user is idle, the CPU should not be 29 | // utilized much. 30 | 31 | get minCpuFraction() { 32 | return 0.1; 33 | }, 34 | 35 | get maxCpuFraction() { 36 | return 1; 37 | } 38 | }; 39 | 40 | return { 41 | IdleInteractionRecord: IdleInteractionRecord 42 | }; 43 | }); 44 | -------------------------------------------------------------------------------- /lib/third_party/tracing/ui/annotations/x_marker_annotation_view.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./annotation_view.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.ui.annotations', function() { 12 | /** 13 | * A view that draws a vertical line on the timeline at a specific timestamp. 14 | * @extends {AnnotationView} 15 | * @constructor 16 | */ 17 | function XMarkerAnnotationView(viewport, annotation) { 18 | this.viewport_ = viewport; 19 | this.annotation_ = annotation; 20 | } 21 | 22 | XMarkerAnnotationView.prototype = { 23 | __proto__: tr.ui.annotations.AnnotationView.prototype, 24 | 25 | draw: function(ctx) { 26 | var dt = this.viewport_.currentDisplayTransform; 27 | var viewX = dt.xWorldToView(this.annotation_.timestamp); 28 | 29 | ctx.beginPath(); 30 | tr.ui.b.drawLine(ctx, viewX, 0, viewX, ctx.canvas.height); 31 | ctx.strokeStyle = this.annotation_.strokeStyle; 32 | ctx.stroke(); 33 | } 34 | }; 35 | 36 | return { 37 | XMarkerAnnotationView: XMarkerAnnotationView 38 | }; 39 | }); 40 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/event_info.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/color_scheme.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.model', function() { 12 | var ColorScheme = tr.b.ColorScheme; 13 | 14 | /** 15 | * EventInfo is an annotation added to Events in order to document 16 | * what they represent, and override their title/colorId values. 17 | * 18 | * TODO(ccraik): eventually support more complex structure/paragraphs. 19 | * 20 | * @param {string} title A user-visible title for the event. 21 | * @param {string} description A user-visible description of the event. 22 | * @param {Array} docLinks A list of Objects, each of the form 23 | * {label: str, textContent: str, href: str} 24 | * 25 | * @constructor 26 | */ 27 | function EventInfo(title, description, docLinks) { 28 | this.title = title; 29 | this.description = description; 30 | this.docLinks = docLinks; 31 | this.colorId = ColorScheme.getColorIdForGeneralPurposeString(title); 32 | } 33 | 34 | return { 35 | EventInfo: EventInfo 36 | }; 37 | }); 38 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/compound_event_selection_state.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/base.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.model', function() { 12 | 13 | /** 14 | * Indicates how much of a compound-event is selected [if any]. 15 | * 16 | * The CompoundEventSelectionState enum is used with events that are 17 | * directly selectable, but also have associated events, too, that can be 18 | * selected. In this situation, there are a variety of different 19 | * selected states other than just "yes, no". This enum encodes those 20 | * various possible states. 21 | */ 22 | var CompoundEventSelectionState = { 23 | // Basic bit states. 24 | NOT_SELECTED: 0, 25 | EVENT_SELECTED: 0x1, 26 | SOME_ASSOCIATED_EVENTS_SELECTED: 0x2, 27 | ALL_ASSOCIATED_EVENTS_SELECTED: 0x4, 28 | 29 | // Common combinations. 30 | EVENT_AND_SOME_ASSOCIATED_SELECTED: 0x1 | 0x2, 31 | EVENT_AND_ALL_ASSOCIATED_SELECTED: 0x1 | 0x4 32 | }; 33 | 34 | return { 35 | CompoundEventSelectionState: CompoundEventSelectionState 36 | }; 37 | }); 38 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/chrome/chrome_gpu_helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./chrome_process_helper.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Utilities for accessing the Chrome GPU Process. 13 | */ 14 | global.tr.exportTo('tr.e.audits', function() { 15 | function ChromeGpuHelper(modelHelper, process) { 16 | tr.e.audits.ChromeProcessHelper.call(this, modelHelper, process); 17 | this.mainThread_ = process.findAtMostOneThreadNamed('CrGpuMain'); 18 | }; 19 | 20 | ChromeGpuHelper.isGpuProcess = function(process) { 21 | // In some android builds the GPU thread is not in a separate process. 22 | if (process.findAtMostOneThreadNamed('CrBrowserMain') || 23 | process.findAtMostOneThreadNamed('CrRendererMain')) 24 | return false; 25 | return process.findAtMostOneThreadNamed('CrGpuMain'); 26 | }; 27 | 28 | ChromeGpuHelper.prototype = { 29 | __proto__: tr.e.audits.ChromeProcessHelper.prototype, 30 | 31 | get mainThread() { 32 | return this.mainThread_; 33 | } 34 | }; 35 | 36 | return { 37 | ChromeGpuHelper: ChromeGpuHelper 38 | }; 39 | }); 40 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/x_marker_annotation.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./annotation.js"); 8 | require("../ui/annotations/x_marker_annotation_view.js"); 9 | 10 | 'use strict'; 11 | 12 | global.tr.exportTo('tr.model', function() { 13 | 14 | function XMarkerAnnotation(timestamp) { 15 | tr.model.Annotation.apply(this, arguments); 16 | 17 | this.timestamp = timestamp; 18 | this.strokeStyle = 'rgba(0, 0, 255, 0.5)'; 19 | } 20 | 21 | XMarkerAnnotation.fromDict = function(dict) { 22 | return new XMarkerAnnotation(dict.args.timestamp); 23 | } 24 | 25 | XMarkerAnnotation.prototype = { 26 | __proto__: tr.model.Annotation.prototype, 27 | 28 | toDict: function() { 29 | return { 30 | typeName: 'xmarker', 31 | args: { 32 | timestamp: this.timestamp 33 | } 34 | }; 35 | }, 36 | 37 | createView_: function(viewport) { 38 | return new tr.ui.annotations.XMarkerAnnotationView(viewport, this); 39 | } 40 | }; 41 | 42 | tr.model.Annotation.register( 43 | XMarkerAnnotation, {typeName: 'xmarker'}); 44 | 45 | return { 46 | XMarkerAnnotation: XMarkerAnnotation 47 | }; 48 | }); 49 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/source_info/source_info.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../base/base.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.model.source_info', function() { 12 | function SourceInfo(file, opt_line, opt_column) { 13 | this.file_ = file; 14 | this.line_ = opt_line || -1; 15 | this.column_ = opt_column || -1; 16 | } 17 | 18 | SourceInfo.prototype = { 19 | get file() { 20 | return this.file_; 21 | }, 22 | 23 | get line() { 24 | return this.line_; 25 | }, 26 | 27 | get column() { 28 | return this.column_; 29 | }, 30 | 31 | get domain() { 32 | if (!this.file_) 33 | return undefined; 34 | var domain = this.file_.match(/(.*:\/\/[^:\/]*)/i); 35 | return domain ? domain[1] : undefined; 36 | }, 37 | 38 | toString: function() { 39 | var str = ''; 40 | 41 | if (this.file_) 42 | str += this.file_; 43 | if (this.line_ > 0) 44 | str += ':' + this.line_; 45 | if (this.column_ > 0) 46 | str += ':' + this.column_; 47 | return str; 48 | } 49 | }; 50 | 51 | return { 52 | SourceInfo: SourceInfo 53 | }; 54 | }); 55 | -------------------------------------------------------------------------------- /lib/third_party/tracing/importer/simple_line_reader.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/base.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.importer', function() { 12 | /** 13 | * @constructor 14 | */ 15 | function SimpleLineReader(text) { 16 | this.lines_ = text.split('\n'); 17 | this.curLine_ = 0; 18 | 19 | this.savedLines_ = undefined; 20 | } 21 | 22 | SimpleLineReader.prototype = { 23 | advanceToLineMatching: function(regex) { 24 | for (; this.curLine_ < this.lines_.length; this.curLine_++) { 25 | var line = this.lines_[this.curLine_]; 26 | if (this.savedLines_ !== undefined) 27 | this.savedLines_.push(line); 28 | if (regex.test(line)) 29 | return true; 30 | } 31 | return false; 32 | }, 33 | 34 | get curLineNumber() { 35 | return this.curLine_; 36 | }, 37 | 38 | beginSavingLines: function() { 39 | this.savedLines_ = []; 40 | }, 41 | 42 | endSavingLinesAndGetResult: function() { 43 | var tmp = this.savedLines_; 44 | this.savedLines_ = undefined; 45 | return tmp; 46 | } 47 | }; 48 | 49 | return { 50 | SimpleLineReader: SimpleLineReader 51 | }; 52 | }); 53 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/source_info/js_source_info.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./source_info.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.model.source_info', function() { 12 | function JSSourceInfo(file, line, column, isNative, scriptId, state) { 13 | tr.model.source_info.SourceInfo.call(this, file, line, column); 14 | 15 | this.isNative_ = isNative; 16 | this.scriptId_ = scriptId; 17 | this.state_ = state; 18 | } 19 | 20 | JSSourceInfo.prototype = { 21 | __proto__: tr.model.source_info.SourceInfo.prototype, 22 | 23 | get state() { 24 | return this.state_; 25 | }, 26 | 27 | get isNative() { 28 | return this.isNative_; 29 | }, 30 | 31 | get scriptId() { 32 | return this.scriptId_; 33 | }, 34 | 35 | toString: function() { 36 | var str = this.isNative_ ? '[native v8] ' : ''; 37 | return str + 38 | tr.model.source_info.SourceInfo.prototype.toString.call(this); 39 | } 40 | }; 41 | 42 | return { 43 | JSSourceInfo: JSSourceInfo, 44 | JSSourceState: { 45 | COMPILED: 'compiled', 46 | OPTIMIZABLE: 'optimizable', 47 | OPTIMIZED: 'optimized', 48 | UNKNOWN: 'unknown' 49 | } 50 | }; 51 | }); 52 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to become a contributor and submit your own code 2 | 3 | ## Contributor License Agreements 4 | 5 | We'd love to accept your sample apps and patches! Before we can take them, we have to jump a couple of legal hurdles. 6 | 7 | Please fill out either the individual or corporate Contributor License Agreement (CLA). 8 | * If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA](https://developers.google.com/open-source/cla/individual). 9 | * If you work for a company that wants to allow you to contribute your work, then you'll need to sign a [corporate CLA](https://developers.google.com/open-source/cla/corporate). 10 | 11 | Follow either of the two links above to access the appropriate CLA and instructions for how to sign and return it. Once we receive it, we'll be able to 12 | accept your pull requests. 13 | 14 | ## Contributing A Patch 15 | 16 | 1. Submit an issue describing your proposed change to the repo in question. 17 | 1. The repo owner will respond to your issue promptly. 18 | 1. If your proposed change is accepted, and you haven't already done so, sign a Contributor License Agreement (see details above). 19 | 1. Fork the repo, develop and test your code changes. 20 | 1. Ensure that your code adheres to the existing style in the sample to which you are contributing. 21 | 1. Submit a pull request. 22 | -------------------------------------------------------------------------------- /lib/third_party/tracing/core/auditor.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/base.js"); 8 | require("../base/extension_registry.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview Base class for auditors. 14 | */ 15 | global.tr.exportTo('tr.c', function() { 16 | function Auditor(model) { 17 | this.model_ = model; 18 | } 19 | 20 | Auditor.prototype = { 21 | __proto__: Object.prototype, 22 | 23 | get model() { 24 | return this.model_; 25 | }, 26 | 27 | /** 28 | * Called by the Model after baking slices. May modify model. 29 | */ 30 | runAnnotate: function() { 31 | }, 32 | 33 | /** 34 | * Called by import to install userFriendlyCategoryDriver. 35 | */ 36 | installUserFriendlyCategoryDriverIfNeeded: function() { 37 | }, 38 | 39 | /** 40 | * Called by the Model after importing. Should not modify model, except 41 | * for adding interaction ranges and audits. 42 | */ 43 | runAudit: function() { 44 | } 45 | }; 46 | 47 | var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE); 48 | options.defaultMetadata = {}; 49 | options.mandatoryBaseClass = Auditor; 50 | tr.b.decorateExtensionRegistry(Auditor, options); 51 | 52 | return { 53 | Auditor: Auditor 54 | }; 55 | }); 56 | -------------------------------------------------------------------------------- /lib/third_party/tracing/base/units/time_display_mode.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base.js"); 8 | require("../event_target.js"); 9 | require("../../ui/base/deep_utils.js"); 10 | 11 | 'use strict'; 12 | 13 | /** 14 | * @fileoverview Time currentDisplayUnit 15 | */ 16 | global.tr.exportTo('tr.b.u', function() { 17 | var msDisplayMode = { 18 | scale: 1e-3, 19 | suffix: 'ms', 20 | // Compares a < b with adjustments to precision errors. 21 | roundedLess: function(a, b) { 22 | return Math.round(a * 1000) < Math.round(b * 1000); 23 | }, 24 | format: function(ts) { 25 | return new Number(ts) 26 | .toLocaleString(undefined, { minimumFractionDigits: 3 }) + ' ms'; 27 | } 28 | }; 29 | 30 | var nsDisplayMode = { 31 | scale: 1e-9, 32 | suffix: 'ns', 33 | // Compares a < b with adjustments to precision errors. 34 | roundedLess: function(a, b) { 35 | return Math.round(a * 1000000) < Math.round(b * 1000000); 36 | }, 37 | format: function(ts) { 38 | return new Number(ts * 1000000) 39 | .toLocaleString(undefined, { maximumFractionDigits: 0 }) + ' ns'; 40 | } 41 | }; 42 | 43 | var TimeDisplayModes = { 44 | ns: nsDisplayMode, 45 | ms: msDisplayMode 46 | }; 47 | 48 | return { 49 | TimeDisplayModes: TimeDisplayModes 50 | }; 51 | }); 52 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/model_indices.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/base.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Provides the Event Index class. 13 | */ 14 | global.tr.exportTo('tr.model', function() { 15 | /** 16 | * A Event Index maps an id to all the events that have that particular id 17 | * 18 | * @constructor 19 | */ 20 | function ModelIndices(model) { 21 | // For now the only indices we construct are for flowEvents 22 | this.flowEventsById_ = {}; 23 | model.flowEvents.forEach(function(fe) { 24 | if (fe.id !== undefined) { 25 | if (!this.flowEventsById_.hasOwnProperty(fe.id)) { 26 | this.flowEventsById_[fe.id] = new Array(); 27 | } 28 | this.flowEventsById_[fe.id].push(fe); 29 | } 30 | }, this); 31 | } 32 | 33 | ModelIndices.prototype = { 34 | addEventWithId: function(id, event) { 35 | if (!this.flowEventsById_.hasOwnProperty(id)) { 36 | this.flowEventsById_[id] = new Array(); 37 | } 38 | this.flowEventsById_[id].push(event); 39 | }, 40 | 41 | getFlowEventsWithId: function(id) { 42 | if (!this.flowEventsById_.hasOwnProperty(id)) 43 | return []; 44 | return this.flowEventsById_[id]; 45 | } 46 | }; 47 | 48 | return { 49 | ModelIndices: ModelIndices 50 | }; 51 | }); 52 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/alert.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/units/time_stamp.js"); 8 | require("./event_info.js"); 9 | require("./event_set.js"); 10 | require("./timed_event.js"); 11 | 12 | 'use strict'; 13 | 14 | global.tr.exportTo('tr.model', function() { 15 | 16 | function Alert(info, start, opt_associatedEvents, opt_args) { 17 | tr.model.TimedEvent.call(this, start); 18 | this.info = info; 19 | this.args = opt_args || {}; 20 | this.associatedEvents = new tr.model.EventSet(opt_associatedEvents); 21 | this.associatedEvents.forEach(function(event) { 22 | event.associatedAlerts.push(this); 23 | }, this); 24 | } 25 | 26 | Alert.prototype = { 27 | __proto__: tr.model.TimedEvent.prototype, 28 | 29 | get title() { 30 | return this.info.title; 31 | }, 32 | 33 | get colorId() { 34 | return this.info.colorId; 35 | }, 36 | 37 | get userFriendlyName() { 38 | return 'Alert ' + this.title + ' at ' + 39 | tr.b.u.TimeStamp.format(this.start); 40 | } 41 | }; 42 | 43 | tr.model.EventRegistry.register( 44 | Alert, 45 | { 46 | name: 'alert', 47 | pluralName: 'alerts', 48 | singleViewElementName: 'tr-ui-a-alert-sub-view', 49 | multiViewElementName: 'tr-ui-a-alert-sub-view' 50 | }); 51 | 52 | return { 53 | Alert: Alert 54 | }; 55 | }); 56 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/event.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/guid.js"); 8 | require("./event_set.js"); 9 | require("./selectable_item.js"); 10 | require("./selection_state.js"); 11 | 12 | 'use strict'; 13 | 14 | /** 15 | * @fileoverview Provides the Event class. 16 | */ 17 | global.tr.exportTo('tr.model', function() { 18 | var SelectableItem = tr.model.SelectableItem; 19 | var SelectionState = tr.model.SelectionState; 20 | 21 | /** 22 | * An Event is the base type for any non-container, selectable piece 23 | * of data in the trace model. 24 | * 25 | * @constructor 26 | * @extends {SelectableItem} 27 | */ 28 | function Event() { 29 | SelectableItem.call(this, this /* modelItem */); 30 | this.guid_ = tr.b.GUID.allocate(); 31 | this.selectionState = SelectionState.NONE; 32 | this.associatedAlerts = new tr.model.EventSet(); 33 | this.info = undefined; 34 | } 35 | 36 | Event.prototype = { 37 | __proto__: SelectableItem.prototype, 38 | 39 | get guid() { 40 | return this.guid_; 41 | }, 42 | 43 | get stableId() { 44 | return undefined; 45 | }, 46 | 47 | /** Adds the range of timestamps for this event to the specified range. */ 48 | addBoundsToRange: function(range) { 49 | throw new Error('Not implemented'); 50 | } 51 | }; 52 | 53 | return { 54 | Event: Event 55 | }; 56 | }); 57 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/selectable_item.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./selection_state.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Provides the SelectableItem class. 13 | */ 14 | global.tr.exportTo('tr.model', function() { 15 | var SelectionState = tr.model.SelectionState; 16 | 17 | /** 18 | * A SelectableItem is the abstract base class for any non-container data that 19 | * has an associated model item in the trace model (possibly itself). 20 | * 21 | * Subclasses must provide a selectionState property (or getter). 22 | * 23 | * @constructor 24 | */ 25 | function SelectableItem(modelItem) { 26 | this.modelItem_ = modelItem; 27 | } 28 | 29 | SelectableItem.prototype = { 30 | get modelItem() { 31 | return this.modelItem_; 32 | }, 33 | 34 | get selected() { 35 | return this.selectionState === SelectionState.SELECTED; 36 | }, 37 | 38 | addToSelection: function(selection) { 39 | var modelItem = this.modelItem_; 40 | if (!modelItem) 41 | return; 42 | selection.push(modelItem); 43 | }, 44 | 45 | addToTrackMap: function(eventToTrackMap, track) { 46 | var modelItem = this.modelItem_; 47 | if (!modelItem) 48 | return; 49 | eventToTrackMap.addEvent(modelItem, track); 50 | } 51 | }; 52 | 53 | return { 54 | SelectableItem: SelectableItem 55 | }; 56 | }); 57 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/comment_box_annotation.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./location.js"); 8 | require("./annotation.js"); 9 | require("./rect_annotation.js"); 10 | require("../ui/annotations/comment_box_annotation_view.js"); 11 | 12 | 'use strict'; 13 | 14 | global.tr.exportTo('tr.model', function() { 15 | 16 | function CommentBoxAnnotation(location, text) { 17 | tr.model.Annotation.apply(this, arguments); 18 | 19 | this.location = location; 20 | this.text = text; 21 | } 22 | 23 | CommentBoxAnnotation.fromDict = function(dict) { 24 | var args = dict.args; 25 | var location = 26 | new tr.model.Location(args.location.xWorld, args.location.yComponents); 27 | return new tr.model.CommentBoxAnnotation(location, args.text); 28 | }; 29 | 30 | CommentBoxAnnotation.prototype = { 31 | __proto__: tr.model.Annotation.prototype, 32 | 33 | onRemove: function() { 34 | this.view_.removeTextArea(); 35 | }, 36 | 37 | toDict: function() { 38 | return { 39 | typeName: 'comment_box', 40 | args: { 41 | text: this.text, 42 | location: this.location.toDict() 43 | } 44 | }; 45 | }, 46 | 47 | createView_: function(viewport) { 48 | return new tr.ui.annotations.CommentBoxAnnotationView(viewport, this); 49 | } 50 | }; 51 | 52 | tr.model.Annotation.register( 53 | CommentBoxAnnotation, {typeName: 'comment_box'}); 54 | 55 | return { 56 | CommentBoxAnnotation: CommentBoxAnnotation 57 | }; 58 | }); 59 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/timed_event.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/units/time_display_mode.js"); 8 | require("./event.js"); 9 | require("../base/guid.js"); 10 | 11 | 'use strict'; 12 | 13 | /** 14 | * @fileoverview Provides the TimedEvent class. 15 | */ 16 | global.tr.exportTo('tr.model', function() { 17 | /** 18 | * A TimedEvent is the base type for any piece of data in the trace model with 19 | * a specific start and duration. 20 | * 21 | * @constructor 22 | */ 23 | function TimedEvent(start) { 24 | tr.model.Event.call(this); 25 | this.start = start; 26 | this.duration = 0; 27 | this.cpuStart = undefined; 28 | this.cpuDuration = undefined; 29 | } 30 | 31 | TimedEvent.prototype = { 32 | __proto__: tr.model.Event.prototype, 33 | 34 | get end() { 35 | return this.start + this.duration; 36 | }, 37 | 38 | addBoundsToRange: function(range) { 39 | range.addValue(this.start); 40 | range.addValue(this.end); 41 | }, 42 | 43 | // bounds returns whether that TimedEvent happens within this timed event 44 | bounds: function(that, precisionUnit) { 45 | if (precisionUnit === undefined) { 46 | precisionUnit = tr.b.u.TimeDisplayModes.ms; 47 | } 48 | var startsBefore = precisionUnit.roundedLess(that.start, this.start); 49 | var endsAfter = precisionUnit.roundedLess(this.end, that.end); 50 | return !startsBefore && !endsAfter; 51 | } 52 | }; 53 | 54 | return { 55 | TimedEvent: TimedEvent 56 | }; 57 | }); 58 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/power_sample.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./event.js"); 8 | require("./event_registry.js"); 9 | 10 | 'use strict'; 11 | 12 | global.tr.exportTo('tr.model', function() { 13 | 14 | var Event = tr.model.Event; 15 | var EventRegistry = tr.model.EventRegistry; 16 | 17 | /** 18 | * A sample that contains a power measurement (in mW). 19 | * 20 | * @constructor 21 | * @extends {Event} 22 | */ 23 | function PowerSample(series, start, power) { 24 | Event.call(this); 25 | 26 | this.series_ = series; 27 | this.start_ = start; 28 | this.power_ = power; 29 | } 30 | 31 | PowerSample.prototype = { 32 | __proto__: Event.prototype, 33 | 34 | get series() { 35 | return this.series_; 36 | }, 37 | 38 | get start() { 39 | return this.start_; 40 | }, 41 | 42 | set start(value) { 43 | this.start_ = value; 44 | }, 45 | 46 | get power() { 47 | return this.power_; 48 | }, 49 | 50 | set power(value) { 51 | this.power_ = value; 52 | }, 53 | 54 | addBoundsToRange: function(range) { 55 | range.addValue(this.start); 56 | } 57 | }; 58 | 59 | EventRegistry.register( 60 | PowerSample, 61 | { 62 | name: 'powerSample', 63 | pluralName: 'powerSamples', 64 | singleViewElementName: 'tr-ui-a-single-power-sample-sub-view', 65 | multiViewElementName: 'tr-ui-a-multi-power-sample-sub-view' 66 | }); 67 | 68 | return { 69 | PowerSample: PowerSample 70 | }; 71 | }); 72 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/flow_event.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/units/time_stamp.js"); 8 | require("./timed_event.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview Provides the Flow class. 14 | */ 15 | global.tr.exportTo('tr.model', function() { 16 | /** 17 | * A Flow represents an interval of time plus parameters associated 18 | * with that interval. 19 | * 20 | * @constructor 21 | */ 22 | function FlowEvent(category, id, title, colorId, start, args, opt_duration) { 23 | tr.model.TimedEvent.call(this, start); 24 | 25 | this.category = category || ''; 26 | this.title = title; 27 | this.colorId = colorId; 28 | this.start = start; 29 | this.args = args; 30 | 31 | this.id = id; 32 | 33 | this.startSlice = undefined; 34 | this.endSlice = undefined; 35 | 36 | this.startStackFrame = undefined; 37 | this.endStackFrame = undefined; 38 | 39 | if (opt_duration !== undefined) 40 | this.duration = opt_duration; 41 | } 42 | 43 | FlowEvent.prototype = { 44 | __proto__: tr.model.TimedEvent.prototype, 45 | 46 | get userFriendlyName() { 47 | return 'Flow event named ' + this.title + ' at ' + 48 | tr.b.u.TimeStamp.format(this.timestamp); 49 | } 50 | }; 51 | 52 | tr.model.EventRegistry.register( 53 | FlowEvent, 54 | { 55 | name: 'flowEvent', 56 | pluralName: 'flowEvents', 57 | singleViewElementName: 'tr-ui-a-single-flow-event-sub-view', 58 | multiViewElementName: 'tr-ui-a-multi-flow-event-sub-view' 59 | }); 60 | 61 | return { 62 | FlowEvent: FlowEvent 63 | }; 64 | }); 65 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { "modules": true }, 3 | "rules": { 4 | "array-bracket-spacing": 2, 5 | "block-spacing": [2, "never"], 6 | "brace-style": [2, "1tbs", { "allowSingleLine": false }], 7 | "camelcase": [2, {"properties": "always"}], 8 | "curly": 2, 9 | "default-case": 2, 10 | "dot-notation": 2, 11 | "eqeqeq": 2, 12 | "key-spacing": [2, {"beforeColon": false, "afterColon": true}], 13 | "max-len": [2, 80, 2], 14 | "new-cap": 2, 15 | "no-console": 0, 16 | "no-else-return": 2, 17 | "no-eval": 2, 18 | "no-multi-spaces": 2, 19 | "no-multiple-empty-lines": [2, {"max": 2}], 20 | "no-shadow": 2, 21 | "no-trailing-spaces": 2, 22 | "no-unused-expressions": 2, 23 | "object-curly-spacing": [2, "never"], 24 | "quotes": [ 25 | 2, 26 | "single" 27 | ], 28 | "semi": [ 29 | 2, 30 | "always" 31 | ], 32 | "space-after-keywords": 2, 33 | "space-before-blocks": 2, 34 | "space-before-function-paren": [2, {"named": "always", "anonymous": "always"}], 35 | "spaced-comment": 2, 36 | "valid-typeof": 2, 37 | "no-unused-vars": [2, {"args": "none"}], 38 | "no-empty-class": 0, 39 | "no-extra-strict": 0, 40 | "no-reserved-keys": 0, 41 | "no-space-before-semi": 0, 42 | "no-wrap-func": 0 43 | }, 44 | "env": { 45 | "es6": true, 46 | "browser": true, 47 | "node": true 48 | }, 49 | "extends": "eslint:recommended", 50 | "globals": { 51 | "importScripts": true, 52 | "describe": true, 53 | "it": true, 54 | "before": true, 55 | "after": true, 56 | "beforeEach": true, 57 | "afterEach": true 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/cpu_slice.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/range.js"); 8 | require("./thread_time_slice.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview Provides the CpuSlice class. 14 | */ 15 | global.tr.exportTo('tr.model', function() { 16 | 17 | var Slice = tr.model.Slice; 18 | 19 | /** 20 | * A CpuSlice represents a slice of time on a CPU. 21 | * 22 | * @constructor 23 | */ 24 | function CpuSlice(cat, title, colorId, start, args, opt_duration) { 25 | Slice.apply(this, arguments); 26 | this.threadThatWasRunning = undefined; 27 | this.cpu = undefined; 28 | } 29 | 30 | CpuSlice.prototype = { 31 | __proto__: Slice.prototype, 32 | 33 | get analysisTypeName() { 34 | return 'tr.ui.analysis.CpuSlice'; 35 | }, 36 | 37 | getAssociatedTimeslice: function() { 38 | if (!this.threadThatWasRunning) 39 | return undefined; 40 | var timeSlices = this.threadThatWasRunning.timeSlices; 41 | for (var i = 0; i < timeSlices.length; i++) { 42 | var timeSlice = timeSlices[i]; 43 | if (timeSlice.start !== this.start) 44 | continue; 45 | if (timeSlice.duration !== this.duration) 46 | continue; 47 | return timeSlice; 48 | } 49 | return undefined; 50 | } 51 | }; 52 | 53 | tr.model.EventRegistry.register( 54 | CpuSlice, 55 | { 56 | name: 'cpuSlice', 57 | pluralName: 'cpuSlices', 58 | singleViewElementName: 'tr-ui-a-single-cpu-slice-sub-view', 59 | multiViewElementName: 'tr-ui-a-multi-cpu-slice-sub-view' 60 | }); 61 | 62 | return { 63 | CpuSlice: CpuSlice 64 | }; 65 | }); 66 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/chrome/chrome_renderer_helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./chrome_process_helper.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Utilities for accessing trace data about the Chrome browser. 13 | */ 14 | global.tr.exportTo('tr.e.audits', function() { 15 | function ChromeRendererHelper(modelHelper, process) { 16 | tr.e.audits.ChromeProcessHelper.call(this, modelHelper, process); 17 | this.mainThread_ = process.findAtMostOneThreadNamed('CrRendererMain'); 18 | this.compositorThread_ = process.findAtMostOneThreadNamed('Compositor'); 19 | this.rasterWorkerThreads_ = process.findAllThreadsMatching(function(t) { 20 | if (t.name === undefined) 21 | return false; 22 | if (t.name.indexOf('CompositorTileWorker') === 0) 23 | return true; 24 | if (t.name.indexOf('CompositorRasterWorker') === 0) 25 | return true; 26 | return false; 27 | }); 28 | }; 29 | 30 | ChromeRendererHelper.isRenderProcess = function(process) { 31 | if (!process.findAtMostOneThreadNamed('CrRendererMain')) 32 | return false; 33 | if (!process.findAtMostOneThreadNamed('Compositor')) 34 | return false; 35 | return true; 36 | }; 37 | 38 | ChromeRendererHelper.prototype = { 39 | __proto__: tr.e.audits.ChromeProcessHelper.prototype, 40 | 41 | get mainThread() { 42 | return this.mainThread_; 43 | }, 44 | 45 | get compositorThread() { 46 | return this.compositorThread_; 47 | }, 48 | 49 | get rasterWorkerThreads() { 50 | return this.rasterWorkerThreads_; 51 | } 52 | }; 53 | 54 | return { 55 | ChromeRendererHelper: ChromeRendererHelper 56 | }; 57 | }); 58 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/rect_annotation.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./location.js"); 8 | require("./annotation.js"); 9 | require("../ui/annotations/rect_annotation_view.js"); 10 | 11 | 'use strict'; 12 | 13 | global.tr.exportTo('tr.model', function() { 14 | 15 | function RectAnnotation(start, end) { 16 | tr.model.Annotation.apply(this, arguments); 17 | 18 | this.startLocation_ = start; // Location of top-left corner. 19 | this.endLocation_ = end; // Location of bottom-right corner. 20 | this.fillStyle = 'rgba(255, 180, 0, 0.3)'; 21 | } 22 | 23 | RectAnnotation.fromDict = function(dict) { 24 | var args = dict.args; 25 | var startLoc = 26 | new tr.model.Location(args.start.xWorld, args.start.yComponents); 27 | var endLoc = 28 | new tr.model.Location(args.end.xWorld, args.end.yComponents); 29 | return new tr.model.RectAnnotation(startLoc, endLoc); 30 | } 31 | 32 | RectAnnotation.prototype = { 33 | __proto__: tr.model.Annotation.prototype, 34 | 35 | get startLocation() { 36 | return this.startLocation_; 37 | }, 38 | 39 | get endLocation() { 40 | return this.endLocation_; 41 | }, 42 | 43 | toDict: function() { 44 | return { 45 | typeName: 'rect', 46 | args: { 47 | start: this.startLocation.toDict(), 48 | end: this.endLocation.toDict() 49 | } 50 | }; 51 | }, 52 | 53 | createView_: function(viewport) { 54 | return new tr.ui.annotations.RectAnnotationView(viewport, this); 55 | } 56 | }; 57 | 58 | tr.model.Annotation.register(RectAnnotation, {typeName: 'rect'}); 59 | 60 | return { 61 | RectAnnotation: RectAnnotation 62 | }; 63 | }); 64 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/sample.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/units/time_stamp.js"); 8 | require("./timed_event.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview Provides the Sample class. 14 | */ 15 | global.tr.exportTo('tr.model', function() { 16 | /** 17 | * A Sample represents a sample taken at an instant in time, plus its stack 18 | * frame and parameters associated with that sample. 19 | * 20 | * @constructor 21 | */ 22 | function Sample(cpu, thread, title, start, leafStackFrame, 23 | opt_weight, opt_args) { 24 | tr.model.TimedEvent.call(this, start); 25 | 26 | this.title = title; 27 | this.cpu = cpu; 28 | this.thread = thread; 29 | this.leafStackFrame = leafStackFrame; 30 | this.weight = opt_weight; 31 | this.args = opt_args || {}; 32 | } 33 | 34 | Sample.prototype = { 35 | __proto__: tr.model.TimedEvent.prototype, 36 | 37 | get colorId() { 38 | return this.leafStackFrame.colorId; 39 | }, 40 | 41 | get stackTrace() { 42 | return this.leafStackFrame.stackTrace; 43 | }, 44 | 45 | getUserFriendlyStackTrace: function() { 46 | return this.leafStackFrame.getUserFriendlyStackTrace(); 47 | }, 48 | 49 | get userFriendlyName() { 50 | return 'Sample at ' + tr.b.u.TimeStamp.format(this.start); 51 | } 52 | }; 53 | 54 | tr.model.EventRegistry.register( 55 | Sample, 56 | { 57 | name: 'sample', 58 | pluralName: 'samples', 59 | singleViewElementName: 'tr-ui-a-single-sample-sub-view', 60 | multiViewElementName: 'tr-ui-a-multi-sample-sub-view' 61 | }); 62 | 63 | return { 64 | Sample: Sample 65 | }; 66 | }); 67 | -------------------------------------------------------------------------------- /lib/third_party/tracing/ui/annotations/rect_annotation_view.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./annotation_view.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.ui.annotations', function() { 12 | /** 13 | * A view responsible for drawing a single highlight rectangle box on 14 | * the timeline. 15 | * @extends {AnnotationView} 16 | * @constructor 17 | */ 18 | function RectAnnotationView(viewport, annotation) { 19 | this.viewport_ = viewport; 20 | this.annotation_ = annotation; 21 | } 22 | 23 | RectAnnotationView.prototype = { 24 | __proto__: tr.ui.annotations.AnnotationView.prototype, 25 | 26 | draw: function(ctx) { 27 | var dt = this.viewport_.currentDisplayTransform; 28 | var startCoords = 29 | this.annotation_.startLocation.toViewCoordinates(this.viewport_); 30 | var endCoords = 31 | this.annotation_.endLocation.toViewCoordinates(this.viewport_); 32 | 33 | // Prevent drawing into the ruler track by clamping the initial Y 34 | // point and the rect's Y size. 35 | var startY = startCoords.viewY - ctx.canvas.getBoundingClientRect().top; 36 | var sizeY = endCoords.viewY - startCoords.viewY; 37 | if (startY + sizeY < 0) { 38 | // In this case sizeY is negative. If final Y is negative, 39 | // overwrite startY so that the rectangle ends at y=0. 40 | startY = sizeY; 41 | } else if (startY < 0) { 42 | startY = 0; 43 | } 44 | 45 | ctx.fillStyle = this.annotation_.fillStyle; 46 | ctx.fillRect(startCoords.viewX, startY, 47 | endCoords.viewX - startCoords.viewX, sizeY); 48 | } 49 | }; 50 | 51 | return { 52 | RectAnnotationView: RectAnnotationView 53 | }; 54 | }); 55 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/thread_slice.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./slice.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Provides the Thread class. 13 | */ 14 | global.tr.exportTo('tr.model', function() { 15 | var Slice = tr.model.Slice; 16 | 17 | /** 18 | * A ThreadSlice represents an interval of time on a thread resource 19 | * with associated nesting slice information. 20 | * 21 | * ThreadSlices are typically associated with a specific trace event pair on a 22 | * specific thread. 23 | * For example, 24 | * TRACE_EVENT_BEGIN1("x","myArg", 7) at time=0.1ms 25 | * TRACE_EVENT_END0() at time=0.3ms 26 | * This results in a single slice from 0.1 with duration 0.2 on a 27 | * specific thread. 28 | * 29 | * @constructor 30 | */ 31 | function ThreadSlice(cat, title, colorId, start, args, opt_duration, 32 | opt_cpuStart, opt_cpuDuration, opt_argsStripped, 33 | opt_bind_id) { 34 | Slice.call(this, cat, title, colorId, start, args, opt_duration, 35 | opt_cpuStart, opt_cpuDuration, opt_argsStripped, opt_bind_id); 36 | // Do not modify this directly. 37 | // subSlices is configured by SliceGroup.rebuildSubRows_. 38 | this.subSlices = []; 39 | } 40 | 41 | ThreadSlice.prototype = { 42 | __proto__: Slice.prototype 43 | }; 44 | 45 | tr.model.EventRegistry.register( 46 | ThreadSlice, 47 | { 48 | name: 'slice', 49 | pluralName: 'slices', 50 | singleViewElementName: 'tr-ui-a-single-thread-slice-sub-view', 51 | multiViewElementName: 'tr-ui-a-multi-thread-slice-sub-view' 52 | }); 53 | 54 | return { 55 | ThreadSlice: ThreadSlice 56 | }; 57 | }); 58 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/heap_dump.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/base.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.model', function() { 12 | 13 | /** 14 | * HeapEntry represents a single value describing the state of the heap of an 15 | * allocator in a single process. 16 | * 17 | * An entry specifies how much space (e.g. 19 MiB) was allocated in a 18 | * particular context, which consists of a codepath (e.g. drawQuad <- draw <- 19 | * MessageLoop::RunTask). 20 | * 21 | * @{constructor} 22 | */ 23 | function HeapEntry(heapDump, leafStackFrame, size) { 24 | this.heapDump = heapDump; 25 | 26 | // The leaf stack frame of the associated backtrace (e.g. drawQuad for the 27 | // drawQuad <- draw <- MessageLoop::RunTask backtrace). If undefined, the 28 | // heap entry is a sum over all backtraces. On the other hand, an empty 29 | // backtrace is represented by the root stack frame, which has an undefined 30 | // name. 31 | this.leafStackFrame = leafStackFrame; 32 | 33 | this.size = size; 34 | } 35 | 36 | /** 37 | * HeapDump represents a dump of the heap of an allocator in a single process 38 | * at a particular timestamp. 39 | * 40 | * @{constructor} 41 | */ 42 | function HeapDump(processMemoryDump, allocatorName) { 43 | this.processMemoryDump = processMemoryDump; 44 | this.allocatorName = allocatorName; 45 | this.entries = []; 46 | } 47 | 48 | HeapDump.prototype = { 49 | addEntry: function(leafStackFrame, size) { 50 | var entry = new HeapEntry(this, leafStackFrame, size); 51 | this.entries.push(entry); 52 | return entry; 53 | } 54 | }; 55 | 56 | return { 57 | HeapEntry: HeapEntry, 58 | HeapDump: HeapDump 59 | }; 60 | }); 61 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/zip_importer.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./jszip.js"); 8 | require("./gzip_importer.js"); 9 | require("../../importer/importer.js"); 10 | require("../../model/model.js"); 11 | 12 | 'use strict'; 13 | 14 | /** 15 | * @fileoverview ZipImporter inflates zip compressed data and passes it along 16 | * to an actual importer. 17 | */ 18 | global.tr.exportTo('tr.e.importer', function() { 19 | function ZipImporter(model, eventData) { 20 | if (eventData instanceof ArrayBuffer) 21 | eventData = new Uint8Array(eventData); 22 | this.model_ = model; 23 | this.eventData_ = eventData; 24 | } 25 | 26 | /** 27 | * @param {eventData} string Possibly zip compressed data. 28 | * @return {boolean} Whether eventData looks like zip compressed data. 29 | */ 30 | ZipImporter.canImport = function(eventData) { 31 | var header; 32 | if (eventData instanceof ArrayBuffer) 33 | header = new Uint8Array(eventData.slice(0, 2)); 34 | else if (typeof(eventData) === 'string' || eventData instanceof String) 35 | header = [eventData.charCodeAt(0), eventData.charCodeAt(1)]; 36 | else 37 | return false; 38 | return header[0] === 'P'.charCodeAt(0) && header[1] === 'K'.charCodeAt(0); 39 | }; 40 | 41 | ZipImporter.prototype = { 42 | __proto__: tr.importer.Importer.prototype, 43 | 44 | isTraceDataContainer: function() { 45 | return true; 46 | }, 47 | 48 | extractSubtraces: function() { 49 | var zip = new JSZip(this.eventData_); 50 | var subtraces = []; 51 | for (var idx in zip.files) 52 | subtraces.push(zip.files[idx].asBinary()); 53 | return subtraces; 54 | } 55 | }; 56 | 57 | tr.importer.Importer.register(ZipImporter); 58 | 59 | return { 60 | ZipImporter: ZipImporter 61 | }; 62 | }); 63 | -------------------------------------------------------------------------------- /lib/third_party/tracing/ui/base/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../base/rect.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.ui.b', function() { 12 | function instantiateTemplate(selector, doc) { 13 | doc = doc || document; 14 | var el = doc.querySelector(selector); 15 | if (!el) 16 | throw new Error('Element not found'); 17 | return el.createInstance(); 18 | } 19 | 20 | function windowRectForElement(element) { 21 | var position = [element.offsetLeft, element.offsetTop]; 22 | var size = [element.offsetWidth, element.offsetHeight]; 23 | var node = element.offsetParent; 24 | while (node) { 25 | position[0] += node.offsetLeft; 26 | position[1] += node.offsetTop; 27 | node = node.offsetParent; 28 | } 29 | return tr.b.Rect.fromXYWH(position[0], position[1], size[0], size[1]); 30 | } 31 | 32 | function scrollIntoViewIfNeeded(el) { 33 | var pr = el.parentElement.getBoundingClientRect(); 34 | var cr = el.getBoundingClientRect(); 35 | if (cr.top < pr.top) { 36 | el.scrollIntoView(true); 37 | } else if (cr.bottom > pr.bottom) { 38 | el.scrollIntoView(false); 39 | } 40 | } 41 | 42 | function extractUrlString(url) { 43 | var extracted = url.replace(/url\((.*)\)/, '$1'); 44 | 45 | // In newer versions of chrome, the contents of url() will be quoted. Remove 46 | // these quotes as well. If quotes are not present, match will fail and this 47 | // becomes a no-op. 48 | extracted = extracted.replace(/\"(.*)\"/, '$1'); 49 | 50 | return extracted; 51 | } 52 | 53 | return { 54 | instantiateTemplate: instantiateTemplate, 55 | windowRectForElement: windowRectForElement, 56 | scrollIntoViewIfNeeded: scrollIntoViewIfNeeded, 57 | extractUrlString: extractUrlString 58 | }; 59 | }); 60 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/linux_perf/drm_parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./parser.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Parses drm driver events in the Linux event trace format. 13 | */ 14 | global.tr.exportTo('tr.e.importer.linux_perf', function() { 15 | 16 | var ColorScheme = tr.b.ColorScheme; 17 | var Parser = tr.e.importer.linux_perf.Parser; 18 | 19 | /** 20 | * Parses linux drm trace events. 21 | * @constructor 22 | */ 23 | function DrmParser(importer) { 24 | Parser.call(this, importer); 25 | 26 | importer.registerEventHandler('drm_vblank_event', 27 | DrmParser.prototype.vblankEvent.bind(this)); 28 | } 29 | 30 | DrmParser.prototype = { 31 | __proto__: Parser.prototype, 32 | 33 | drmVblankSlice: function(ts, eventName, args) { 34 | var kthread = this.importer.getOrCreatePseudoThread('drm_vblank'); 35 | kthread.openSlice = eventName; 36 | var slice = new tr.model.Slice('', kthread.openSlice, 37 | ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice), 38 | ts, args, 0); 39 | 40 | kthread.thread.sliceGroup.pushSlice(slice); 41 | }, 42 | 43 | /** 44 | * Parses drm driver events and sets up state in the importer. 45 | */ 46 | vblankEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 47 | var event = /crtc=(\d+), seq=(\d+)/.exec(eventBase.details); 48 | if (!event) 49 | return false; 50 | 51 | var crtc = parseInt(event[1]); 52 | var seq = parseInt(event[2]); 53 | this.drmVblankSlice(ts, 'vblank:' + crtc, 54 | { 55 | crtc: crtc, 56 | seq: seq 57 | }); 58 | return true; 59 | } 60 | }; 61 | 62 | Parser.register(DrmParser); 63 | 64 | return { 65 | DrmParser: DrmParser 66 | }; 67 | }); 68 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/linux_perf/clock_parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./parser.js"); 8 | require("../../../model/counter_series.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview Parses trace_marker events that were inserted in the trace by 14 | * userland. 15 | */ 16 | global.tr.exportTo('tr.e.importer.linux_perf', function() { 17 | 18 | var ColorScheme = tr.b.ColorScheme; 19 | var Parser = tr.e.importer.linux_perf.Parser; 20 | 21 | /** 22 | * Parses linux trace mark events that were inserted in the trace by userland. 23 | * @constructor 24 | */ 25 | function ClockParser(importer) { 26 | Parser.call(this, importer); 27 | 28 | importer.registerEventHandler('clock_set_rate', 29 | ClockParser.prototype.traceMarkWriteClockEvent.bind(this)); 30 | 31 | this.model_ = importer.model_; 32 | this.ppids_ = {}; 33 | } 34 | 35 | ClockParser.prototype = { 36 | __proto__: Parser.prototype, 37 | 38 | traceMarkWriteClockEvent: function(eventName, cpuNumber, pid, ts, 39 | eventBase, threadName) { 40 | var event = /(\S+) state=(\d+) cpu_id=(\d+)/.exec(eventBase.details); 41 | 42 | 43 | var name = event[1]; 44 | var rate = parseInt(event[2]); 45 | 46 | var ctr = this.model_.kernel 47 | .getOrCreateCounter(null, name); 48 | // Initialize the counter's series fields if needed. 49 | if (ctr.numSeries === 0) { 50 | ctr.addSeries(new tr.model.CounterSeries('value', 51 | ColorScheme.getColorIdForGeneralPurposeString( 52 | ctr.name + '.' + 'value'))); 53 | } 54 | ctr.series.forEach(function(series) { 55 | series.addCounterSample(ts, rate); 56 | }); 57 | 58 | return true; 59 | } 60 | }; 61 | 62 | Parser.register(ClockParser); 63 | 64 | return { 65 | ClockParser: ClockParser 66 | }; 67 | }); 68 | -------------------------------------------------------------------------------- /lib/third_party/tracing/importer/importer.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/base.js"); 8 | require("../base/extension_registry.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview Base class for trace data importers. 14 | */ 15 | global.tr.exportTo('tr.importer', function() { 16 | function Importer() { } 17 | 18 | Importer.prototype = { 19 | __proto__: Object.prototype, 20 | 21 | /** 22 | * Called by the Model to check whether the importer type stores the actual 23 | * trace data or just holds it as container for further extraction. 24 | */ 25 | isTraceDataContainer: function() { 26 | return false; 27 | }, 28 | 29 | /** 30 | * Called by the Model to extract one or more subtraces from the event data. 31 | */ 32 | extractSubtraces: function() { 33 | return []; 34 | }, 35 | 36 | /** 37 | * Called to import events into the Model. 38 | */ 39 | importEvents: function() { 40 | }, 41 | 42 | /** 43 | * Called to import sample data into the Model. 44 | */ 45 | importSampleData: function() { 46 | }, 47 | 48 | /** 49 | * Called by the Model after all other importers have imported their 50 | * events. 51 | */ 52 | finalizeImport: function() { 53 | }, 54 | 55 | /** 56 | * Called by the Model to join references between objects, after final 57 | * model bounds have been computed. 58 | */ 59 | joinRefs: function() { 60 | } 61 | }; 62 | 63 | 64 | var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE); 65 | options.defaultMetadata = {}; 66 | options.mandatoryBaseClass = Importer; 67 | tr.b.decorateExtensionRegistry(Importer, options); 68 | 69 | Importer.findImporterFor = function(eventData) { 70 | var typeInfo = Importer.findTypeInfoMatching(function(ti) { 71 | return ti.constructor.canImport(eventData); 72 | }); 73 | if (typeInfo) 74 | return typeInfo.constructor; 75 | return undefined; 76 | }; 77 | 78 | return { 79 | Importer: Importer 80 | }; 81 | }); 82 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/selection_state.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/base.js"); 8 | require("../base/color_scheme.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview Provides the SelectionState class. 14 | */ 15 | global.tr.exportTo('tr.model', function() { 16 | var ColorScheme = tr.b.ColorScheme; 17 | 18 | /** 19 | * Describes the level of visual highlighting to apply to an event when shown. 20 | * 21 | * color_scheme.html defines N variations off of a base color palette, 22 | * one for each selection state, all concatenated into one flat array. To 23 | * pick the final colorId for a given variations, the SelectionState is 24 | * multiplied by the number of base colors. 25 | * 26 | * Thus, the values here must be kept in sync with color_scheme's palette 27 | * layout. 28 | */ 29 | var SelectionState = { 30 | NONE: 0, 31 | 32 | // Legacy names. 33 | SELECTED: ColorScheme.properties.brightenedOffsets[0], 34 | HIGHLIGHTED: ColorScheme.properties.brightenedOffsets[1], 35 | DIMMED: ColorScheme.properties.dimmedOffsets[0], 36 | 37 | // Modern names. 38 | BRIGHTENED0: ColorScheme.properties.brightenedOffsets[0], 39 | BRIGHTENED1: ColorScheme.properties.brightenedOffsets[1], 40 | BRIGHTENED2: ColorScheme.properties.brightenedOffsets[2], 41 | 42 | DIMMED0: ColorScheme.properties.dimmedOffsets[0], 43 | DIMMED1: ColorScheme.properties.dimmedOffsets[1], 44 | DIMMED2: ColorScheme.properties.dimmedOffsets[2] 45 | }; 46 | 47 | var brighteningLevels = [ 48 | SelectionState.NONE, 49 | SelectionState.BRIGHTENED0, 50 | SelectionState.BRIGHTENED1, 51 | SelectionState.BRIGHTENED2 52 | ]; 53 | SelectionState.getFromBrighteningLevel = function(level) { 54 | return brighteningLevels[level]; 55 | } 56 | 57 | var dimmingLevels = [ 58 | SelectionState.DIMMED0, 59 | SelectionState.DIMMED1, 60 | SelectionState.DIMMED2 61 | ]; 62 | SelectionState.getFromDimmingLevel = function(level) { 63 | return dimmingLevels[level]; 64 | } 65 | 66 | return { 67 | SelectionState: SelectionState 68 | }; 69 | }); 70 | -------------------------------------------------------------------------------- /lib/global-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2015 Google Inc. All Rights Reserved. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | function enable () { 19 | // Sets some global options so that the trace viewer code can work. 20 | // It expects to be run inside of a browser, where host objects 21 | // (and Polymer) exist. Since they don't they need stubbing out. 22 | global.Polymer = function () {}; 23 | global.Polymer.elements = {}; 24 | 25 | global.HTMLUnknownElement = {}; 26 | global.HTMLDivElement = {}; 27 | global.document = { 28 | currentScript: { 29 | ownerDocument: {} 30 | }, 31 | 32 | createElement: function () { 33 | return { 34 | style: { 35 | 36 | } 37 | }; 38 | } 39 | }; 40 | 41 | global.vec2 = {create: function () {}, set: function () {}}; 42 | global.vec3 = {create: function () {}}; 43 | global.vec4 = {create: function () {}}; 44 | global.mat2d = {create: function () {}}; 45 | global.mat4 = {create: function () {}}; 46 | global.window = { 47 | performance: { 48 | now: function () { 49 | return Date.now(); 50 | } 51 | }, webkitRequestAnimationFrame: function (cb) { 52 | cb(); 53 | }, requestAnimationFrame: function (cb) { 54 | cb(); 55 | } 56 | }; 57 | } 58 | 59 | function disable () { 60 | 61 | delete global.Polymer.elements; 62 | delete global.Polymer; 63 | 64 | delete global.HTMLUnknownElement; 65 | delete global.HTMLDivElement; 66 | delete global.document; 67 | 68 | delete global.vec2; 69 | delete global.vec3; 70 | delete global.vec4; 71 | delete global.mat2d; 72 | delete global.mat4; 73 | delete global.window; 74 | } 75 | 76 | module.exports = { 77 | enable: enable, 78 | disable: disable 79 | }; 80 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/annotation.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/extension_registry.js"); 8 | require("../base/guid.js"); 9 | 10 | 'use strict'; 11 | 12 | global.tr.exportTo('tr.model', function() { 13 | /** 14 | * Annotation is a base class that represents all annotation objects that 15 | * can be drawn on the timeline. 16 | * 17 | * @constructor 18 | */ 19 | function Annotation() { 20 | this.guid_ = tr.b.GUID.allocate(); 21 | this.view_ = undefined; 22 | }; 23 | 24 | Annotation.fromDictIfPossible = function(args) { 25 | if (args.typeName === undefined) 26 | throw new Error('Missing typeName argument'); 27 | 28 | var typeInfo = Annotation.findTypeInfoMatching(function(typeInfo) { 29 | return typeInfo.metadata.typeName === args.typeName; 30 | }); 31 | 32 | if (typeInfo === undefined) 33 | return undefined; 34 | 35 | return typeInfo.constructor.fromDict(args); 36 | }; 37 | 38 | Annotation.fromDict = function() { 39 | throw new Error('Not implemented'); 40 | } 41 | 42 | Annotation.prototype = { 43 | get guid() { 44 | return this.guid_; 45 | }, 46 | 47 | // Invoked by trace model when this annotation is removed. 48 | onRemove: function() { 49 | }, 50 | 51 | toDict: function() { 52 | throw new Error('Not implemented'); 53 | }, 54 | 55 | getOrCreateView: function(viewport) { 56 | if (!this.view_) 57 | this.view_ = this.createView_(viewport); 58 | return this.view_; 59 | }, 60 | 61 | createView_: function() { 62 | throw new Error('Not implemented'); 63 | } 64 | }; 65 | 66 | var options = new tr.b.ExtensionRegistryOptions(tr.b. BASIC_REGISTRY_MODE); 67 | tr.b.decorateExtensionRegistry(Annotation, options); 68 | 69 | Annotation.addEventListener('will-register', function(e) { 70 | if (!e.typeInfo.constructor.hasOwnProperty('fromDict')) 71 | throw new Error('Must have fromDict method'); 72 | 73 | if (!e.typeInfo.metadata.typeName) 74 | throw new Error('Registered Annotations must provide typeName'); 75 | }); 76 | 77 | return { 78 | Annotation: Annotation 79 | }; 80 | }); 81 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/instant_event.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/units/time_stamp.js"); 8 | require("./timed_event.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview Provides the InstantEvent class. 14 | */ 15 | global.tr.exportTo('tr.model', function() { 16 | var InstantEventType = { 17 | GLOBAL: 1, 18 | PROCESS: 2 19 | }; 20 | 21 | function InstantEvent(category, title, colorId, start, args) { 22 | tr.model.TimedEvent.call(this); 23 | 24 | this.category = category || ''; 25 | this.title = title; 26 | this.colorId = colorId; 27 | this.start = start; 28 | this.args = args; 29 | 30 | this.type = undefined; 31 | }; 32 | 33 | InstantEvent.prototype = { 34 | __proto__: tr.model.TimedEvent.prototype 35 | }; 36 | 37 | function GlobalInstantEvent(category, title, colorId, start, args) { 38 | InstantEvent.apply(this, arguments); 39 | this.type = InstantEventType.GLOBAL; 40 | }; 41 | 42 | GlobalInstantEvent.prototype = { 43 | __proto__: InstantEvent.prototype, 44 | get userFriendlyName() { 45 | return 'Global instant event ' + this.title + ' @ ' + 46 | tr.b.u.TimeStamp.format(start); 47 | } 48 | }; 49 | 50 | function ProcessInstantEvent(category, title, colorId, start, args) { 51 | InstantEvent.apply(this, arguments); 52 | this.type = InstantEventType.PROCESS; 53 | }; 54 | 55 | ProcessInstantEvent.prototype = { 56 | __proto__: InstantEvent.prototype, 57 | 58 | get userFriendlyName() { 59 | return 'Process-level instant event ' + this.title + ' @ ' + 60 | tr.b.u.TimeStamp.format(start); 61 | } 62 | }; 63 | 64 | tr.model.EventRegistry.register( 65 | InstantEvent, 66 | { 67 | name: 'instantEvent', 68 | pluralName: 'instantEvents', 69 | singleViewElementName: 'tr-ui-a-single-instant-event-sub-view', 70 | multiViewElementName: 'tr-ui-a-multi-instant-event-sub-view' 71 | }); 72 | 73 | return { 74 | GlobalInstantEvent: GlobalInstantEvent, 75 | ProcessInstantEvent: ProcessInstantEvent, 76 | 77 | InstantEventType: InstantEventType, 78 | InstantEvent: InstantEvent 79 | }; 80 | }); 81 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/container_memory_dump.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./timed_event.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Provides the ContainerMemoryDump class. 13 | */ 14 | global.tr.exportTo('tr.model', function() { 15 | /** 16 | * The ContainerMemoryDump represents an abstract container memory dump. 17 | * @constructor 18 | */ 19 | function ContainerMemoryDump(start) { 20 | tr.model.TimedEvent.call(this, start); 21 | 22 | // 'light' or 'detailed' memory dump. See 23 | // base::trace_event::MemoryDumpLevelOfDetail in the Chromium 24 | // repository. 25 | this.levelOfDetail = undefined; 26 | 27 | this.memoryAllocatorDumps_ = undefined; 28 | this.memoryAllocatorDumpsByFullName_ = undefined; 29 | }; 30 | 31 | ContainerMemoryDump.prototype = { 32 | __proto__: tr.model.TimedEvent.prototype, 33 | 34 | shiftTimestampsForward: function(amount) { 35 | this.start += amount; 36 | }, 37 | 38 | get memoryAllocatorDumps() { 39 | return this.memoryAllocatorDumps_; 40 | }, 41 | 42 | set memoryAllocatorDumps(memoryAllocatorDumps) { 43 | this.memoryAllocatorDumps_ = memoryAllocatorDumps; 44 | 45 | // Clear the index and generate it lazily. 46 | this.memoryAllocatorDumpsByFullName_ = undefined; 47 | }, 48 | 49 | getMemoryAllocatorDumpByFullName: function(fullName) { 50 | if (this.memoryAllocatorDumps_ === undefined) 51 | return undefined; 52 | 53 | // Lazily generate the index if necessary. 54 | if (this.memoryAllocatorDumpsByFullName_ === undefined) { 55 | var index = {}; 56 | function addDumpsToIndex(dumps) { 57 | dumps.forEach(function(dump) { 58 | index[dump.fullName] = dump; 59 | addDumpsToIndex(dump.children); 60 | }); 61 | }; 62 | addDumpsToIndex(this.memoryAllocatorDumps_); 63 | this.memoryAllocatorDumpsByFullName_ = index; 64 | } 65 | 66 | return this.memoryAllocatorDumpsByFullName_[fullName]; 67 | }, 68 | 69 | iterateRootAllocatorDumps: function(fn, opt_this) { 70 | if (this.memoryAllocatorDumps === undefined) 71 | return; 72 | this.memoryAllocatorDumps.forEach(fn, opt_this || this); 73 | } 74 | }; 75 | 76 | return { 77 | ContainerMemoryDump: ContainerMemoryDump 78 | }; 79 | }); 80 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/interaction_record.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/units/time_stamp.js"); 8 | require("./compound_event_selection_state.js"); 9 | require("./event_set.js"); 10 | require("./timed_event.js"); 11 | 12 | 'use strict'; 13 | 14 | global.tr.exportTo('tr.model', function() { 15 | var CompoundEventSelectionState = tr.model.CompoundEventSelectionState; 16 | 17 | function InteractionRecord(parentModel, title, colorId, start, duration) { 18 | tr.model.TimedEvent.call(this, start); 19 | this.title = title; 20 | this.colorId = colorId; 21 | this.duration = duration; 22 | this.args = {}; 23 | this.associatedEvents = new tr.model.EventSet(); 24 | this.parentModel = parentModel; 25 | 26 | // sourceEvents are the ones that caused the IR Finder to create this IR. 27 | this.sourceEvents = new tr.model.EventSet(); 28 | } 29 | 30 | InteractionRecord.prototype = { 31 | __proto__: tr.model.TimedEvent.prototype, 32 | 33 | get subSlices() { 34 | return []; 35 | }, 36 | 37 | get userFriendlyName() { 38 | return this.title + ' interaction at ' + 39 | tr.b.u.TimeStamp.format(this.start); 40 | }, 41 | 42 | get stableId() { 43 | return 'IR.' + this.parentModel.interactionRecords.indexOf(this); 44 | }, 45 | 46 | computeCompoundEvenSelectionState: function(selection) { 47 | var cess = CompoundEventSelectionState.NOT_SELECTED; 48 | if (selection.contains(this)) 49 | cess |= CompoundEventSelectionState.EVENT_SELECTED; 50 | 51 | if (this.associatedEvents.intersectionIsEmpty(selection)) 52 | return cess; 53 | 54 | var allContained = this.associatedEvents.every(function(event) { 55 | return selection.contains(event); 56 | }); 57 | 58 | if (allContained) 59 | cess |= CompoundEventSelectionState.ALL_ASSOCIATED_EVENTS_SELECTED; 60 | else 61 | cess |= CompoundEventSelectionState.SOME_ASSOCIATED_EVENTS_SELECTED; 62 | return cess; 63 | } 64 | }; 65 | 66 | tr.model.EventRegistry.register( 67 | InteractionRecord, 68 | { 69 | name: 'interaction', 70 | pluralName: 'interactions', 71 | singleViewElementName: 'tr-ui-a-single-interaction-record-sub-view', 72 | multiViewElementName: 'tr-ui-a-multi-interaction-record-sub-view' 73 | }); 74 | 75 | return { 76 | InteractionRecord: InteractionRecord 77 | }; 78 | }); 79 | -------------------------------------------------------------------------------- /lib/third_party/tracing/base/extension_registry.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./iteration_helpers.js"); 8 | require("./event_target.js"); 9 | require("./extension_registry_basic.js"); 10 | require("./extension_registry_type_based.js"); 11 | 12 | 'use strict'; 13 | 14 | /** 15 | * @fileoverview Helper code for defining extension registries, which can be 16 | * used to make a part of trace-viewer extensible. 17 | * 18 | * This file provides two basic types of extension registries: 19 | * - Generic: register a type with metadata, query for those types based on 20 | * a predicate 21 | * 22 | * - TypeName-based: register a type that handles some combination 23 | * of tracing categories or typeNames, then query 24 | * for it based on a category, typeName or both. 25 | * 26 | * Use these for pure-JS classes or ui.define'd classes. For polymer element 27 | * related registries, consult base/polymer_utils.html. 28 | * 29 | * When you register subtypes, you pass the constructor for the 30 | * subtype, and any metadata you want associated with the subtype. Use metadata 31 | * instead of stuffing fields onto the constructor. E.g.: 32 | * registry.register(MySubclass, {titleWhenShownInTabStrip: 'MySub'}) 33 | * 34 | * Some registries want a default object that is returned when a more precise 35 | * subtype has been registered. To provide one, set the defaultConstructor 36 | * option on the registry options. 37 | * 38 | * TODO: Extension registry used to make reference to mandatoryBaseType but it 39 | * was never enforced. We may want to add it back in the future in order to 40 | * enforce the types that can be put into a given registry. 41 | */ 42 | global.tr.exportTo('tr.b', function() { 43 | 44 | function decorateExtensionRegistry(registry, registryOptions) { 45 | if (registry.register) 46 | throw new Error('Already has registry'); 47 | 48 | registryOptions.freeze(); 49 | if (registryOptions.mode == tr.b.BASIC_REGISTRY_MODE) { 50 | tr.b._decorateBasicExtensionRegistry(registry, registryOptions); 51 | } else if (registryOptions.mode == tr.b.TYPE_BASED_REGISTRY_MODE) { 52 | tr.b._decorateTypeBasedExtensionRegistry(registry, registryOptions); 53 | } else { 54 | throw new Error('Unrecognized mode'); 55 | } 56 | 57 | // Make it an event target. 58 | if (registry.addEventListener === undefined) 59 | tr.b.EventTarget.decorate(registry); 60 | } 61 | 62 | return { 63 | decorateExtensionRegistry: decorateExtensionRegistry 64 | }; 65 | }); 66 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/rail/response_interaction_record.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../base/units/histogram.js"); 8 | require("./rail_interaction_record.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview The Response phase of RAIL. 14 | */ 15 | global.tr.exportTo('tr.e.rail', function() { 16 | // This histogram represents the number of people who we believe would have 17 | // comfort with a response level of a certain value. We have set this with 18 | // just a best-effort guess, though. In #1696, we plan to derive this 19 | // experimentally. 20 | var COMFORT_HISTOGRAM = tr.b.u.Histogram.fromDict({ 21 | unit: 'unitless', 22 | min: 150, 23 | max: 5000, 24 | centralBinWidth: 485, 25 | underflowBin: {min: -Number.MAX_VALUE, max: 150, count: 1000}, 26 | centralBins: [ 27 | {min: 150, max: 635, count: 708}, 28 | {min: 635, max: 1120, count: 223}, 29 | {min: 1120, max: 1605, count: 50}, 30 | {min: 1605, max: 2090, count: 33}, 31 | {min: 2090, max: 2575, count: 23}, 32 | {min: 2575, max: 3060, count: 17}, 33 | {min: 3060, max: 3545, count: 12}, 34 | {min: 3545, max: 4030, count: 8}, 35 | {min: 4030, max: 4515, count: 4}, 36 | {min: 4515, max: 5000, count: 1} 37 | ], 38 | overflowBin: {min: 5000, max: Number.MAX_VALUE, count: 0} 39 | }); 40 | 41 | function ResponseInteractionRecord(parentModel, start, duration) { 42 | tr.e.rail.RAILInteractionRecord.call( 43 | this, parentModel, 'Response', 'rail_response', start, duration); 44 | } 45 | 46 | ResponseInteractionRecord.prototype = { 47 | __proto__: tr.e.rail.RAILInteractionRecord.prototype, 48 | 49 | get normalizedUserComfort() { 50 | // User comfort is derived from the time between when the user thinks they 51 | // begin an interation (expectedStart) and the time when the screen first 52 | // changes to reflect the interaction (actualEnd). There may be a delay 53 | // between expectedStart and when chrome first starts processing the 54 | // interaction (actualStart) if the main thread is busy. The user doesn't 55 | // know when actualStart is, they only know when expectedStart is. User 56 | // comfort, by definition, considers only what the user experiences, so 57 | // "duration" is defined as actualEnd - expectedStart. 58 | 59 | return COMFORT_HISTOGRAM.getInterpolatedCountAt(this.duration) / 60 | COMFORT_HISTOGRAM.maxCount; 61 | } 62 | }; 63 | 64 | return { 65 | ResponseInteractionRecord: ResponseInteractionRecord 66 | }; 67 | }); 68 | -------------------------------------------------------------------------------- /lib/third_party/tracing/ui/base/deep_utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../base/base.js"); 8 | 9 | 10 | 'use strict'; 11 | 12 | global.tr.exportTo('tr.b', function() { 13 | function _iterateElementDeeplyImpl(element, cb, thisArg, includeElement) { 14 | if (includeElement) { 15 | if (cb.call(thisArg, element)) 16 | return true; 17 | } 18 | 19 | if (element.shadowRoot) { 20 | if (_iterateElementDeeplyImpl(element.shadowRoot, cb, thisArg, false)) 21 | return true; 22 | } 23 | for (var i = 0; i < element.children.length; i++) { 24 | if (_iterateElementDeeplyImpl(element.children[i], cb, thisArg, true)) 25 | return true; 26 | } 27 | } 28 | function iterateElementDeeply(element, cb, thisArg) { 29 | _iterateElementDeeplyImpl(element, cb, thisArg, false); 30 | } 31 | 32 | function findDeepElementMatchingPredicate(element, predicate) { 33 | var foundElement = undefined; 34 | function matches(element) { 35 | var match = predicate(element); 36 | if (!match) 37 | return false; 38 | foundElement = element; 39 | return true; 40 | } 41 | iterateElementDeeply(element, matches); 42 | return foundElement; 43 | } 44 | 45 | function findDeepElementsMatchingPredicate(element, predicate) { 46 | var foundElements = []; 47 | function matches(element) { 48 | var match = predicate(element); 49 | if (match) { 50 | foundElements.push(element); 51 | } 52 | return false; 53 | } 54 | iterateElementDeeply(element, matches); 55 | return foundElements; 56 | } 57 | 58 | function findDeepElementMatching(element, selector) { 59 | return findDeepElementMatchingPredicate(element, function(element) { 60 | return element.matches(selector); 61 | }); 62 | } 63 | function findDeepElementsMatching(element, selector) { 64 | return findDeepElementsMatchingPredicate(element, function(element) { 65 | return element.matches(selector); 66 | }); 67 | } 68 | function findDeepElementWithTextContent(element, re) { 69 | return findDeepElementMatchingPredicate(element, function(element) { 70 | if (element.children.length !== 0) 71 | return false; 72 | return re.test(element.textContent); 73 | }); 74 | } 75 | return { 76 | iterateElementDeeply: iterateElementDeeply, 77 | findDeepElementMatching: findDeepElementMatching, 78 | findDeepElementsMatching: findDeepElementsMatching, 79 | findDeepElementMatchingPredicate: findDeepElementMatchingPredicate, 80 | findDeepElementsMatchingPredicate: findDeepElementsMatchingPredicate, 81 | findDeepElementWithTextContent: findDeepElementWithTextContent 82 | }; 83 | }); 84 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/chrome/chrome_process_helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../base/base.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Utilities for accessing trace data about the Chrome browser. 13 | */ 14 | global.tr.exportTo('tr.e.audits', function() { 15 | var MAIN_FRAMETIME_TYPE = 'main_frametime_type'; 16 | var IMPL_FRAMETIME_TYPE = 'impl_frametime_type'; 17 | 18 | var MAIN_RENDERING_STATS = 19 | 'BenchmarkInstrumentation::MainThreadRenderingStats'; 20 | var IMPL_RENDERING_STATS = 21 | 'BenchmarkInstrumentation::ImplThreadRenderingStats'; 22 | 23 | 24 | function getSlicesIntersectingRange(rangeOfInterest, slices) { 25 | var slicesInFilterRange = []; 26 | for (var i = 0; i < slices.length; i++) { 27 | var slice = slices[i]; 28 | if (rangeOfInterest.intersectsExplicitRangeInclusive( 29 | slice.start, slice.end)) 30 | slicesInFilterRange.push(slice); 31 | } 32 | return slicesInFilterRange; 33 | } 34 | 35 | 36 | function ChromeProcessHelper(modelHelper, process) { 37 | this.modelHelper = modelHelper; 38 | this.process = process; 39 | } 40 | 41 | ChromeProcessHelper.prototype = { 42 | get pid() { 43 | return this.process.pid; 44 | }, 45 | 46 | getFrameEventsInRange: function(frametimeType, range) { 47 | var titleToGet; 48 | if (frametimeType == MAIN_FRAMETIME_TYPE) 49 | titleToGet = MAIN_RENDERING_STATS; 50 | else 51 | titleToGet = IMPL_RENDERING_STATS; 52 | 53 | var frameEvents = []; 54 | this.process.iterateAllEvents(function(event) { 55 | if (event.title !== titleToGet) 56 | return; 57 | if (range.intersectsExplicitRangeInclusive(event.start, event.end)) 58 | frameEvents.push(event); 59 | }); 60 | 61 | frameEvents.sort(function(a, b) {return a.start - b.start}); 62 | return frameEvents; 63 | } 64 | }; 65 | 66 | function getFrametimeDataFromEvents(frameEvents) { 67 | var frametimeData = []; 68 | for (var i = 1; i < frameEvents.length; i++) { 69 | var diff = frameEvents[i].start - frameEvents[i - 1].start; 70 | frametimeData.push({ 71 | 'x': frameEvents[i].start, 72 | 'frametime': diff 73 | }); 74 | } 75 | return frametimeData; 76 | } 77 | 78 | return { 79 | ChromeProcessHelper: ChromeProcessHelper, 80 | 81 | MAIN_FRAMETIME_TYPE: MAIN_FRAMETIME_TYPE, 82 | IMPL_FRAMETIME_TYPE: IMPL_FRAMETIME_TYPE, 83 | MAIN_RENDERING_STATS: MAIN_RENDERING_STATS, 84 | IMPL_RENDERING_STATS: IMPL_RENDERING_STATS, 85 | 86 | getSlicesIntersectingRange: getSlicesIntersectingRange, 87 | getFrametimeDataFromEvents: getFrametimeDataFromEvents 88 | }; 89 | }); 90 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/linux_perf/bus_parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./parser.js"); 8 | require("../../../model/counter_series.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview Parses trace_marker events that were inserted in the trace by 14 | * userland. 15 | */ 16 | global.tr.exportTo('tr.e.importer.linux_perf', function() { 17 | var ColorScheme = tr.b.ColorScheme; 18 | var Parser = tr.e.importer.linux_perf.Parser; 19 | 20 | /** 21 | * Parses linux trace mark events that were inserted in the trace by userland. 22 | * @constructor 23 | */ 24 | function BusParser(importer) { 25 | Parser.call(this, importer); 26 | 27 | importer.registerEventHandler('memory_bus_usage', 28 | BusParser.prototype.traceMarkWriteBusEvent.bind(this)); 29 | 30 | this.model_ = importer.model_; 31 | this.ppids_ = {}; 32 | } 33 | 34 | BusParser.prototype = { 35 | __proto__: Parser.prototype, 36 | 37 | traceMarkWriteBusEvent: function(eventName, cpuNumber, pid, ts, 38 | eventBase, threadName) { 39 | var re = new RegExp('bus=(\\S+) rw_bytes=(\\d+) r_bytes=(\\d+) ' + 40 | 'w_bytes=(\\d+) cycles=(\\d+) ns=(\\d+)'); 41 | var event = re.exec(eventBase.details); 42 | 43 | var name = event[1]; 44 | var rw_bytes = parseInt(event[2]); 45 | var r_bytes = parseInt(event[3]); 46 | var w_bytes = parseInt(event[4]); 47 | var cycles = parseInt(event[5]); 48 | var ns = parseInt(event[6]); 49 | 50 | // BW in MB/s 51 | var r_bw = r_bytes * 1000000000 / ns; 52 | r_bw /= 1024 * 1024; 53 | var w_bw = w_bytes * 1000000000 / ns; 54 | w_bw /= 1024 * 1024; 55 | 56 | var ctr = this.model_.kernel 57 | .getOrCreateCounter(null, 'bus ' + name + ' read'); 58 | if (ctr.numSeries === 0) { 59 | ctr.addSeries(new tr.model.CounterSeries('value', 60 | ColorScheme.getColorIdForGeneralPurposeString( 61 | ctr.name + '.' + 'value'))); 62 | } 63 | ctr.series.forEach(function(series) { 64 | series.addCounterSample(ts, r_bw); 65 | }); 66 | 67 | ctr = this.model_.kernel 68 | .getOrCreateCounter(null, 'bus ' + name + ' write'); 69 | if (ctr.numSeries === 0) { 70 | ctr.addSeries(new tr.model.CounterSeries('value', 71 | ColorScheme.getColorIdForGeneralPurposeString( 72 | ctr.name + '.' + 'value'))); 73 | } 74 | ctr.series.forEach(function(series) { 75 | series.addCounterSample(ts, r_bw); 76 | }); 77 | 78 | return true; 79 | } 80 | }; 81 | 82 | Parser.register(BusParser); 83 | 84 | return { 85 | BusParser: BusParser 86 | }; 87 | }); 88 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/frame.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/color_scheme.js"); 8 | require("../base/statistics.js"); 9 | require("./event.js"); 10 | require("./event_set.js"); 11 | 12 | 'use strict'; 13 | 14 | /** 15 | * @fileoverview Class describing rendered frames. 16 | * 17 | * Because a frame is produced by multiple threads, it does not inherit from 18 | * TimedEvent, and has no duration. 19 | */ 20 | global.tr.exportTo('tr.model', function() { 21 | var ColorScheme = tr.b.ColorScheme; 22 | var Statistics = tr.b.Statistics; 23 | 24 | var FRAME_PERF_CLASS = { 25 | GOOD: 'good', 26 | BAD: 'bad', 27 | TERRIBLE: 'terrible', 28 | NEUTRAL: 'generic_work' 29 | }; 30 | 31 | /** 32 | * @constructor 33 | * @param {Array} associatedEvents Selection of events composing the frame. 34 | * @param {Array} threadTimeRanges Array of {thread, start, end} 35 | * for each thread, describing the critical path of the frame. 36 | */ 37 | function Frame(associatedEvents, threadTimeRanges, opt_args) { 38 | tr.model.Event.call(this); 39 | 40 | this.threadTimeRanges = threadTimeRanges; 41 | this.associatedEvents = new tr.model.EventSet(associatedEvents); 42 | this.args = opt_args || {}; 43 | 44 | this.title = 'Frame'; 45 | this.start = Statistics.min( 46 | threadTimeRanges, function(x) { return x.start; }); 47 | this.end = Statistics.max( 48 | threadTimeRanges, function(x) { return x.end; }); 49 | this.totalDuration = Statistics.sum( 50 | threadTimeRanges, function(x) { return x.end - x.start; }); 51 | 52 | this.perfClass = FRAME_PERF_CLASS.NEUTRAL; 53 | }; 54 | 55 | Frame.prototype = { 56 | __proto__: tr.model.Event.prototype, 57 | 58 | set perfClass(perfClass) { 59 | this.colorId = ColorScheme.getColorIdForReservedName(perfClass); 60 | this.perfClass_ = perfClass; 61 | }, 62 | 63 | get perfClass() { 64 | return this.perfClass_; 65 | }, 66 | 67 | shiftTimestampsForward: function(amount) { 68 | this.start += amount; 69 | this.end += amount; 70 | 71 | for (var i = 0; i < this.threadTimeRanges.length; i++) { 72 | this.threadTimeRanges[i].start += amount; 73 | this.threadTimeRanges[i].end += amount; 74 | } 75 | }, 76 | 77 | addBoundsToRange: function(range) { 78 | range.addValue(this.start); 79 | range.addValue(this.end); 80 | } 81 | }; 82 | 83 | tr.model.EventRegistry.register( 84 | Frame, 85 | { 86 | name: 'frame', 87 | pluralName: 'frames', 88 | singleViewElementName: 'tr-ui-a-single-frame-sub-view', 89 | multiViewElementName: 'tr-ui-a-multi-frame-sub-view' 90 | }); 91 | 92 | return { 93 | Frame: Frame, 94 | FRAME_PERF_CLASS: FRAME_PERF_CLASS 95 | }; 96 | }); 97 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/device.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/guid.js"); 8 | require("../base/range.js"); 9 | require("./event_container.js"); 10 | require("./power_series.js"); 11 | 12 | 'use strict'; 13 | 14 | /** 15 | * @fileoverview Provides the Device class. 16 | */ 17 | global.tr.exportTo('tr.model', function() { 18 | 19 | /** 20 | * Device represents the device-level objects in the model. 21 | * @constructor 22 | * @extends {tr.model.EventContainer} 23 | */ 24 | function Device(model) { 25 | if (!model) 26 | throw new Error('Must provide a model.'); 27 | 28 | tr.model.EventContainer.call(this); 29 | 30 | this.powerSeries_ = undefined; 31 | this.vSyncTimestamps_ = []; 32 | }; 33 | 34 | Device.compare = function(x, y) { 35 | return x.guid - y.guid; 36 | }; 37 | 38 | Device.prototype = { 39 | __proto__: tr.model.EventContainer.prototype, 40 | 41 | compareTo: function(that) { 42 | return Device.compare(this, that); 43 | }, 44 | 45 | get userFriendlyName() { 46 | return 'Device'; 47 | }, 48 | 49 | get userFriendlyDetails() { 50 | return 'Device'; 51 | }, 52 | 53 | get stableId() { 54 | return 'Device'; 55 | }, 56 | 57 | getSettingsKey: function() { 58 | return 'device'; 59 | }, 60 | 61 | get powerSeries() { 62 | return this.powerSeries_; 63 | }, 64 | 65 | set powerSeries(powerSeries) { 66 | this.powerSeries_ = powerSeries; 67 | }, 68 | 69 | get vSyncTimestamps() { 70 | return this.vSyncTimestamps_; 71 | }, 72 | 73 | set vSyncTimestamps(value) { 74 | this.vSyncTimestamps_ = value; 75 | }, 76 | 77 | updateBounds: function() { 78 | this.bounds.reset(); 79 | 80 | this.iterateAllChildEventContainers(function(child) { 81 | child.updateBounds(); 82 | this.bounds.addRange(child.bounds); 83 | }, this); 84 | }, 85 | 86 | shiftTimestampsForward: function(amount) { 87 | this.iterateAllChildEventContainers(function(child) { 88 | child.shiftTimestampsForward(amount); 89 | }); 90 | 91 | for (var i = 0; i < this.vSyncTimestamps_.length; i++) 92 | this.vSyncTimestamps_[i] += amount; 93 | }, 94 | 95 | addCategoriesToDict: function(categoriesDict) { 96 | }, 97 | 98 | iterateAllEventsInThisContainer: function(eventTypePredicate, 99 | callback, opt_this) { 100 | }, 101 | 102 | iterateAllChildEventContainers: function(callback, opt_this) { 103 | if (this.powerSeries_) 104 | callback.call(opt_this, this.powerSeries_); 105 | } 106 | }; 107 | 108 | return { 109 | Device: Device 110 | }; 111 | }); 112 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/rail/load_interaction_record.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../base/units/histogram.js"); 8 | require("./rail_interaction_record.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview The Load phase of RAIL. 14 | */ 15 | global.tr.exportTo('tr.e.rail', function() { 16 | // This histogram represents the number of people who we believe would have 17 | // comfort with a response level of a certain value. We have set this with 18 | // just a best-effort guess, though. In #1696, we plan to derive this 19 | // experimentally. 20 | var COMFORT_HISTOGRAM = tr.b.u.Histogram.fromDict({ 21 | unit: 'unitless', 22 | min: 1000, 23 | max: 60000, 24 | centralBinWidth: 5900, 25 | underflowBin: {min: -Number.MAX_VALUE, max: 1000, count: 1000}, 26 | centralBins: [ 27 | {min: 1000, max: 6900, count: 901}, 28 | {min: 6900, max: 12800, count: 574}, 29 | {min: 12800, max: 18700, count: 298}, 30 | {min: 18700, max: 24600, count: 65}, 31 | {min: 24600, max: 30500, count: 35}, 32 | {min: 30500, max: 36400, count: 23}, 33 | {min: 36400, max: 42300, count: 16}, 34 | {min: 42300, max: 48200, count: 10}, 35 | {min: 48200, max: 54100, count: 5}, 36 | {min: 54100, max: 60000, count: 2} 37 | ], 38 | overflowBin: {min: 60000, max: Number.MAX_VALUE, count: 0} 39 | }); 40 | 41 | function LoadInteractionRecord(parentModel, start, duration) { 42 | tr.e.rail.RAILInteractionRecord.call( 43 | this, parentModel, 'Load', 'rail_load', 44 | start, duration); 45 | 46 | // |renderProcess| is the renderer process that contains the loading 47 | // RenderFrame. 48 | this.renderProcess = undefined; 49 | 50 | // |renderMainThread| is the CrRendererMain thread in the |renderProcess| 51 | // that contains the loading RenderFrame. 52 | this.renderMainThread = undefined; 53 | 54 | // |routingId| identifies the loading RenderFrame within the renderer 55 | // process. 56 | this.routingId = undefined; 57 | 58 | // |parentRoutingId| identifies the RenderFrame that created and contains 59 | // the loading RenderFrame. 60 | this.parentRoutingId = undefined; 61 | 62 | // |loadFinishedEvent|, if present, signals that this is a main frame. 63 | this.loadFinishedEvent = undefined; 64 | 65 | // Startup LoadIRs do not have renderProcess, routingId, or 66 | // parentRoutingId. Maybe RenderLoadIR should be a separate class? 67 | } 68 | 69 | LoadInteractionRecord.prototype = { 70 | __proto__: tr.e.rail.RAILInteractionRecord.prototype, 71 | 72 | get normalizedUserComfort() { 73 | return COMFORT_HISTOGRAM.getInterpolatedCountAt(this.duration) / 74 | COMFORT_HISTOGRAM.maxCount; 75 | } 76 | }; 77 | 78 | return { 79 | LoadInteractionRecord: LoadInteractionRecord 80 | }; 81 | }); 82 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/counter_sample.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/iteration_helpers.js"); 8 | require("../base/sorted_array_utils.js"); 9 | require("../base/units/time_stamp.js"); 10 | require("./event.js"); 11 | 12 | 'use strict'; 13 | 14 | global.tr.exportTo('tr.model', function() { 15 | 16 | /** 17 | * The value of a given measurement at a given time. 18 | * 19 | * As an example, if we're measuring the throughput of data sent over a USB 20 | * connection, each counter sample might represent the instantaneous 21 | * throughput of the connection at a given time. 22 | * 23 | * @constructor 24 | * @extends {Event} 25 | */ 26 | function CounterSample(series, timestamp, value) { 27 | tr.model.Event.call(this); 28 | this.series_ = series; 29 | this.timestamp_ = timestamp; 30 | this.value_ = value; 31 | } 32 | 33 | CounterSample.groupByTimestamp = function(samples) { 34 | var samplesByTimestamp = tr.b.group(samples, function(sample) { 35 | return sample.timestamp; 36 | }); 37 | 38 | var timestamps = tr.b.dictionaryKeys(samplesByTimestamp); 39 | timestamps.sort(); 40 | var groups = []; 41 | for (var i = 0; i < timestamps.length; i++) { 42 | var ts = timestamps[i]; 43 | var group = samplesByTimestamp[ts]; 44 | group.sort(function(x, y) { 45 | return x.series.seriesIndex - y.series.seriesIndex; 46 | }); 47 | groups.push(group); 48 | } 49 | return groups; 50 | } 51 | 52 | CounterSample.prototype = { 53 | __proto__: tr.model.Event.prototype, 54 | 55 | get series() { 56 | return this.series_; 57 | }, 58 | 59 | get timestamp() { 60 | return this.timestamp_; 61 | }, 62 | 63 | get value() { 64 | return this.value_; 65 | }, 66 | 67 | set timestamp(timestamp) { 68 | this.timestamp_ = timestamp; 69 | }, 70 | 71 | addBoundsToRange: function(range) { 72 | range.addValue(this.timestamp); 73 | }, 74 | 75 | getSampleIndex: function() { 76 | return tr.b.findLowIndexInSortedArray( 77 | this.series.timestamps, 78 | function(x) { return x; }, 79 | this.timestamp_); 80 | }, 81 | 82 | get userFriendlyName() { 83 | return 'Counter sample from ' + this.series_.title + ' at ' + 84 | tr.b.u.TimeStamp.format(this.timestamp); 85 | } 86 | }; 87 | 88 | 89 | tr.model.EventRegistry.register( 90 | CounterSample, 91 | { 92 | name: 'counterSample', 93 | pluralName: 'counterSamples', 94 | singleViewElementName: 'tr-ui-a-counter-sample-sub-view', 95 | multiViewElementName: 'tr-ui-a-counter-sample-sub-view' 96 | }); 97 | 98 | return { 99 | CounterSample: CounterSample 100 | }; 101 | }); 102 | -------------------------------------------------------------------------------- /lib/third_party/tracing/ui/annotations/comment_box_annotation_view.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./annotation_view.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.ui.annotations', function() { 12 | /** 13 | * A view of a comment box consisting of a textarea and a line to the 14 | * actual location. 15 | * @extends {AnnotationView} 16 | * @constructor 17 | */ 18 | function CommentBoxAnnotationView(viewport, annotation) { 19 | this.viewport_ = viewport; 20 | this.annotation_ = annotation; 21 | this.textArea_ = undefined; 22 | 23 | this.styleWidth = 250; 24 | this.styleHeight = 50; 25 | this.fontSize = 10; 26 | this.rightOffset = 50; 27 | this.topOffset = 25; 28 | } 29 | 30 | CommentBoxAnnotationView.prototype = { 31 | __proto__: tr.ui.annotations.AnnotationView.prototype, 32 | 33 | removeTextArea: function() { 34 | this.textArea_.parentNode.removeChild(this.textArea_); 35 | }, 36 | 37 | draw: function(ctx) { 38 | var coords = this.annotation_.location.toViewCoordinates(this.viewport_); 39 | if (coords.viewX < 0) { 40 | if (this.textArea_) 41 | this.textArea_.style.visibility = 'hidden'; 42 | return; 43 | } 44 | 45 | // Set up textarea element. 46 | if (!this.textArea_) { 47 | this.textArea_ = document.createElement('textarea'); 48 | this.textArea_.style.position = 'absolute'; 49 | this.textArea_.readOnly = true; 50 | this.textArea_.value = this.annotation_.text; 51 | // Set the z-index so that this is shown on top of canvas. 52 | this.textArea_.style.zIndex = 1; 53 | ctx.canvas.parentNode.appendChild(this.textArea_); 54 | } 55 | 56 | this.textArea_.style.width = this.styleWidth + 'px'; 57 | this.textArea_.style.height = this.styleHeight + 'px'; 58 | this.textArea_.style.fontSize = this.fontSize + 'px'; 59 | this.textArea_.style.visibility = 'visible'; 60 | 61 | // Update positions to latest coordinate. 62 | this.textArea_.style.left = 63 | coords.viewX + ctx.canvas.getBoundingClientRect().left + 64 | this.rightOffset + 'px'; 65 | this.textArea_.style.top = 66 | coords.viewY - ctx.canvas.getBoundingClientRect().top - 67 | this.topOffset + 'px'; 68 | 69 | // Draw pointer line from offset to actual location. 70 | ctx.strokeStyle = 'rgb(0, 0, 0)'; 71 | ctx.lineWidth = 2; 72 | ctx.beginPath(); 73 | tr.ui.b.drawLine(ctx, coords.viewX, 74 | coords.viewY - ctx.canvas.getBoundingClientRect().top, 75 | coords.viewX + this.rightOffset, 76 | coords.viewY - this.topOffset - 77 | ctx.canvas.getBoundingClientRect().top); 78 | ctx.stroke(); 79 | } 80 | }; 81 | 82 | return { 83 | CommentBoxAnnotationView: CommentBoxAnnotationView 84 | }; 85 | }); 86 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/stack_frame.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/base.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.model', function() { 12 | function StackFrame(parentFrame, id, title, colorId, opt_sourceInfo) { 13 | if (id === undefined) 14 | throw new Error('id must be given'); 15 | this.parentFrame_ = parentFrame; 16 | this.id = id; 17 | this.title_ = title; 18 | this.colorId = colorId; 19 | this.children = []; 20 | this.sourceInfo_ = opt_sourceInfo; 21 | 22 | if (this.parentFrame_) 23 | this.parentFrame_.addChild(this); 24 | } 25 | 26 | StackFrame.prototype = { 27 | get parentFrame() { 28 | return this.parentFrame_; 29 | }, 30 | 31 | get title() { 32 | if (this.sourceInfo_) { 33 | var src = this.sourceInfo_.toString(); 34 | return this.title_ + (src === '' ? '' : ' ' + src); 35 | } 36 | return this.title_; 37 | }, 38 | 39 | /** 40 | * Attempts to find the domain of the origin of the script either from this 41 | * stack trace or from its ancestors. 42 | */ 43 | get domain() { 44 | var result = 'unknown'; 45 | if (this.sourceInfo_ && this.sourceInfo_.domain) 46 | result = this.sourceInfo_.domain; 47 | if (result === 'unknown' && this.parentFrame) 48 | result = this.parentFrame.domain; 49 | return result; 50 | }, 51 | 52 | get sourceInfo() { 53 | return this.sourceInfo_; 54 | }, 55 | 56 | set parentFrame(parentFrame) { 57 | if (this.parentFrame_) 58 | this.parentFrame_.removeChild(this); 59 | this.parentFrame_ = parentFrame; 60 | if (this.parentFrame_) 61 | this.parentFrame_.addChild(this); 62 | }, 63 | 64 | addChild: function(child) { 65 | this.children.push(child); 66 | }, 67 | 68 | removeChild: function(child) { 69 | var i = this.children.indexOf(child.id); 70 | if (i == -1) 71 | throw new Error('omg'); 72 | this.children.splice(i, 1); 73 | }, 74 | 75 | removeAllChildren: function() { 76 | for (var i = 0; i < this.children.length; i++) 77 | this.children[i].parentFrame_ = undefined; 78 | this.children.splice(0, this.children.length); 79 | }, 80 | 81 | /** 82 | * Returns stackFrames where the most specific frame is first. 83 | */ 84 | get stackTrace() { 85 | var stack = []; 86 | var cur = this; 87 | while (cur) { 88 | stack.push(cur); 89 | cur = cur.parentFrame; 90 | } 91 | return stack; 92 | }, 93 | 94 | getUserFriendlyStackTrace: function() { 95 | return this.stackTrace.map(function(x) { return x.title; }); 96 | } 97 | }; 98 | 99 | return { 100 | StackFrame: StackFrame 101 | }; 102 | }); 103 | -------------------------------------------------------------------------------- /lib/third_party/tracing/base/math.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./base.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.b', function() { 12 | function clamp(x, lo, hi) { 13 | return Math.min(Math.max(x, lo), hi); 14 | } 15 | 16 | function lerp(percentage, lo, hi) { 17 | var range = hi - lo; 18 | return lo + percentage * range; 19 | } 20 | 21 | function normalize(value, lo, hi) { 22 | return (value - lo) / (hi - lo); 23 | } 24 | 25 | function deg2rad(deg) { 26 | return (Math.PI * deg) / 180.0; 27 | } 28 | 29 | var tmp_vec2 = vec2.create(); 30 | var tmp_vec2b = vec2.create(); 31 | var tmp_vec4 = vec4.create(); 32 | var tmp_mat2d = mat2d.create(); 33 | 34 | vec2.createFromArray = function(arr) { 35 | if (arr.length != 2) 36 | throw new Error('Should be length 2'); 37 | var v = vec2.create(); 38 | vec2.set(v, arr[0], arr[1]); 39 | return v; 40 | }; 41 | 42 | vec2.createXY = function(x, y) { 43 | var v = vec2.create(); 44 | vec2.set(v, x, y); 45 | return v; 46 | }; 47 | 48 | vec2.toString = function(a) { 49 | return '[' + a[0] + ', ' + a[1] + ']'; 50 | }; 51 | 52 | vec2.addTwoScaledUnitVectors = function(out, u1, scale1, u2, scale2) { 53 | // out = u1 * scale1 + u2 * scale2 54 | vec2.scale(tmp_vec2, u1, scale1); 55 | vec2.scale(tmp_vec2b, u2, scale2); 56 | vec2.add(out, tmp_vec2, tmp_vec2b); 57 | }; 58 | 59 | vec2.interpolatePiecewiseFunction = function(points, x) { 60 | if (x < points[0][0]) 61 | return points[0][1]; 62 | for (var i = 1; i < points.length; ++i) { 63 | if (x < points[i][0]) { 64 | var percent = normalize(x, points[i - 1][0], points[i][0]); 65 | return lerp(percent, points[i - 1][1], points[i][1]); 66 | } 67 | } 68 | return points[points.length - 1][1]; 69 | }; 70 | 71 | vec3.createXYZ = function(x, y, z) { 72 | var v = vec3.create(); 73 | vec3.set(v, x, y, z); 74 | return v; 75 | }; 76 | 77 | vec3.toString = function(a) { 78 | return 'vec3(' + a[0] + ', ' + a[1] + ', ' + a[2] + ')'; 79 | } 80 | 81 | mat2d.translateXY = function(out, x, y) { 82 | vec2.set(tmp_vec2, x, y); 83 | mat2d.translate(out, out, tmp_vec2); 84 | } 85 | 86 | mat2d.scaleXY = function(out, x, y) { 87 | vec2.set(tmp_vec2, x, y); 88 | mat2d.scale(out, out, tmp_vec2); 89 | } 90 | 91 | vec4.unitize = function(out, a) { 92 | out[0] = a[0] / a[3]; 93 | out[1] = a[1] / a[3]; 94 | out[2] = a[2] / a[3]; 95 | out[3] = 1; 96 | return out; 97 | } 98 | 99 | vec2.copyFromVec4 = function(out, a) { 100 | vec4.unitize(tmp_vec4, a); 101 | vec2.copy(out, tmp_vec4); 102 | } 103 | 104 | return { 105 | clamp: clamp, 106 | lerp: lerp, 107 | normalize: normalize, 108 | deg2rad: deg2rad 109 | }; 110 | 111 | }); 112 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/object_snapshot.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/extension_registry.js"); 8 | require("../base/units/time_stamp.js"); 9 | require("./event.js"); 10 | 11 | 'use strict'; 12 | 13 | global.tr.exportTo('tr.model', function() { 14 | /** 15 | * A snapshot of an object instance, at a given moment in time. 16 | * 17 | * Initialization of snapshots and instances is three phased: 18 | * 19 | * 1. Instances and snapshots are constructed. This happens during event 20 | * importing. Little should be done here, because the object's data 21 | * are still being used by the importer to reconstruct object references. 22 | * 23 | * 2. Instances and snapshtos are preinitialized. This happens after implicit 24 | * objects have been found, but before any references have been found and 25 | * switched to direct references. Thus, every snapshot stands on its own. 26 | * This is a good time to do global field renaming and type conversion, 27 | * e.g. recognizing domain-specific types and converting from C++ naming 28 | * convention to JS. 29 | * 30 | * 3. Instances and snapshtos are initialized. At this point, {id_ref: 31 | * '0x1000'} fields have been converted to snapshot references. This is a 32 | * good time to generic initialization steps and argument verification. 33 | * 34 | * @constructor 35 | */ 36 | function ObjectSnapshot(objectInstance, ts, args) { 37 | tr.model.Event.call(this); 38 | this.objectInstance = objectInstance; 39 | this.ts = ts; 40 | this.args = args; 41 | } 42 | 43 | ObjectSnapshot.prototype = { 44 | __proto__: tr.model.Event.prototype, 45 | 46 | /** 47 | * See ObjectSnapshot constructor notes on object initialization. 48 | */ 49 | preInitialize: function() { 50 | }, 51 | 52 | /** 53 | * See ObjectSnapshot constructor notes on object initialization. 54 | */ 55 | initialize: function() { 56 | }, 57 | 58 | addBoundsToRange: function(range) { 59 | range.addValue(this.ts); 60 | }, 61 | 62 | get userFriendlyName() { 63 | return 'Snapshot of ' + 64 | this.objectInstance.typeName + ' ' + 65 | this.objectInstance.id + ' @ ' + 66 | tr.b.u.TimeStamp.format(this.ts); 67 | } 68 | }; 69 | 70 | tr.model.EventRegistry.register( 71 | ObjectSnapshot, 72 | { 73 | name: 'objectSnapshot', 74 | pluralName: 'objectSnapshots', 75 | singleViewElementName: 'tr-ui-a-single-object-snapshot-sub-view', 76 | multiViewElementName: 'tr-ui-a-multi-object-sub-view' 77 | }); 78 | 79 | var options = new tr.b.ExtensionRegistryOptions( 80 | tr.b.TYPE_BASED_REGISTRY_MODE); 81 | options.mandatoryBaseClass = ObjectSnapshot; 82 | options.defaultConstructor = ObjectSnapshot; 83 | tr.b.decorateExtensionRegistry(ObjectSnapshot, options); 84 | 85 | return { 86 | ObjectSnapshot: ObjectSnapshot 87 | }; 88 | }); 89 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/event_registry.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/extension_registry.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Provides the EventRegistry class. 13 | */ 14 | global.tr.exportTo('tr.model', function() { 15 | // Create the type registry. 16 | function EventRegistry() { 17 | } 18 | 19 | var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE); 20 | tr.b.decorateExtensionRegistry(EventRegistry, options); 21 | 22 | // Enforce all options objects have the right fields. 23 | EventRegistry.addEventListener('will-register', function(e) { 24 | var metadata = e.typeInfo.metadata; 25 | 26 | if (metadata.name === undefined) 27 | throw new Error('Registered events must provide name metadata'); 28 | var i = tr.b.findFirstInArray( 29 | EventRegistry.getAllRegisteredTypeInfos(), 30 | function(x) { return x.metadata.name === metadata.name; }); 31 | if (i !== undefined) 32 | throw new Error('Event type with that name already registered'); 33 | 34 | if (metadata.pluralName === undefined) 35 | throw new Error('Registered events must provide pluralName metadata'); 36 | if (metadata.singleViewElementName === undefined) { 37 | throw new Error('Registered events must provide ' + 38 | 'singleViewElementName metadata'); 39 | } 40 | if (metadata.multiViewElementName === undefined) { 41 | throw new Error('Registered events must provide ' + 42 | 'multiViewElementName metadata'); 43 | } 44 | }); 45 | 46 | // Helper: lookup Events indexed by type name. 47 | var eventsByTypeName = undefined; 48 | EventRegistry.getEventTypeInfoByTypeName = function(typeName) { 49 | if (eventsByTypeName === undefined) { 50 | eventsByTypeName = {}; 51 | EventRegistry.getAllRegisteredTypeInfos().forEach(function(typeInfo) { 52 | eventsByTypeName[typeInfo.metadata.name] = typeInfo; 53 | }); 54 | } 55 | return eventsByTypeName[typeName]; 56 | } 57 | 58 | // Ensure eventsByTypeName stays current. 59 | EventRegistry.addEventListener('registry-changed', function() { 60 | eventsByTypeName = undefined; 61 | }); 62 | 63 | function convertCamelCaseToTitleCase(name) { 64 | var result = name.replace(/[A-Z]/g, ' $&'); 65 | result = result.charAt(0).toUpperCase() + result.slice(1); 66 | return result; 67 | } 68 | 69 | EventRegistry.getUserFriendlySingularName = function(typeName) { 70 | var typeInfo = EventRegistry.getEventTypeInfoByTypeName(typeName); 71 | var str = typeInfo.metadata.name; 72 | return convertCamelCaseToTitleCase(str); 73 | }; 74 | 75 | EventRegistry.getUserFriendlyPluralName = function(typeName) { 76 | var typeInfo = EventRegistry.getEventTypeInfoByTypeName(typeName); 77 | var str = typeInfo.metadata.pluralName; 78 | return convertCamelCaseToTitleCase(str); 79 | }; 80 | 81 | return { 82 | EventRegistry: EventRegistry 83 | }; 84 | }); 85 | -------------------------------------------------------------------------------- /lib/third_party/tracing/base/event.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./event_target.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.b', function() { 12 | var Event; 13 | if (tr.isHeadless) { 14 | /** 15 | * Creates a new event to be used with tr.b.EventTarget or DOM EventTarget 16 | * objects. 17 | * @param {string} type The name of the event. 18 | * @param {boolean=} opt_bubbles Whether the event bubbles. 19 | * Default is false. 20 | * @param {boolean=} opt_preventable Whether the default action of the event 21 | * can be prevented. 22 | * @constructor 23 | * @extends {Event} 24 | */ 25 | function HeadlessEvent(type, opt_bubbles, opt_preventable) { 26 | this.type = type; 27 | this.bubbles = (opt_bubbles !== undefined ? 28 | !!opt_bubbles : false); 29 | this.cancelable = (opt_preventable !== undefined ? 30 | !!opt_preventable : false); 31 | 32 | this.defaultPrevented = false; 33 | this.cancelBubble = false; 34 | }; 35 | 36 | HeadlessEvent.prototype = { 37 | preventDefault: function() { 38 | this.defaultPrevented = true; 39 | }, 40 | 41 | stopPropagation: function() { 42 | this.cancelBubble = true; 43 | } 44 | }; 45 | Event = HeadlessEvent; 46 | } else { 47 | /** 48 | * Creates a new event to be used with tr.b.EventTarget or DOM EventTarget 49 | * objects. 50 | * @param {string} type The name of the event. 51 | * @param {boolean=} opt_bubbles Whether the event bubbles. 52 | * Default is false. 53 | * @param {boolean=} opt_preventable Whether the default action of the event 54 | * can be prevented. 55 | * @constructor 56 | * @extends {Event} 57 | */ 58 | function TrEvent(type, opt_bubbles, opt_preventable) { 59 | var e = tr.doc.createEvent('Event'); 60 | e.initEvent(type, !!opt_bubbles, !!opt_preventable); 61 | e.__proto__ = global.Event.prototype; 62 | return e; 63 | }; 64 | 65 | TrEvent.prototype = { 66 | __proto__: global.Event.prototype 67 | }; 68 | Event = TrEvent; 69 | } 70 | 71 | /** 72 | * Dispatches a simple event on an event target. 73 | * @param {!EventTarget} target The event target to dispatch the event on. 74 | * @param {string} type The type of the event. 75 | * @param {boolean=} opt_bubbles Whether the event bubbles or not. 76 | * @param {boolean=} opt_cancelable Whether the default action of the event 77 | * can be prevented. 78 | * @return {boolean} If any of the listeners called {@code preventDefault} 79 | * during the dispatch this will return false. 80 | */ 81 | function dispatchSimpleEvent(target, type, opt_bubbles, opt_cancelable) { 82 | var e = new tr.b.Event(type, opt_bubbles, opt_cancelable); 83 | return target.dispatchEvent(e); 84 | } 85 | 86 | return { 87 | Event: Event, 88 | dispatchSimpleEvent: dispatchSimpleEvent 89 | }; 90 | }); 91 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/ir_coverage.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/iteration_helpers.js"); 8 | require("./event_set.js"); 9 | 10 | 'use strict'; 11 | 12 | global.tr.exportTo('tr.model', function() { 13 | function getAssociatedEvents(irs) { 14 | var allAssociatedEvents = new tr.model.EventSet(); 15 | irs.forEach(function(ir) { 16 | ir.associatedEvents.forEach(function(event) { 17 | // FlowEvents don't have parentContainers or cpuDurations, and it's 18 | // annoying to highlight them. 19 | if (event instanceof tr.model.FlowEvent) 20 | return; 21 | allAssociatedEvents.push(event); 22 | }); 23 | }); 24 | return allAssociatedEvents; 25 | } 26 | 27 | function getUnassociatedEvents(model, associatedEvents) { 28 | var unassociatedEvents = new tr.model.EventSet(); 29 | model.getAllProcesses().forEach(function(process) { 30 | for (var tid in process.threads) { 31 | var thread = process.threads[tid]; 32 | thread.sliceGroup.iterateAllEvents(function(event) { 33 | // The set of unassociated events contains only events that are not in 34 | // the set of associated events. 35 | // Only add event to the set of unassociated events if it is not in 36 | // the set of associated events. 37 | if (!associatedEvents.contains(event)) 38 | unassociatedEvents.push(event); 39 | }); 40 | } 41 | }); 42 | return unassociatedEvents; 43 | } 44 | 45 | function getTotalCpuDuration(events) { 46 | var cpuMs = 0; 47 | events.forEach(function(event) { 48 | // Add up events' cpu self time if they have any. 49 | if (event.cpuSelfTime) 50 | cpuMs += event.cpuSelfTime; 51 | }); 52 | return cpuMs; 53 | } 54 | 55 | function getIRCoverageFromModel(model) { 56 | var associatedEvents = getAssociatedEvents(model.interactionRecords); 57 | 58 | if (!associatedEvents.length) 59 | return undefined; 60 | 61 | var unassociatedEvents = getUnassociatedEvents( 62 | model, associatedEvents); 63 | 64 | var associatedCpuMs = getTotalCpuDuration(associatedEvents); 65 | var unassociatedCpuMs = getTotalCpuDuration(unassociatedEvents); 66 | 67 | var totalEventCount = associatedEvents.length + unassociatedEvents.length; 68 | var totalCpuMs = associatedCpuMs + unassociatedCpuMs; 69 | 70 | return { 71 | associatedEventsCount: associatedEvents.length, 72 | unassociatedEventsCount: unassociatedEvents.length, 73 | associatedEventsCpuTimeMs: associatedCpuMs, 74 | unassociatedEventsCpuTimeMs: unassociatedCpuMs, 75 | coveredEventsCountRatio: associatedEvents.length / totalEventCount, 76 | coveredEventsCpuTimeRatio: associatedCpuMs / totalCpuMs 77 | }; 78 | } 79 | 80 | return { 81 | getIRCoverageFromModel: getIRCoverageFromModel, 82 | getAssociatedEvents: getAssociatedEvents, 83 | getUnassociatedEvents: getUnassociatedEvents 84 | }; 85 | }); 86 | -------------------------------------------------------------------------------- /lib/third_party/tracing/base/extension_registry_base.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./base.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.b', function() { 12 | function RegisteredTypeInfo(constructor, metadata) { 13 | this.constructor = constructor; 14 | this.metadata = metadata; 15 | }; 16 | 17 | var BASIC_REGISTRY_MODE = 'BASIC_REGISTRY_MODE'; 18 | var TYPE_BASED_REGISTRY_MODE = 'TYPE_BASED_REGISTRY_MODE'; 19 | var ALL_MODES = {BASIC_REGISTRY_MODE: true, TYPE_BASED_REGISTRY_MODE: true}; 20 | 21 | function ExtensionRegistryOptions(mode) { 22 | if (mode === undefined) 23 | throw new Error('Mode is required'); 24 | if (!ALL_MODES[mode]) 25 | throw new Error('Not a mode.'); 26 | 27 | this.mode_ = mode; 28 | this.defaultMetadata_ = {}; 29 | this.defaultConstructor_ = undefined; 30 | this.mandatoryBaseClass_ = undefined; 31 | this.defaultTypeInfo_ = undefined; 32 | this.frozen_ = false; 33 | } 34 | ExtensionRegistryOptions.prototype = { 35 | freeze: function() { 36 | if (this.frozen_) 37 | throw new Error('Frozen'); 38 | this.frozen_ = true; 39 | }, 40 | 41 | get mode() { 42 | return this.mode_; 43 | }, 44 | 45 | get defaultMetadata() { 46 | return this.defaultMetadata_; 47 | }, 48 | 49 | set defaultMetadata(defaultMetadata) { 50 | if (this.frozen_) 51 | throw new Error('Frozen'); 52 | this.defaultMetadata_ = defaultMetadata; 53 | this.defaultTypeInfo_ = undefined; 54 | }, 55 | 56 | get defaultConstructor() { 57 | return this.defaultConstructor_; 58 | }, 59 | 60 | set defaultConstructor(defaultConstructor) { 61 | if (this.frozen_) 62 | throw new Error('Frozen'); 63 | this.defaultConstructor_ = defaultConstructor; 64 | this.defaultTypeInfo_ = undefined; 65 | }, 66 | 67 | get defaultTypeInfo() { 68 | if (this.defaultTypeInfo_ === undefined && this.defaultConstructor_) { 69 | this.defaultTypeInfo_ = new RegisteredTypeInfo( 70 | this.defaultConstructor, 71 | this.defaultMetadata); 72 | } 73 | return this.defaultTypeInfo_; 74 | }, 75 | 76 | validateConstructor: function(constructor) { 77 | if (!this.mandatoryBaseClass) 78 | return; 79 | var curProto = constructor.prototype.__proto__; 80 | var ok = false; 81 | while (curProto) { 82 | if (curProto === this.mandatoryBaseClass.prototype) { 83 | ok = true; 84 | break; 85 | } 86 | curProto = curProto.__proto__; 87 | } 88 | if (!ok) 89 | throw new Error(constructor + 'must be subclass of ' + registry); 90 | } 91 | }; 92 | 93 | return { 94 | BASIC_REGISTRY_MODE: BASIC_REGISTRY_MODE, 95 | TYPE_BASED_REGISTRY_MODE: TYPE_BASED_REGISTRY_MODE, 96 | 97 | ExtensionRegistryOptions: ExtensionRegistryOptions, 98 | RegisteredTypeInfo: RegisteredTypeInfo 99 | }; 100 | }); 101 | 102 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/rail/animation_interaction_record.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../base/statistics.js"); 8 | require("../chrome/chrome_process_helper.js"); 9 | require("./rail_interaction_record.js"); 10 | 11 | 'use strict'; 12 | 13 | /** 14 | * @fileoverview The Animation phase of RAIL. 15 | */ 16 | global.tr.exportTo('tr.e.rail', function() { 17 | // The FPS comfort score is maximized at this value of average 18 | // frames-per-second. 19 | var MAX_COMFORT_FPS = 60; 20 | 21 | // The FPS comfort score is minimized at this value of average 22 | // frames-per-second. 23 | var MIN_COMFORT_FPS = 10; 24 | 25 | // The jank comfort score is maximized when frame timestamp discrepancy is 26 | // less than or equal to this: 27 | var MIN_DISCOMFORT_JANK = 0.05; 28 | 29 | // The jank comfort score is minimized when frame timestamp discrepancy is 30 | // greater than or equal to this: 31 | var MAX_DISCOMFORT_JANK = 0.3; 32 | 33 | function AnimationInteractionRecord(parentModel, start, duration) { 34 | tr.e.rail.RAILInteractionRecord.call( 35 | this, parentModel, 'Animation', 'rail_animate', 36 | start, duration); 37 | this.frameEvents_ = undefined; 38 | } 39 | 40 | AnimationInteractionRecord.prototype = { 41 | __proto__: tr.e.rail.RAILInteractionRecord.prototype, 42 | 43 | get frameEvents() { 44 | if (this.frameEvents_) 45 | return this.frameEvents_; 46 | 47 | this.frameEvents_ = new tr.model.EventSet(); 48 | 49 | this.associatedEvents.forEach(function(event) { 50 | if (event.title === tr.e.audits.IMPL_RENDERING_STATS) 51 | this.frameEvents_.push(event); 52 | }, this); 53 | 54 | return this.frameEvents_; 55 | }, 56 | 57 | get normalizedUserComfort() { 58 | // Combine jank comfort and fps comfort non-linearly. 59 | // weightedAverage2 weights lower scores exponentially more heavily than 60 | // higher scores. 61 | // http://goo.gl/W6MswA 62 | return tr.e.rail.weightedAverage2( 63 | this.normalizedJankComfort, this.normalizedFPSComfort); 64 | }, 65 | 66 | get normalizedFPSComfort() { 67 | var durationSeconds = this.duration / 1000; 68 | var avgSpf = durationSeconds / this.frameEvents.length; 69 | var normalizedDiscomfort = tr.b.normalize( 70 | avgSpf, 1 / MAX_COMFORT_FPS, 1 / MIN_COMFORT_FPS); 71 | var normalizedComfort = 1 - normalizedDiscomfort; 72 | return tr.b.clamp(normalizedComfort, 0, 1); 73 | }, 74 | 75 | get normalizedJankComfort() { 76 | var frameTimestamps = this.frameEvents.toArray().map(function(event) { 77 | return event.start; 78 | }); 79 | var absolute = false; 80 | var discrepancy = tr.b.Statistics.timestampsDiscrepancy( 81 | frameTimestamps, absolute); 82 | var normalizedDiscomfort = tr.b.normalize( 83 | discrepancy, MIN_DISCOMFORT_JANK, MAX_DISCOMFORT_JANK); 84 | var normalizedComfort = 1 - normalizedDiscomfort; 85 | return tr.b.clamp(normalizedComfort, 0, 1); 86 | } 87 | }; 88 | 89 | return { 90 | AnimationInteractionRecord: AnimationInteractionRecord 91 | }; 92 | }); 93 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/linux_perf/parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../../base/base.js"); 8 | require("../../../base/extension_registry.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview Base class for linux perf event parsers. 14 | * 15 | * The linux perf trace event importer depends on subclasses of 16 | * Parser to parse event data. Each subclass corresponds 17 | * to a group of trace events; e.g. SchedParser implements 18 | * parsing of sched:* kernel trace events. Parser subclasses must 19 | * call Parser.register to arrange to be instantiated 20 | * and their constructor must register their event handlers with the 21 | * importer. For example, 22 | * 23 | * var Parser = tr.e.importer.linux_perf.Parser; 24 | * 25 | * function WorkqueueParser(importer) { 26 | * Parser.call(this, importer); 27 | * 28 | * importer.registerEventHandler('workqueue_execute_start', 29 | * WorkqueueParser.prototype.executeStartEvent.bind(this)); 30 | * importer.registerEventHandler('workqueue_execute_end', 31 | * WorkqueueParser.prototype.executeEndEvent.bind(this)); 32 | * } 33 | * 34 | * Parser.register(WorkqueueParser); 35 | * 36 | * When a registered event name is found in the data stream the associated 37 | * event handler is invoked: 38 | * 39 | * executeStartEvent: function(eventName, cpuNumber, ts, eventBase) 40 | * 41 | * If the routine returns false the caller will generate an import error 42 | * saying there was a problem parsing it. Handlers can also emit import 43 | * messages using this.importer.model.importWarning. If this is done in lieu of 44 | * the generic import error it may be desirable for the handler to return 45 | * true. 46 | * 47 | * Trace events generated by writing to the trace_marker file are expected 48 | * to have a leading text marker followed by a ':'; e.g. the trace clock 49 | * synchronization event is: 50 | * 51 | * tracing_mark_write: trace_event_clock_sync: parent_ts=0 52 | * 53 | * To register an event handler for these events, prepend the marker with 54 | * 'tracing_mark_write:'; e.g. 55 | * 56 | * this.registerEventHandler('tracing_mark_write:trace_event_clock_sync', 57 | * 58 | * All subclasses should depend on importer.linux_perf.parser, e.g. 59 | * 60 | * tr.defineModule('importer.linux_perf.workqueue_parser') 61 | * .dependsOn('importer.linux_perf.parser') 62 | * .exportsTo('tracing', function() 63 | * 64 | * and be listed in the dependsOn of LinuxPerfImporter. Beware that after 65 | * adding a new subclass you must run build/generate_about_tracing_contents.py 66 | * to regenerate tr.ui.e.about_tracing.*. 67 | */ 68 | global.tr.exportTo('tr.e.importer.linux_perf', function() { 69 | /** 70 | * Parses linux perf events. 71 | * @constructor 72 | */ 73 | function Parser(importer) { 74 | this.importer = importer; 75 | this.model = importer.model; 76 | } 77 | 78 | Parser.prototype = { 79 | __proto__: Object.prototype 80 | }; 81 | 82 | var options = new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE); 83 | options.mandatoryBaseClass = Parser; 84 | tr.b.decorateExtensionRegistry(Parser, options); 85 | 86 | return { 87 | Parser: Parser 88 | }; 89 | }); 90 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/power_series.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/range.js"); 8 | require("./event_container.js"); 9 | require("./power_sample.js"); 10 | 11 | 'use strict'; 12 | 13 | global.tr.exportTo('tr.model', function() { 14 | 15 | var PowerSample = tr.model.PowerSample; 16 | 17 | /** 18 | * A container holding a time series of power samples. 19 | * 20 | * @constructor 21 | * @extends {EventContainer} 22 | */ 23 | function PowerSeries(device) { 24 | tr.model.EventContainer.call(this); 25 | 26 | this.device_ = device; 27 | this.samples_ = []; 28 | } 29 | 30 | PowerSeries.prototype = { 31 | __proto__: tr.model.EventContainer.prototype, 32 | 33 | get device() { 34 | return this.device_; 35 | }, 36 | 37 | get samples() { 38 | return this.samples_; 39 | }, 40 | 41 | get stableId() { 42 | return this.device_.stableId + '.PowerSeries'; 43 | }, 44 | 45 | /** 46 | * Adds a power sample to the series and returns it. 47 | * 48 | * Note: Samples must be added in chronological order. 49 | */ 50 | addPowerSample: function(ts, val) { 51 | var sample = new PowerSample(this, ts, val); 52 | this.samples_.push(sample); 53 | return sample; 54 | }, 55 | 56 | /** 57 | * Returns the total energy (in Joules) consumed between the specified 58 | * start and end timestamps (in milliseconds). 59 | */ 60 | getEnergyConsumed: function(start, end) { 61 | var measurementRange = tr.b.Range.fromExplicitRange(start, end); 62 | 63 | var energyConsumed = 0; 64 | for (var i = 0; i < this.samples.length; i++) { 65 | var sample = this.samples[i]; 66 | var nextSample = this.samples[i + 1]; 67 | 68 | var sampleRange = new tr.b.Range(); 69 | sampleRange.addValue(sample.start); 70 | sampleRange.addValue(nextSample ? nextSample.start : Infinity); 71 | 72 | var timeIntersection = measurementRange.findIntersection(sampleRange); 73 | 74 | // Divide by 1000 to convert milliseconds to seconds. 75 | energyConsumed += timeIntersection.duration / 1000 * sample.power; 76 | } 77 | 78 | return energyConsumed; 79 | }, 80 | 81 | shiftTimestampsForward: function(amount) { 82 | for (var i = 0; i < this.samples_.length; ++i) 83 | this.samples_[i].start += amount; 84 | }, 85 | 86 | updateBounds: function() { 87 | this.bounds.reset(); 88 | 89 | if (this.samples_.length === 0) 90 | return; 91 | 92 | this.bounds.addValue(this.samples_[0].start); 93 | this.bounds.addValue(this.samples_[this.samples_.length - 1].start); 94 | }, 95 | 96 | iterateAllEventsInThisContainer: function(eventTypePredicate, callback, 97 | opt_this) { 98 | if (eventTypePredicate.call(opt_this, PowerSample)) 99 | this.samples_.forEach(callback, opt_this); 100 | }, 101 | 102 | iterateAllChildEventContainers: function(callback, opt_this) { 103 | } 104 | }; 105 | 106 | return { 107 | PowerSeries: PowerSeries 108 | }; 109 | }); 110 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/linux_perf/kfunc_parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./parser.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Parses graph_ent and graph_ret events that were inserted by 13 | * the Linux kernel's function graph trace. 14 | */ 15 | global.tr.exportTo('tr.e.importer.linux_perf', function() { 16 | 17 | var LinuxPerfParser = tr.e.importer.linux_perf.Parser; 18 | 19 | /** 20 | * Parses graph_ent and graph_ret events that were inserted by the Linux 21 | * kernel's function graph trace. 22 | * @constructor 23 | */ 24 | function KernelFuncParser(importer) { 25 | LinuxPerfParser.call(this, importer); 26 | 27 | importer.registerEventHandler('graph_ent', 28 | KernelFuncParser.prototype.traceKernelFuncEnterEvent. 29 | bind(this)); 30 | importer.registerEventHandler('graph_ret', 31 | KernelFuncParser.prototype.traceKernelFuncReturnEvent. 32 | bind(this)); 33 | 34 | this.model_ = importer.model_; 35 | this.ppids_ = {}; 36 | } 37 | 38 | var TestExports = {}; 39 | 40 | var funcEnterRE = new RegExp('func=(.+)'); 41 | TestExports.funcEnterRE = funcEnterRE; 42 | 43 | KernelFuncParser.prototype = { 44 | __proto__: LinuxPerfParser.prototype, 45 | 46 | traceKernelFuncEnterEvent: function(eventName, cpuNumber, pid, ts, 47 | eventBase) { 48 | var eventData = funcEnterRE.exec(eventBase.details); 49 | if (!eventData) 50 | return false; 51 | 52 | if (eventBase.tgid === undefined) { 53 | return false; 54 | } 55 | 56 | var tgid = parseInt(eventBase.tgid); 57 | var name = eventData[1]; 58 | var thread = this.model_.getOrCreateProcess(tgid) 59 | .getOrCreateThread(pid); 60 | thread.name = eventBase.threadName; 61 | 62 | var slices = thread.kernelSliceGroup; 63 | if (!slices.isTimestampValidForBeginOrEnd(ts)) { 64 | this.model_.importWarning({ 65 | type: 'parse_error', 66 | message: 'Timestamps are moving backward.' 67 | }); 68 | return false; 69 | } 70 | 71 | var slice = slices.beginSlice(null, name, ts, {}); 72 | 73 | return true; 74 | }, 75 | 76 | traceKernelFuncReturnEvent: function(eventName, cpuNumber, pid, ts, 77 | eventBase) { 78 | if (eventBase.tgid === undefined) { 79 | return false; 80 | } 81 | 82 | var tgid = parseInt(eventBase.tgid); 83 | var thread = this.model_.getOrCreateProcess(tgid) 84 | .getOrCreateThread(pid); 85 | thread.name = eventBase.threadName; 86 | 87 | var slices = thread.kernelSliceGroup; 88 | if (!slices.isTimestampValidForBeginOrEnd(ts)) { 89 | this.model_.importWarning({ 90 | type: 'parse_error', 91 | message: 'Timestamps are moving backward.' 92 | }); 93 | return false; 94 | } 95 | 96 | if (slices.openSliceCount > 0) { 97 | slices.endSlice(ts); 98 | } 99 | 100 | return true; 101 | } 102 | }; 103 | 104 | LinuxPerfParser.register(KernelFuncParser); 105 | 106 | return { 107 | KernelFuncParser: KernelFuncParser 108 | }; 109 | }); 110 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/rail/rail_score.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../base/statistics.js"); 8 | require("./rail_interaction_record.js"); 9 | 10 | 'use strict'; 11 | 12 | global.tr.exportTo('tr.e.rail', function() { 13 | function RAILScore(opt_irs, opt_rangeOfInterest) { 14 | this.interactionRecords_ = []; 15 | if (opt_irs) 16 | this.interactionRecords_.push.apply(this.interactionRecords_, opt_irs); 17 | this.rangeOfInterest_ = opt_rangeOfInterest; 18 | if (!this.rangeOfInterest_ || this.rangeOfInterest_.isEmpty) 19 | this.rangeOfInterest_ = tr.b.Range.fromExplicitRange( 20 | -Number.MAX_VALUE, Number.MAX_VALUE); 21 | }; 22 | 23 | RAILScore.prototype = { 24 | get interactionRecords() { 25 | return this.interactionRecords_; 26 | }, 27 | 28 | get overallScore() { 29 | // The design of this algorithm is discussed here: https://goo.gl/Cc0H1z 30 | // TODO(benjhayden): Make doc public and remove below comment? 31 | // Until the doc is made public, this is basically a weighted average, 32 | // where the weights are tunable. The weights are recommended to be higher 33 | // for lower scores, so that lower scores will bring down the overallScore 34 | // more than higher scores bring it up. The optional fields provide an 35 | // opportunity to customize the tunable parameters based on IR type, 36 | // duration, etc. The continuity and monotonicity of the weighting 37 | // function are also important characteristics. The weighting function is 38 | // not composed of meaningful sub-expressions; it is a monolithic 39 | // combination of the score and tunable parameters, and is open to 40 | // reformulation. 41 | // The weighting function is graphed here: https://goo.gl/1blsXW 42 | 43 | function getScore(ir) { 44 | return ir.railScore; 45 | } 46 | 47 | function getWeight(ir) { 48 | // If this IR is not in the range of interest, then remove it from the 49 | // weightedMean calculation by setting its weight to zero. 50 | if (!this.rangeOfInterest_.intersectsExplicitRangeExclusive( 51 | ir.start, ir.end)) 52 | return 0; 53 | 54 | var score = getScore(ir); 55 | 56 | var scale = ir.railScoreScale; 57 | if (scale === undefined) 58 | scale = 3; 59 | 60 | var power = ir.railScorePower; 61 | if (power === undefined) 62 | power = 0.3; 63 | 64 | var base = ir.railScoreBase; 65 | if (base === undefined) 66 | base = Math.exp(1); 67 | 68 | return Math.pow(base, -scale * Math.pow(score, power)); 69 | } 70 | 71 | return tr.b.Statistics.weightedMean( 72 | this.interactionRecords, getWeight, getScore, this); 73 | }, 74 | 75 | asDict: function() { 76 | return { 77 | overallScore: this.overallScore 78 | }; 79 | } 80 | }; 81 | 82 | RAILScore.fromModel = function(model, opt_rangeOfInterest) { 83 | var rirs = model.interactionRecords.filter(function(ir) { 84 | return ir instanceof tr.e.rail.RAILInteractionRecord; 85 | }); 86 | 87 | if (rirs.length === 0) 88 | return undefined; 89 | 90 | return new RAILScore(rirs, opt_rangeOfInterest); 91 | }; 92 | 93 | return { 94 | RAILScore: RAILScore 95 | }; 96 | }); 97 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/linux_perf/workqueue_parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./parser.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Parses workqueue events in the Linux event trace format. 13 | */ 14 | global.tr.exportTo('tr.e.importer.linux_perf', function() { 15 | 16 | var ColorScheme = tr.b.ColorScheme; 17 | var Parser = tr.e.importer.linux_perf.Parser; 18 | 19 | /** 20 | * Parses linux workqueue trace events. 21 | * @constructor 22 | */ 23 | function WorkqueueParser(importer) { 24 | Parser.call(this, importer); 25 | 26 | importer.registerEventHandler('workqueue_execute_start', 27 | WorkqueueParser.prototype.executeStartEvent.bind(this)); 28 | importer.registerEventHandler('workqueue_execute_end', 29 | WorkqueueParser.prototype.executeEndEvent.bind(this)); 30 | importer.registerEventHandler('workqueue_queue_work', 31 | WorkqueueParser.prototype.executeQueueWork.bind(this)); 32 | importer.registerEventHandler('workqueue_activate_work', 33 | WorkqueueParser.prototype.executeActivateWork.bind(this)); 34 | } 35 | 36 | // Matches the workqueue_execute_start record 37 | // workqueue_execute_start: work struct c7a8a89c: function MISRWrapper 38 | var workqueueExecuteStartRE = /work struct (.+): function (\S+)/; 39 | 40 | // Matches the workqueue_execute_start record 41 | // workqueue_execute_end: work struct c7a8a89c 42 | var workqueueExecuteEndRE = /work struct (.+)/; 43 | 44 | WorkqueueParser.prototype = { 45 | __proto__: Parser.prototype, 46 | 47 | /** 48 | * Parses workqueue events and sets up state in the importer. 49 | */ 50 | executeStartEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 51 | var event = workqueueExecuteStartRE.exec(eventBase.details); 52 | if (!event) 53 | return false; 54 | 55 | var kthread = this.importer.getOrCreateKernelThread(eventBase.threadName, 56 | pid, pid); 57 | kthread.openSliceTS = ts; 58 | kthread.openSlice = event[2]; 59 | return true; 60 | }, 61 | 62 | executeEndEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 63 | var event = workqueueExecuteEndRE.exec(eventBase.details); 64 | if (!event) 65 | return false; 66 | 67 | var kthread = this.importer.getOrCreateKernelThread(eventBase.threadName, 68 | pid, pid); 69 | if (kthread.openSlice) { 70 | var slice = new tr.model.Slice('', kthread.openSlice, 71 | ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice), 72 | kthread.openSliceTS, 73 | {}, 74 | ts - kthread.openSliceTS); 75 | 76 | kthread.thread.sliceGroup.pushSlice(slice); 77 | } 78 | kthread.openSlice = undefined; 79 | return true; 80 | }, 81 | 82 | executeQueueWork: function(eventName, cpuNumber, pid, ts, eventBase) { 83 | // TODO: Do something with this event? 84 | return true; 85 | }, 86 | 87 | executeActivateWork: function(eventName, cpuNumber, pid, ts, eventBase) { 88 | // TODO: Do something with this event? 89 | return true; 90 | } 91 | 92 | }; 93 | 94 | Parser.register(WorkqueueParser); 95 | 96 | return { 97 | WorkqueueParser: WorkqueueParser 98 | }; 99 | }); 100 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/counter_series.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./counter_sample.js"); 8 | require("./event_container.js"); 9 | 10 | 'use strict'; 11 | 12 | global.tr.exportTo('tr.model', function() { 13 | var CounterSample = tr.model.CounterSample; 14 | 15 | /** 16 | * A container holding all samples of a given measurement over time. 17 | * 18 | * As an example, a counter series might measure the throughput of data sent 19 | * over a USB connection, with each sample representing the instantaneous 20 | * throughput of the connection. 21 | * 22 | * @constructor 23 | * @extends {EventContainer} 24 | */ 25 | function CounterSeries(name, color) { 26 | tr.model.EventContainer.call(this); 27 | 28 | this.name_ = name; 29 | this.color_ = color; 30 | 31 | this.timestamps_ = []; 32 | this.samples_ = []; 33 | 34 | // Set by counter.addSeries 35 | this.counter = undefined; 36 | this.seriesIndex = undefined; 37 | } 38 | 39 | CounterSeries.prototype = { 40 | __proto__: tr.model.EventContainer.prototype, 41 | 42 | get length() { 43 | return this.timestamps_.length; 44 | }, 45 | 46 | get name() { 47 | return this.name_; 48 | }, 49 | 50 | get color() { 51 | return this.color_; 52 | }, 53 | 54 | get samples() { 55 | return this.samples_; 56 | }, 57 | 58 | get timestamps() { 59 | return this.timestamps_; 60 | }, 61 | 62 | getSample: function(idx) { 63 | return this.samples_[idx]; 64 | }, 65 | 66 | getTimestamp: function(idx) { 67 | return this.timestamps_[idx]; 68 | }, 69 | 70 | addCounterSample: function(ts, val) { 71 | var sample = new CounterSample(this, ts, val); 72 | this.addSample(sample); 73 | return sample; 74 | }, 75 | 76 | addSample: function(sample) { 77 | this.timestamps_.push(sample.timestamp); 78 | this.samples_.push(sample); 79 | }, 80 | 81 | getStatistics: function(sampleIndices) { 82 | var sum = 0; 83 | var min = Number.MAX_VALUE; 84 | var max = -Number.MAX_VALUE; 85 | 86 | for (var i = 0; i < sampleIndices.length; ++i) { 87 | var sample = this.getSample(sampleIndices[i]).value; 88 | 89 | sum += sample; 90 | min = Math.min(sample, min); 91 | max = Math.max(sample, max); 92 | } 93 | 94 | return { 95 | min: min, 96 | max: max, 97 | avg: (sum / sampleIndices.length), 98 | start: this.getSample(sampleIndices[0]).value, 99 | end: this.getSample(sampleIndices.length - 1).value 100 | }; 101 | }, 102 | 103 | shiftTimestampsForward: function(amount) { 104 | for (var i = 0; i < this.timestamps_.length; ++i) { 105 | this.timestamps_[i] += amount; 106 | this.samples_[i].timestamp = this.timestamps_[i]; 107 | } 108 | }, 109 | 110 | iterateAllEventsInThisContainer: function(eventTypePredicate, 111 | callback, opt_this) { 112 | if (eventTypePredicate.call(opt_this, tr.model.CounterSample)) { 113 | this.samples_.forEach(callback, opt_this); 114 | } 115 | }, 116 | 117 | iterateAllChildEventContainers: function(callback, opt_this) { 118 | } 119 | }; 120 | 121 | return { 122 | CounterSeries: CounterSeries 123 | }; 124 | }); 125 | -------------------------------------------------------------------------------- /lib/third_party/tracing/base/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./base.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.b', function() { 12 | /** 13 | * Adds a {@code getInstance} static method that always return the same 14 | * instance object. 15 | * @param {!Function} ctor The constructor for the class to add the static 16 | * method to. 17 | */ 18 | function addSingletonGetter(ctor) { 19 | ctor.getInstance = function() { 20 | return ctor.instance_ || (ctor.instance_ = new ctor()); 21 | }; 22 | } 23 | 24 | function deepCopy(value) { 25 | if (!(value instanceof Object)) { 26 | if (value === undefined || value === null) 27 | return value; 28 | if (typeof value == 'string') 29 | return value.substring(); 30 | if (typeof value == 'boolean') 31 | return value; 32 | if (typeof value == 'number') 33 | return value; 34 | throw new Error('Unrecognized: ' + typeof value); 35 | } 36 | 37 | var object = value; 38 | if (object instanceof Array) { 39 | var res = new Array(object.length); 40 | for (var i = 0; i < object.length; i++) 41 | res[i] = deepCopy(object[i]); 42 | return res; 43 | } 44 | 45 | if (object.__proto__ != Object.prototype) 46 | throw new Error('Can only clone simple types'); 47 | var res = {}; 48 | for (var key in object) { 49 | res[key] = deepCopy(object[key]); 50 | } 51 | return res; 52 | } 53 | 54 | function normalizeException(e) { 55 | if (e === undefined || e === null) { 56 | return { 57 | typeName: 'UndefinedError', 58 | message: 'Unknown: null or undefined exception', 59 | stack: 'Unknown' 60 | }; 61 | } 62 | 63 | if (typeof(e) == 'string') { 64 | return { 65 | typeName: 'StringError', 66 | message: e, 67 | stack: [e] 68 | }; 69 | } 70 | 71 | var typeName; 72 | if (e.name) { 73 | typeName = e.name; 74 | } else if (e.constructor) { 75 | if (e.constructor.name) { 76 | typeName = e.constructor.name; 77 | } else { 78 | typeName = 'AnonymousError'; 79 | } 80 | } else { 81 | typeName = 'ErrorWithNoConstructor'; 82 | } 83 | 84 | var msg = e.message ? e.message : 'Unknown'; 85 | return { 86 | typeName: typeName, 87 | message: msg, 88 | stack: e.stack ? e.stack : [msg] 89 | }; 90 | } 91 | 92 | function stackTraceAsString() { 93 | return new Error().stack + ''; 94 | } 95 | function stackTrace() { 96 | var stack = stackTraceAsString(); 97 | stack = stack.split('\n'); 98 | return stack.slice(2); 99 | } 100 | 101 | function getUsingPath(path, from_dict) { 102 | var parts = path.split('.'); 103 | var cur = from_dict; 104 | 105 | for (var part; parts.length && (part = parts.shift());) { 106 | if (!parts.length) { 107 | return cur[part]; 108 | } else if (part in cur) { 109 | cur = cur[part]; 110 | } else { 111 | return undefined; 112 | } 113 | } 114 | return undefined; 115 | } 116 | 117 | return { 118 | addSingletonGetter: addSingletonGetter, 119 | 120 | deepCopy: deepCopy, 121 | 122 | normalizeException: normalizeException, 123 | stackTrace: stackTrace, 124 | stackTraceAsString: stackTraceAsString, 125 | 126 | getUsingPath: getUsingPath 127 | }; 128 | }); 129 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/event_container.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/base.js"); 8 | require("../base/guid.js"); 9 | require("../base/range.js"); 10 | 11 | 'use strict'; 12 | 13 | global.tr.exportTo('tr.model', function() { 14 | 15 | /** 16 | * EventContainer is a base class for any class in the trace model that 17 | * contains child events or child EventContainers. 18 | * 19 | * For all EventContainers, updateBounds() must be called after modifying the 20 | * container's events if an up-to-date bounds is expected. 21 | * 22 | * @constructor 23 | */ 24 | function EventContainer() { 25 | this.guid_ = tr.b.GUID.allocate(); 26 | this.important = true; 27 | this.bounds_ = new tr.b.Range(); 28 | } 29 | 30 | EventContainer.prototype = { 31 | get guid() { 32 | return this.guid_; 33 | }, 34 | 35 | /** 36 | * @return {String} A stable and unique identifier that describes this 37 | * container's position in the event tree relative to the root. If an event 38 | * container 'B' is a child to another event container 'A', then container 39 | * B's stable ID would be 'A.B'. 40 | */ 41 | get stableId() { 42 | throw new Error('Not implemented'); 43 | }, 44 | 45 | /** 46 | * Returns the bounds of the event container, which describe the range 47 | * of timestamps for all ancestor events. 48 | */ 49 | get bounds() { 50 | return this.bounds_; 51 | }, 52 | 53 | // TODO(charliea): A default implementation of this method could likely be 54 | // provided that uses 'iterateAllEvents'. 55 | /** 56 | * Updates the bounds of the event container. After updating, this.bounds 57 | * will describe the range of timestamps of all ancestor events. 58 | */ 59 | updateBounds: function() { 60 | throw new Error('Not implemented'); 61 | }, 62 | 63 | // TODO(charliea): A default implementation of this method could likely be 64 | // provided that uses 'iterateAllEvents'. 65 | /** 66 | * Shifts the timestamps for ancestor events by 'amount' milliseconds. 67 | */ 68 | shiftTimestampsForward: function(amount) { 69 | throw new Error('Not implemented'); 70 | }, 71 | 72 | /** 73 | * Iterates over all child events. 74 | */ 75 | iterateAllEventsInThisContainer: function(eventTypePredicate, 76 | callback, opt_this) { 77 | throw new Error('Not implemented'); 78 | }, 79 | 80 | /** 81 | * Iterates over all child containers. 82 | */ 83 | iterateAllChildEventContainers: function(callback, opt_this) { 84 | throw new Error('Not implemented'); 85 | }, 86 | 87 | /** 88 | * Iterates over all ancestor events. 89 | */ 90 | iterateAllEvents: function(callback, opt_this) { 91 | this.iterateAllEventContainers(function(ec) { 92 | ec.iterateAllEventsInThisContainer( 93 | function(eventType) { return true; }, 94 | callback, opt_this); 95 | }); 96 | }, 97 | 98 | /** 99 | * Iterates over this container and all ancestor containers. 100 | */ 101 | iterateAllEventContainers: function(callback, opt_this) { 102 | function visit(ec) { 103 | callback.call(opt_this, ec); 104 | ec.iterateAllChildEventContainers(visit); 105 | } 106 | visit(this); 107 | } 108 | }; 109 | 110 | return { 111 | EventContainer: EventContainer 112 | }; 113 | }); 114 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node Big Rig 2 | 3 | [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][depstat-image]][depstat-url] 4 | 5 | Node Big Rig comes in two flavors: 6 | 7 | 1. A module for doing trace analysis inline to other tasks. 8 | 2. A CLI tool. 9 | 10 | ![Big Rig CLI](https://cloud.githubusercontent.com/assets/617438/10954268/5c977f4c-8344-11e5-9460-dc00e86970f3.png) 11 | 12 | Both the module and CLI perform the same analysis as [the web app](https://github.com/GoogleChrome/big-rig), just without a UI. This makes it a good fit for use in CI environments, or as part of bigger workflows. 13 | 14 | ## Installation 15 | 16 | ### CLI 17 | 18 | ```bash 19 | npm install -g bigrig 20 | ``` 21 | 22 | ### Module 23 | 24 | ```bash 25 | npm install bigrig 26 | ``` 27 | 28 | ## Usage 29 | 30 | ### CLI 31 | 32 | To use the CLI you call `bigrig` and pass it the path to a trace file: 33 | 34 | ```bash 35 | bigrig --file /path/to/trace.json 36 | ``` 37 | 38 | This will, by default, simply return a JSON string that you can parse or manipulate as you see fit. 39 | 40 | If you wish to see a pretty printed version, add the `--pretty-print` flag: 41 | 42 | ```bash 43 | bigrig --file /path/to/trace.json --pretty-print 44 | ``` 45 | 46 | You should then see a pretty printed output of the time breakdown for the trace. 47 | 48 | ### Module 49 | 50 | You can also use Big Rig's module as part of a wider workflow. 51 | 52 | ```node 53 | var bigrig = require('bigrig'); 54 | var fs = require('fs'); 55 | 56 | // Read trace file contents. 57 | fs.readFile('/path/to/trace.json', 'utf8', function(err, data) { 58 | if (err) 59 | throw err; 60 | 61 | results = bigrig.analyze(data); 62 | 63 | // Now do something with the results, like 64 | // post to a dashboard. 65 | }); 66 | 67 | ``` 68 | 69 | ## Getting a trace 70 | 71 | You can get a trace from: 72 | 73 | * **[WebPagetest](http://webpagetest.org)**. Run your test with Chrome, and check "Capture Dev Tools Timeline" under the Chrome options. Download the timeline file (which is a trace file) and pass it to Big Rig. 74 | * **[Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/profile/evaluate-performance/timeline-tool?hl=en)**. Take a timeline recording, and then right click on the timeline, save the file, and pass it to Big Rig. 75 | * **[Big Rig's Test Runner](https://github.com/GoogleChrome/big-rig/tree/master/test-runner)**. This uses Chrome Driver under the hood, and will allow you to run an automated test (including for Android) and get back a trace file. 76 | 77 | **Please note:** you can only have one tab open when running the trace. If you have multiple tabs Big Rig won't be able to disambiguate and process the correct tab. You should also ideally disable any extensions you have running, as these can skew results. You can add the `--strict` flag if you want Big Rig to throw an error when it encounters extensions. 78 | 79 | ## License 80 | 81 | See /LICENSE 82 | 83 | ## Owner 84 | 85 | Paul Lewis - [@aerotwist](https://twitter.com/aerotwist) 86 | 87 | ## Thanks 88 | 89 | The tracing code is a manipulated version of [Chrome's Trace Viewer](https://github.com/catapult-project/catapult/tree/master/tracing). A huge thanks to the Chromium engineers for making it possible to analyze traces. 90 | 91 | Please note: this is not an official Google product. 92 | 93 | [npm-url]: https://npmjs.org/package/bigrig 94 | [npm-image]: https://badge.fury.io/js/bigrig.svg 95 | 96 | [travis-url]: https://travis-ci.org/GoogleChrome/node-big-rig 97 | [travis-image]: https://travis-ci.org/GoogleChrome/node-big-rig.svg?branch=master 98 | 99 | [depstat-url]: https://david-dm.org/GoogleChrome/node-big-rig 100 | [depstat-image]: https://david-dm.org/GoogleChrome/node-big-rig.svg 101 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/chrome/chrome_model_helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../base/base.js"); 8 | require("../../base/iteration_helpers.js"); 9 | require("./chrome_browser_helper.js"); 10 | require("./chrome_gpu_helper.js"); 11 | require("./chrome_renderer_helper.js"); 12 | 13 | 'use strict'; 14 | 15 | /** 16 | * @fileoverview Utilities for accessing trace data about the Chrome browser. 17 | */ 18 | global.tr.exportTo('tr.e.audits', function() { 19 | function findChromeBrowserProcess(model) { 20 | var browserProcesses = []; 21 | model.getAllProcesses().forEach(function(process) { 22 | if (!tr.e.audits.ChromeBrowserHelper.isBrowserProcess(process)) 23 | return; 24 | browserProcesses.push(process); 25 | }, this); 26 | if (browserProcesses.length === 0) 27 | return undefined; 28 | if (browserProcesses.length > 1) 29 | return undefined; 30 | return browserProcesses[0]; 31 | } 32 | 33 | function findChromeRenderProcesses(model) { 34 | var rendererProcesses = []; 35 | model.getAllProcesses().forEach(function(process) { 36 | if (!tr.e.audits.ChromeRendererHelper.isRenderProcess(process)) 37 | return; 38 | rendererProcesses.push(process); 39 | }); 40 | return rendererProcesses; 41 | } 42 | 43 | function findChromeGpuProcess(model) { 44 | var gpuProcesses = model.getAllProcesses().filter( 45 | tr.e.audits.ChromeGpuHelper.isGpuProcess); 46 | if (gpuProcesses.length != 1) 47 | return undefined; 48 | return gpuProcesses[0]; 49 | } 50 | 51 | /** 52 | * @constructor 53 | */ 54 | function ChromeModelHelper(model) { 55 | this.model_ = model; 56 | 57 | // Find browserHelper. 58 | this.browserProcess_ = findChromeBrowserProcess(model); 59 | if (this.browserProcess_) { 60 | this.browserHelper_ = new tr.e.audits.ChromeBrowserHelper( 61 | this, this.browserProcess_); 62 | } else { 63 | this.browserHelper_ = undefined; 64 | } 65 | 66 | // Find gpuHelper. 67 | var gpuProcess = findChromeGpuProcess(model); 68 | if (gpuProcess) { 69 | this.gpuHelper_ = new tr.e.audits.ChromeGpuHelper( 70 | this, gpuProcess); 71 | } else { 72 | this.gpuHelper_ = undefined; 73 | } 74 | 75 | // Find rendererHelpers. 76 | var rendererProcesses_ = findChromeRenderProcesses(model); 77 | 78 | this.rendererHelpers_ = {}; 79 | rendererProcesses_.forEach(function(renderProcess) { 80 | var rendererHelper = new tr.e.audits.ChromeRendererHelper( 81 | this, renderProcess); 82 | this.rendererHelpers_[rendererHelper.pid] = rendererHelper; 83 | }, this); 84 | } 85 | 86 | ChromeModelHelper.supportsModel = function(model) { 87 | if (findChromeBrowserProcess(model) !== undefined) 88 | return true; 89 | if (findChromeRenderProcesses(model).length) 90 | return true; 91 | return false; 92 | } 93 | 94 | ChromeModelHelper.prototype = { 95 | get pid() { 96 | throw new Error('woah'); 97 | }, 98 | 99 | get process() { 100 | throw new Error('woah'); 101 | }, 102 | 103 | get model() { 104 | return this.model_; 105 | }, 106 | 107 | get browserProcess() { 108 | return this.browserProcess_; 109 | }, 110 | 111 | get browserHelper() { 112 | return this.browserHelper_; 113 | }, 114 | 115 | get gpuHelper() { 116 | return this.gpuHelper_; 117 | }, 118 | 119 | get rendererHelpers() { 120 | return this.rendererHelpers_; 121 | } 122 | }; 123 | 124 | return { 125 | ChromeModelHelper: ChromeModelHelper 126 | }; 127 | }); 128 | -------------------------------------------------------------------------------- /lib/third_party/tracing/core/filter.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/base.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.c', function() { 12 | function makeCaseInsensitiveRegex(pattern) { 13 | // See https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/ 14 | // Regular_Expressions. 15 | pattern = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); 16 | return new RegExp(pattern, 'i'); 17 | } 18 | 19 | /** 20 | * @constructor The generic base class for filtering a Model based on 21 | * various rules. The base class returns true for everything. 22 | */ 23 | function Filter() { } 24 | 25 | Filter.prototype = { 26 | __proto__: Object.prototype, 27 | 28 | matchCounter: function(counter) { 29 | return true; 30 | }, 31 | 32 | matchCpu: function(cpu) { 33 | return true; 34 | }, 35 | 36 | matchProcess: function(process) { 37 | return true; 38 | }, 39 | 40 | matchSlice: function(slice) { 41 | return true; 42 | }, 43 | 44 | matchThread: function(thread) { 45 | return true; 46 | } 47 | }; 48 | 49 | /** 50 | * @constructor A filter that matches objects by their name or category 51 | * case insensitive. 52 | * .findAllObjectsMatchingFilter 53 | */ 54 | function TitleOrCategoryFilter(text) { 55 | Filter.call(this); 56 | this.regex_ = makeCaseInsensitiveRegex(text); 57 | 58 | if (!text.length) 59 | throw new Error('Filter text is empty.'); 60 | } 61 | TitleOrCategoryFilter.prototype = { 62 | __proto__: Filter.prototype, 63 | 64 | matchSlice: function(slice) { 65 | if (slice.title === undefined && slice.category === undefined) 66 | return false; 67 | 68 | return this.regex_.test(slice.title) || 69 | (!!slice.category && this.regex_.test(slice.category)); 70 | } 71 | }; 72 | 73 | /** 74 | * @constructor A filter that matches objects with the exact given title. 75 | */ 76 | function ExactTitleFilter(text) { 77 | Filter.call(this); 78 | this.text_ = text; 79 | 80 | if (!text.length) 81 | throw new Error('Filter text is empty.'); 82 | } 83 | ExactTitleFilter.prototype = { 84 | __proto__: Filter.prototype, 85 | 86 | matchSlice: function(slice) { 87 | return slice.title === this.text_; 88 | } 89 | }; 90 | 91 | /** 92 | * @constructor A filter that matches objects by their full text contents 93 | * (title, category, args). Note that for performance this filter applies a 94 | * regex against all the keys of the slice arguments instead of recursing 95 | * through any embedded sub-objects. 96 | */ 97 | function FullTextFilter(text) { 98 | Filter.call(this); 99 | this.regex_ = makeCaseInsensitiveRegex(text); 100 | this.titleOrCategoryFilter_ = new TitleOrCategoryFilter(text); 101 | } 102 | FullTextFilter.prototype = { 103 | __proto__: Filter.prototype, 104 | 105 | matchObject_: function(obj) { 106 | for (var key in obj) { 107 | if (!obj.hasOwnProperty(key)) 108 | continue; 109 | if (this.regex_.test(key)) 110 | return true; 111 | if (this.regex_.test(obj[key])) 112 | return true; 113 | } 114 | return false; 115 | }, 116 | 117 | matchSlice: function(slice) { 118 | if (this.titleOrCategoryFilter_.matchSlice(slice)) 119 | return true; 120 | return this.matchObject_(slice.args); 121 | } 122 | }; 123 | 124 | return { 125 | Filter: Filter, 126 | TitleOrCategoryFilter: TitleOrCategoryFilter, 127 | ExactTitleFilter: ExactTitleFilter, 128 | FullTextFilter: FullTextFilter 129 | }; 130 | }); 131 | -------------------------------------------------------------------------------- /lib/third_party/tracing/base/extension_registry_basic.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./extension_registry_base.js"); 8 | require("./event.js"); 9 | 10 | 'use strict'; 11 | 12 | global.tr.exportTo('tr.b', function() { 13 | 14 | var RegisteredTypeInfo = tr.b.RegisteredTypeInfo; 15 | var ExtensionRegistryOptions = tr.b.ExtensionRegistryOptions; 16 | 17 | function decorateBasicExtensionRegistry(registry, extensionRegistryOptions) { 18 | var savedStateStack = []; 19 | registry.registeredTypeInfos_ = []; 20 | 21 | registry.register = function(constructor, 22 | opt_metadata) { 23 | if (registry.findIndexOfRegisteredConstructor( 24 | constructor) !== undefined) 25 | throw new Error('Handler already registered for ' + constructor); 26 | 27 | extensionRegistryOptions.validateConstructor(constructor); 28 | 29 | var metadata = {}; 30 | for (var k in extensionRegistryOptions.defaultMetadata) 31 | metadata[k] = extensionRegistryOptions.defaultMetadata[k]; 32 | if (opt_metadata) { 33 | for (var k in opt_metadata) 34 | metadata[k] = opt_metadata[k]; 35 | } 36 | 37 | var typeInfo = new RegisteredTypeInfo( 38 | constructor, 39 | metadata); 40 | 41 | var e = new tr.b.Event('will-register'); 42 | e.typeInfo = typeInfo; 43 | registry.dispatchEvent(e); 44 | 45 | registry.registeredTypeInfos_.push(typeInfo); 46 | 47 | e = new tr.b.Event('registry-changed'); 48 | registry.dispatchEvent(e); 49 | }; 50 | 51 | registry.pushCleanStateBeforeTest = function() { 52 | savedStateStack.push(registry.registeredTypeInfos_); 53 | registry.registeredTypeInfos_ = []; 54 | 55 | var e = new tr.b.Event('registry-changed'); 56 | registry.dispatchEvent(e); 57 | }; 58 | registry.popCleanStateAfterTest = function() { 59 | registry.registeredTypeInfos_ = savedStateStack[0]; 60 | savedStateStack.splice(0, 1); 61 | 62 | var e = new tr.b.Event('registry-changed'); 63 | registry.dispatchEvent(e); 64 | }; 65 | 66 | registry.findIndexOfRegisteredConstructor = function(constructor) { 67 | for (var i = 0; i < registry.registeredTypeInfos_.length; i++) 68 | if (registry.registeredTypeInfos_[i].constructor == constructor) 69 | return i; 70 | return undefined; 71 | }; 72 | 73 | registry.unregister = function(constructor) { 74 | var foundIndex = registry.findIndexOfRegisteredConstructor(constructor); 75 | if (foundIndex === undefined) 76 | throw new Error(constructor + ' not registered'); 77 | registry.registeredTypeInfos_.splice(foundIndex, 1); 78 | 79 | var e = new tr.b.Event('registry-changed'); 80 | registry.dispatchEvent(e); 81 | }; 82 | 83 | registry.getAllRegisteredTypeInfos = function() { 84 | return registry.registeredTypeInfos_; 85 | }; 86 | 87 | registry.findTypeInfo = function(constructor) { 88 | var foundIndex = this.findIndexOfRegisteredConstructor(constructor); 89 | if (foundIndex !== undefined) 90 | return this.registeredTypeInfos_[foundIndex]; 91 | return undefined; 92 | }; 93 | 94 | registry.findTypeInfoMatching = function(predicate, opt_this) { 95 | opt_this = opt_this ? opt_this : undefined; 96 | for (var i = 0; i < registry.registeredTypeInfos_.length; ++i) { 97 | var typeInfo = registry.registeredTypeInfos_[i]; 98 | if (predicate.call(opt_this, typeInfo)) 99 | return typeInfo; 100 | } 101 | return extensionRegistryOptions.defaultTypeInfo; 102 | }; 103 | } 104 | 105 | return { 106 | _decorateBasicExtensionRegistry: decorateBasicExtensionRegistry 107 | }; 108 | }); 109 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/linux_perf/sched_parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./parser.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Parses scheduler events in the Linux event trace format. 13 | */ 14 | global.tr.exportTo('tr.e.importer.linux_perf', function() { 15 | 16 | var Parser = tr.e.importer.linux_perf.Parser; 17 | 18 | /** 19 | * Parses linux sched trace events. 20 | * @constructor 21 | */ 22 | function SchedParser(importer) { 23 | Parser.call(this, importer); 24 | 25 | importer.registerEventHandler('sched_switch', 26 | SchedParser.prototype.schedSwitchEvent.bind(this)); 27 | importer.registerEventHandler('sched_wakeup', 28 | SchedParser.prototype.schedWakeupEvent.bind(this)); 29 | importer.registerEventHandler('sched_blocked_reason', 30 | SchedParser.prototype.schedBlockedEvent.bind(this)); 31 | } 32 | 33 | var TestExports = {}; 34 | 35 | // Matches the sched_switch record 36 | var schedSwitchRE = new RegExp( 37 | 'prev_comm=(.+) prev_pid=(\\d+) prev_prio=(\\d+) ' + 38 | 'prev_state=(\\S\\+?|\\S\\|\\S) ==> ' + 39 | 'next_comm=(.+) next_pid=(\\d+) next_prio=(\\d+)'); 40 | 41 | // Matches sched_blocked_reason record 42 | var schedBlockedRE = new RegExp('pid=(\\d+) iowait=(\\d) caller=(.+)'); 43 | TestExports.schedSwitchRE = schedSwitchRE; 44 | 45 | // Matches the sched_wakeup record 46 | var schedWakeupRE = 47 | /comm=(.+) pid=(\d+) prio=(\d+) success=(\d+) target_cpu=(\d+)/; 48 | TestExports.schedWakeupRE = schedWakeupRE; 49 | 50 | SchedParser.prototype = { 51 | __proto__: Parser.prototype, 52 | 53 | /** 54 | * Parses scheduler events and sets up state in the CPUs of the importer. 55 | */ 56 | schedSwitchEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 57 | var event = schedSwitchRE.exec(eventBase.details); 58 | if (!event) 59 | return false; 60 | 61 | var prevState = event[4]; 62 | var nextComm = event[5]; 63 | var nextPid = parseInt(event[6]); 64 | var nextPrio = parseInt(event[7]); 65 | 66 | var nextThread = this.importer.threadsByLinuxPid[nextPid]; 67 | var nextName; 68 | if (nextThread) 69 | nextName = nextThread.userFriendlyName; 70 | else 71 | nextName = nextComm; 72 | 73 | var cpu = this.importer.getOrCreateCpu(cpuNumber); 74 | cpu.switchActiveThread( 75 | ts, 76 | {stateWhenDescheduled: prevState}, 77 | nextPid, 78 | nextName, 79 | { 80 | comm: nextComm, 81 | tid: nextPid, 82 | prio: nextPrio 83 | }); 84 | 85 | return true; 86 | }, 87 | 88 | schedWakeupEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 89 | var event = schedWakeupRE.exec(eventBase.details); 90 | if (!event) 91 | return false; 92 | 93 | var fromPid = pid; 94 | var comm = event[1]; 95 | var pid = parseInt(event[2]); 96 | var prio = parseInt(event[3]); 97 | this.importer.markPidRunnable(ts, pid, comm, prio, fromPid); 98 | return true; 99 | }, 100 | 101 | schedBlockedEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 102 | var event = schedBlockedRE.exec(eventBase.details); 103 | if (!event) 104 | return false; 105 | 106 | var pid = parseInt(event[1]); 107 | var iowait = parseInt(event[2]); 108 | var caller = event[3]; 109 | 110 | this.importer.addPidBlockedReason(ts, pid, iowait, caller); 111 | return true; 112 | } 113 | }; 114 | 115 | Parser.register(SchedParser); 116 | 117 | return { 118 | SchedParser: SchedParser, 119 | _SchedParserTestExports: TestExports 120 | }; 121 | }); 122 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/trace_code_entry.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../../model/source_info/js_source_info.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview TraceCodeEntry is a wrapper around the V8 CodeEntry that 13 | * extracts extra context information for each item. This includes things like 14 | * the source file, line and if the function is a native method or not. 15 | */ 16 | global.tr.exportTo('tr.e.importer', function() { 17 | function TraceCodeEntry(address, size, name, scriptId) { 18 | this.id_ = tr.b.GUID.allocate(); 19 | this.address_ = address; 20 | this.size_ = size; 21 | 22 | // Stolen from DevTools TimelineJSProfileProcessor._buildCallFrame 23 | // Code states: 24 | // (empty) -> compiled 25 | // ~ -> optimizable 26 | // * -> optimized 27 | var rePrefix = /^(\w*:)?([*~]?)(.*)$/m; 28 | var tokens = rePrefix.exec(name); 29 | var prefix = tokens[1]; 30 | var state = tokens[2]; 31 | var body = tokens[3]; 32 | 33 | if (state === '*') { 34 | state = tr.model.source_info.JSSourceState.OPTIMIZED; 35 | } else if (state === '~') { 36 | state = tr.model.source_info.JSSourceState.OPTIMIZABLE; 37 | } else if (state === '') { 38 | state = tr.model.source_info.JSSourceState.COMPILED; 39 | } else { 40 | console.warning('Unknown v8 code state ' + state); 41 | state = tr.model.source_info.JSSourceState.UNKNOWN; 42 | } 43 | 44 | var rawName; 45 | var rawUrl; 46 | if (prefix === 'Script:') { 47 | rawName = ''; 48 | rawUrl = body; 49 | } else { 50 | var spacePos = body.lastIndexOf(' '); 51 | rawName = spacePos !== -1 ? body.substr(0, spacePos) : body; 52 | rawUrl = spacePos !== -1 ? body.substr(spacePos + 1) : ''; 53 | } 54 | 55 | function splitLineAndColumn(url) { 56 | var lineColumnRegEx = /(?::(\d+))?(?::(\d+))?$/; 57 | var lineColumnMatch = lineColumnRegEx.exec(url); 58 | var lineNumber; 59 | var columnNumber; 60 | 61 | if (typeof(lineColumnMatch[1]) === 'string') { 62 | lineNumber = parseInt(lineColumnMatch[1], 10); 63 | // Immediately convert line and column to 0-based numbers. 64 | lineNumber = isNaN(lineNumber) ? undefined : lineNumber - 1; 65 | } 66 | if (typeof(lineColumnMatch[2]) === 'string') { 67 | columnNumber = parseInt(lineColumnMatch[2], 10); 68 | columnNumber = isNaN(columnNumber) ? undefined : columnNumber - 1; 69 | } 70 | 71 | return { 72 | url: url.substring(0, url.length - lineColumnMatch[0].length), 73 | lineNumber: lineNumber, 74 | columnNumber: columnNumber 75 | }; 76 | } 77 | 78 | var nativeSuffix = ' native'; 79 | var isNative = rawName.endsWith(nativeSuffix); 80 | this.name_ = 81 | isNative ? rawName.slice(0, -nativeSuffix.length) : rawName; 82 | 83 | var urlData = splitLineAndColumn(rawUrl); 84 | var url = urlData.url || ''; 85 | var line = urlData.lineNumber || 0; 86 | var column = urlData.columnNumber || 0; 87 | 88 | this.sourceInfo_ = new tr.model.source_info.JSSourceInfo( 89 | url, line, column, isNative, scriptId, state); 90 | }; 91 | 92 | TraceCodeEntry.prototype = { 93 | get id() { 94 | return this.id_; 95 | }, 96 | 97 | get sourceInfo() { 98 | return this.sourceInfo_; 99 | }, 100 | 101 | get name() { 102 | return this.name_; 103 | }, 104 | 105 | set address(address) { 106 | this.address_ = address; 107 | }, 108 | 109 | get address() { 110 | return this.address_; 111 | }, 112 | 113 | set size(size) { 114 | this.size_ = size; 115 | }, 116 | 117 | get size() { 118 | return this.size_; 119 | } 120 | }; 121 | 122 | return { 123 | TraceCodeEntry: TraceCodeEntry 124 | }; 125 | }); 126 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/linux_perf/cpufreq_parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./parser.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Parses cpufreq events in the Linux event trace format. 13 | */ 14 | global.tr.exportTo('tr.e.importer.linux_perf', function() { 15 | 16 | var ColorScheme = tr.b.ColorScheme; 17 | var Parser = tr.e.importer.linux_perf.Parser; 18 | 19 | /** 20 | * Parses linux cpufreq trace events. 21 | * @constructor 22 | */ 23 | function CpufreqParser(importer) { 24 | Parser.call(this, importer); 25 | 26 | importer.registerEventHandler('cpufreq_interactive_up', 27 | CpufreqParser.prototype.cpufreqUpDownEvent.bind(this)); 28 | importer.registerEventHandler('cpufreq_interactive_down', 29 | CpufreqParser.prototype.cpufreqUpDownEvent.bind(this)); 30 | importer.registerEventHandler('cpufreq_interactive_already', 31 | CpufreqParser.prototype.cpufreqTargetEvent.bind(this)); 32 | importer.registerEventHandler('cpufreq_interactive_notyet', 33 | CpufreqParser.prototype.cpufreqTargetEvent.bind(this)); 34 | importer.registerEventHandler('cpufreq_interactive_setspeed', 35 | CpufreqParser.prototype.cpufreqTargetEvent.bind(this)); 36 | importer.registerEventHandler('cpufreq_interactive_target', 37 | CpufreqParser.prototype.cpufreqTargetEvent.bind(this)); 38 | importer.registerEventHandler('cpufreq_interactive_boost', 39 | CpufreqParser.prototype.cpufreqBoostUnboostEvent.bind(this)); 40 | importer.registerEventHandler('cpufreq_interactive_unboost', 41 | CpufreqParser.prototype.cpufreqBoostUnboostEvent.bind(this)); 42 | } 43 | 44 | function splitData(input) { 45 | // TODO(sleffler) split by cpu 46 | var data = {}; 47 | var args = input.split(/\s+/); 48 | var len = args.length; 49 | for (var i = 0; i < len; i++) { 50 | var item = args[i].split('='); 51 | data[item[0]] = parseInt(item[1]); 52 | } 53 | return data; 54 | } 55 | 56 | CpufreqParser.prototype = { 57 | __proto__: Parser.prototype, 58 | 59 | cpufreqSlice: function(ts, eventName, cpu, args) { 60 | // TODO(sleffler) should be per-cpu 61 | var kthread = this.importer.getOrCreatePseudoThread('cpufreq'); 62 | kthread.openSlice = eventName; 63 | var slice = new tr.model.Slice('', kthread.openSlice, 64 | ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice), 65 | ts, args, 0); 66 | 67 | kthread.thread.sliceGroup.pushSlice(slice); 68 | }, 69 | 70 | cpufreqBoostSlice: function(ts, eventName, args) { 71 | var kthread = this.importer.getOrCreatePseudoThread('cpufreq_boost'); 72 | kthread.openSlice = eventName; 73 | var slice = new tr.model.Slice('', kthread.openSlice, 74 | ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice), 75 | ts, args, 0); 76 | 77 | kthread.thread.sliceGroup.pushSlice(slice); 78 | }, 79 | 80 | /** 81 | * Parses cpufreq events and sets up state in the importer. 82 | */ 83 | cpufreqUpDownEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 84 | var data = splitData(eventBase.details); 85 | this.cpufreqSlice(ts, eventName, data.cpu, data); 86 | return true; 87 | }, 88 | 89 | cpufreqTargetEvent: function(eventName, cpuNumber, pid, ts, 90 | eventBase) { 91 | var data = splitData(eventBase.details); 92 | this.cpufreqSlice(ts, eventName, data.cpu, data); 93 | return true; 94 | }, 95 | 96 | cpufreqBoostUnboostEvent: function(eventName, cpuNumber, pid, ts, 97 | eventBase) { 98 | this.cpufreqBoostSlice(ts, eventName, 99 | { 100 | type: eventBase.details 101 | }); 102 | return true; 103 | } 104 | }; 105 | 106 | Parser.register(CpufreqParser); 107 | 108 | return { 109 | CpufreqParser: CpufreqParser 110 | }; 111 | }); 112 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/linux_perf/sync_parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./parser.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Parses sync events in the Linux event trace format. 13 | */ 14 | global.tr.exportTo('tr.e.importer.linux_perf', function() { 15 | 16 | var ColorScheme = tr.b.ColorScheme; 17 | var Parser = tr.e.importer.linux_perf.Parser; 18 | 19 | /** 20 | * Parses linux sync trace events. 21 | * @constructor 22 | */ 23 | function SyncParser(importer) { 24 | Parser.call(this, importer); 25 | 26 | importer.registerEventHandler( 27 | 'sync_timeline', 28 | SyncParser.prototype.timelineEvent.bind(this)); 29 | importer.registerEventHandler( 30 | 'sync_wait', 31 | SyncParser.prototype.syncWaitEvent.bind(this)); 32 | importer.registerEventHandler( 33 | 'sync_pt', 34 | SyncParser.prototype.syncPtEvent.bind(this)); 35 | this.model_ = importer.model_; 36 | } 37 | 38 | var syncTimelineRE = /name=(\S+) value=(\S*)/; 39 | var syncWaitRE = /(\S+) name=(\S+) state=(\d+)/; 40 | var syncPtRE = /name=(\S+) value=(\S*)/; 41 | 42 | SyncParser.prototype = { 43 | __proto__: Parser.prototype, 44 | 45 | /** 46 | * Parses sync events and sets up state in the importer. 47 | */ 48 | timelineEvent: function(eventName, cpuNumber, pid, 49 | ts, eventBase) { 50 | var event = syncTimelineRE.exec(eventBase.details); 51 | if (!event) 52 | return false; 53 | 54 | var thread = this.importer.getOrCreatePseudoThread(event[1]); 55 | 56 | if (thread.lastActiveTs !== undefined) { 57 | var duration = ts - thread.lastActiveTs; 58 | var value = thread.lastActiveValue; 59 | if (value == undefined) 60 | value = ' '; 61 | var slice = new tr.model.Slice( 62 | '', value, 63 | ColorScheme.getColorIdForGeneralPurposeString(value), 64 | thread.lastActiveTs, {}, 65 | duration); 66 | thread.thread.sliceGroup.pushSlice(slice); 67 | } 68 | thread.lastActiveTs = ts; 69 | thread.lastActiveValue = event[2]; 70 | return true; 71 | }, 72 | 73 | syncWaitEvent: function(eventName, cpuNumber, pid, ts, 74 | eventBase) { 75 | var event = syncWaitRE.exec(eventBase.details); 76 | if (!event) 77 | return false; 78 | 79 | if (eventBase.tgid === undefined) { 80 | return false; 81 | } 82 | 83 | var tgid = parseInt(eventBase.tgid); 84 | var thread = this.model_.getOrCreateProcess(tgid) 85 | .getOrCreateThread(pid); 86 | thread.name = eventBase.threadName; 87 | var slices = thread.kernelSliceGroup; 88 | if (!slices.isTimestampValidForBeginOrEnd(ts)) { 89 | this.model_.importWarning({ 90 | type: 'parse_error', 91 | message: 'Timestamps are moving backward.' 92 | }); 93 | return false; 94 | } 95 | 96 | var name = 'fence_wait("' + event[2] + '")'; 97 | if (event[1] == 'begin') { 98 | var slice = slices.beginSlice(null, name, ts, { 99 | 'Start state': event[3] 100 | }); 101 | } else if (event[1] == 'end') { 102 | if (slices.openSliceCount > 0) { 103 | slices.endSlice(ts); 104 | } 105 | } else { 106 | return false; 107 | } 108 | 109 | return true; 110 | }, 111 | 112 | syncPtEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 113 | var event = syncPtRE.exec(eventBase.details); 114 | if (!event) 115 | return false; 116 | 117 | return true; 118 | 119 | var thread = this.importer.getOrCreateKernelThread( 120 | eventBase[1]).thread; 121 | thread.syncWaitSyncPts[event[1]] = event[2]; 122 | return true; 123 | } 124 | }; 125 | 126 | Parser.register(SyncParser); 127 | 128 | return { 129 | SyncParser: SyncParser 130 | }; 131 | }); 132 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/memory_allocator_dump.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./attribute.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Provides the MemoryAllocatorDump class. 13 | */ 14 | global.tr.exportTo('tr.model', function() { 15 | /** 16 | * @constructor 17 | */ 18 | function MemoryAllocatorDump(containerMemoryDump, fullName, opt_guid) { 19 | this.fullName = fullName; 20 | this.parent = undefined; 21 | this.children = []; 22 | this.attributes = {}; 23 | 24 | // The associated container memory dump. 25 | this.containerMemoryDump = containerMemoryDump; 26 | 27 | // Ownership relationship between memory allocator dumps. 28 | this.owns = undefined; 29 | this.ownedBy = []; 30 | 31 | // Retention relationship between memory allocator dumps. 32 | this.retains = []; 33 | this.retainedBy = []; 34 | 35 | // For debugging purposes. 36 | this.guid = opt_guid; 37 | }; 38 | 39 | /** 40 | * Size attribute names. Please refer to the Memory Dump Graph Metric 41 | * Calculation design document for more details (https://goo.gl/fKg0dt). 42 | */ 43 | MemoryAllocatorDump.SIZE_ATTRIBUTE_NAME = 'size'; 44 | MemoryAllocatorDump.EFFECTIVE_SIZE_ATTRIBUTE_NAME = 'effective_size'; 45 | MemoryAllocatorDump.RESIDENT_SIZE_ATTRIBUTE_NAME = 'resident_size'; 46 | MemoryAllocatorDump.DISPLAYED_SIZE_ATTRIBUTE_NAME = 47 | MemoryAllocatorDump.EFFECTIVE_SIZE_ATTRIBUTE_NAME; 48 | 49 | MemoryAllocatorDump.prototype = { 50 | get name() { 51 | return this.fullName.substring(this.fullName.lastIndexOf('/') + 1); 52 | }, 53 | 54 | get quantifiedName() { 55 | return '\'' + this.fullName + '\' in ' + 56 | this.containerMemoryDump.containerName; 57 | }, 58 | 59 | isDescendantOf: function(otherDump) { 60 | var dump = this; 61 | while (dump !== undefined) { 62 | if (dump === otherDump) 63 | return true; 64 | dump = dump.parent; 65 | } 66 | return false; 67 | }, 68 | 69 | addAttribute: function(name, value) { 70 | if (name in this.attributes) 71 | throw new Error('Duplicate attribute name: ' + name + '.'); 72 | this.attributes[name] = value; 73 | }, 74 | 75 | aggregateAttributes: function(opt_model) { 76 | var attributes = {}; 77 | 78 | this.children.forEach(function(child) { 79 | child.aggregateAttributes(opt_model); 80 | tr.b.iterItems(child.attributes, function(name) { 81 | attributes[name] = true; 82 | }, this); 83 | }, this); 84 | 85 | tr.b.iterItems(attributes, function(name) { 86 | var childAttributes = this.children.map(function(child) { 87 | return child.attributes[name]; 88 | }, this); 89 | var currentAttribute = this.attributes[name]; 90 | this.attributes[name] = tr.model.Attribute.aggregate( 91 | childAttributes, currentAttribute, opt_model); 92 | }, this); 93 | }, 94 | 95 | getValidSizeAttributeOrUndefined: function(sizeAttrName, opt_model) { 96 | var sizeAttr = this.attributes[sizeAttrName]; 97 | if (sizeAttr === undefined) 98 | return undefined; 99 | 100 | if (!(sizeAttr instanceof tr.model.ScalarAttribute)) { 101 | if (opt_model !== undefined) { 102 | opt_model.importWarning({ 103 | type: 'memory_dump_parse_error', 104 | message: '\'' + sizeAttrName + '\' attribute of memory allocator ' + 105 | 'dump \'' + memoryAllocatorDump.fullName + '\' is not a scalar.' 106 | }); 107 | } 108 | return undefined; 109 | } 110 | 111 | return sizeAttr; 112 | } 113 | }; 114 | 115 | /** 116 | * @constructor 117 | */ 118 | function MemoryAllocatorDumpLink(source, target, opt_importance) { 119 | this.source = source; 120 | this.target = target; 121 | this.importance = opt_importance; 122 | } 123 | 124 | return { 125 | MemoryAllocatorDump: MemoryAllocatorDump, 126 | MemoryAllocatorDumpLink: MemoryAllocatorDumpLink 127 | }; 128 | }); 129 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/kernel.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./cpu.js"); 8 | require("./process_base.js"); 9 | require("../base/iteration_helpers.js"); 10 | 11 | 'use strict'; 12 | 13 | /** 14 | * @fileoverview Provides the Process class. 15 | */ 16 | global.tr.exportTo('tr.model', function() { 17 | var Cpu = tr.model.Cpu; 18 | var ProcessBase = tr.model.ProcessBase; 19 | 20 | /** 21 | * The Kernel represents kernel-level objects in the model. 22 | * @constructor 23 | */ 24 | function Kernel(model) { 25 | ProcessBase.call(this, model); 26 | 27 | this.cpus = {}; 28 | this.softwareMeasuredCpuCount_ = undefined; 29 | }; 30 | 31 | /** 32 | * Comparison between kernels is pretty meaningless. 33 | */ 34 | Kernel.compare = function(x, y) { 35 | return 0; 36 | }; 37 | 38 | Kernel.prototype = { 39 | __proto__: ProcessBase.prototype, 40 | 41 | compareTo: function(that) { 42 | return Kernel.compare(this, that); 43 | }, 44 | 45 | get userFriendlyName() { 46 | return 'Kernel'; 47 | }, 48 | 49 | get userFriendlyDetails() { 50 | return 'Kernel'; 51 | }, 52 | 53 | get stableId() { 54 | return 'Kernel'; 55 | }, 56 | 57 | /** 58 | * @return {Cpu} Gets a specific Cpu or creates one if 59 | * it does not exist. 60 | */ 61 | getOrCreateCpu: function(cpuNumber) { 62 | if (!this.cpus[cpuNumber]) 63 | this.cpus[cpuNumber] = new Cpu(this, cpuNumber); 64 | return this.cpus[cpuNumber]; 65 | }, 66 | 67 | get softwareMeasuredCpuCount() { 68 | return this.softwareMeasuredCpuCount_; 69 | }, 70 | 71 | set softwareMeasuredCpuCount(softwareMeasuredCpuCount) { 72 | if (this.softwareMeasuredCpuCount_ !== undefined && 73 | this.softwareMeasuredCpuCount_ !== softwareMeasuredCpuCount) { 74 | throw new Error( 75 | 'Cannot change the softwareMeasuredCpuCount once it is set'); 76 | } 77 | 78 | this.softwareMeasuredCpuCount_ = softwareMeasuredCpuCount; 79 | }, 80 | 81 | /** 82 | * Estimates how many cpus are in the system, for use in system load 83 | * estimation. 84 | * 85 | * If kernel trace was provided, uses that data. Otherwise, uses the 86 | * software measured cpu count. 87 | */ 88 | get bestGuessAtCpuCount() { 89 | var realCpuCount = tr.b.dictionaryLength(this.cpus); 90 | if (realCpuCount !== 0) 91 | return realCpuCount; 92 | return this.softwareMeasuredCpuCount; 93 | }, 94 | 95 | updateBounds: function() { 96 | ProcessBase.prototype.updateBounds.call(this); 97 | for (var cpuNumber in this.cpus) { 98 | var cpu = this.cpus[cpuNumber]; 99 | cpu.updateBounds(); 100 | this.bounds.addRange(cpu.bounds); 101 | } 102 | }, 103 | 104 | createSubSlices: function() { 105 | ProcessBase.prototype.createSubSlices.call(this); 106 | for (var cpuNumber in this.cpus) { 107 | var cpu = this.cpus[cpuNumber]; 108 | cpu.createSubSlices(); 109 | } 110 | }, 111 | 112 | addCategoriesToDict: function(categoriesDict) { 113 | ProcessBase.prototype.addCategoriesToDict.call(this, categoriesDict); 114 | for (var cpuNumber in this.cpus) 115 | this.cpus[cpuNumber].addCategoriesToDict(categoriesDict); 116 | }, 117 | 118 | getSettingsKey: function() { 119 | return 'kernel'; 120 | }, 121 | 122 | iterateAllChildEventContainers: function(callback, opt_this) { 123 | ProcessBase.prototype.iterateAllChildEventContainers.call( 124 | this, callback, opt_this); 125 | for (var cpuId in this.cpus) 126 | callback.call(opt_this, this.cpus[cpuId]); 127 | }, 128 | 129 | iterateAllEventsInThisContainer: function(eventTypePredicate, 130 | callback, opt_this) { 131 | ProcessBase.prototype.iterateAllEventsInThisContainer.call( 132 | this, eventTypePredicate, callback, opt_this); 133 | } 134 | }; 135 | 136 | return { 137 | Kernel: Kernel 138 | }; 139 | }); 140 | -------------------------------------------------------------------------------- /lib/third_party/tracing/base/rect.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./base.js"); 8 | require("./math.js"); 9 | 10 | 'use strict'; 11 | 12 | /** 13 | * @fileoverview 2D Rectangle math. 14 | */ 15 | 16 | global.tr.exportTo('tr.b', function() { 17 | 18 | /** 19 | * Tracks a 2D bounding box. 20 | * @constructor 21 | */ 22 | function Rect() { 23 | this.x = 0; 24 | this.y = 0; 25 | this.width = 0; 26 | this.height = 0; 27 | }; 28 | Rect.fromXYWH = function(x, y, w, h) { 29 | var rect = new Rect(); 30 | rect.x = x; 31 | rect.y = y; 32 | rect.width = w; 33 | rect.height = h; 34 | return rect; 35 | } 36 | Rect.fromArray = function(ary) { 37 | if (ary.length != 4) 38 | throw new Error('ary.length must be 4'); 39 | var rect = new Rect(); 40 | rect.x = ary[0]; 41 | rect.y = ary[1]; 42 | rect.width = ary[2]; 43 | rect.height = ary[3]; 44 | return rect; 45 | } 46 | 47 | Rect.prototype = { 48 | __proto__: Object.prototype, 49 | 50 | get left() { 51 | return this.x; 52 | }, 53 | 54 | get top() { 55 | return this.y; 56 | }, 57 | 58 | get right() { 59 | return this.x + this.width; 60 | }, 61 | 62 | get bottom() { 63 | return this.y + this.height; 64 | }, 65 | 66 | toString: function() { 67 | return 'Rect(' + this.x + ', ' + this.y + ', ' + 68 | this.width + ', ' + this.height + ')'; 69 | }, 70 | 71 | toArray: function() { 72 | return [this.x, this.y, this.width, this.height]; 73 | }, 74 | 75 | clone: function() { 76 | var rect = new Rect(); 77 | rect.x = this.x; 78 | rect.y = this.y; 79 | rect.width = this.width; 80 | rect.height = this.height; 81 | return rect; 82 | }, 83 | 84 | enlarge: function(pad) { 85 | var rect = new Rect(); 86 | this.enlargeFast(rect, pad); 87 | return rect; 88 | }, 89 | 90 | enlargeFast: function(out, pad) { 91 | out.x = this.x - pad; 92 | out.y = this.y - pad; 93 | out.width = this.width + 2 * pad; 94 | out.height = this.height + 2 * pad; 95 | return out; 96 | }, 97 | 98 | size: function() { 99 | return {width: this.width, height: this.height}; 100 | }, 101 | 102 | scale: function(s) { 103 | var rect = new Rect(); 104 | this.scaleFast(rect, s); 105 | return rect; 106 | }, 107 | 108 | scaleSize: function(s) { 109 | return Rect.fromXYWH(this.x, this.y, this.width * s, this.height * s); 110 | }, 111 | 112 | scaleFast: function(out, s) { 113 | out.x = this.x * s; 114 | out.y = this.y * s; 115 | out.width = this.width * s; 116 | out.height = this.height * s; 117 | return out; 118 | }, 119 | 120 | translate: function(v) { 121 | var rect = new Rect(); 122 | this.translateFast(rect, v); 123 | return rect; 124 | }, 125 | 126 | translateFast: function(out, v) { 127 | out.x = this.x + v[0]; 128 | out.y = this.x + v[1]; 129 | out.width = this.width; 130 | out.height = this.height; 131 | return out; 132 | }, 133 | 134 | asUVRectInside: function(containingRect) { 135 | var rect = new Rect(); 136 | rect.x = (this.x - containingRect.x) / containingRect.width; 137 | rect.y = (this.y - containingRect.y) / containingRect.height; 138 | rect.width = this.width / containingRect.width; 139 | rect.height = this.height / containingRect.height; 140 | return rect; 141 | }, 142 | 143 | intersects: function(that) { 144 | var ok = true; 145 | ok &= this.x < that.right; 146 | ok &= this.right > that.x; 147 | ok &= this.y < that.bottom; 148 | ok &= this.bottom > that.y; 149 | return ok; 150 | }, 151 | 152 | equalTo: function(rect) { 153 | return rect && 154 | (this.x === rect.x) && 155 | (this.y === rect.y) && 156 | (this.width === rect.width) && 157 | (this.height === rect.height); 158 | } 159 | }; 160 | 161 | return { 162 | Rect: Rect 163 | }; 164 | 165 | }); 166 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/chrome/chrome_browser_helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2014 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./chrome_process_helper.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Utilities for accessing trace data about the Chrome browser. 13 | */ 14 | global.tr.exportTo('tr.e.audits', function() { 15 | function ChromeBrowserHelper(modelHelper, process) { 16 | tr.e.audits.ChromeProcessHelper.call(this, modelHelper, process); 17 | this.mainThread_ = process.findAtMostOneThreadNamed('CrBrowserMain'); 18 | } 19 | 20 | ChromeBrowserHelper.isBrowserProcess = function(process) { 21 | return !!process.findAtMostOneThreadNamed('CrBrowserMain'); 22 | }; 23 | 24 | ChromeBrowserHelper.prototype = { 25 | __proto__: tr.e.audits.ChromeProcessHelper.prototype, 26 | 27 | get rendererHelpers() { 28 | return this.modelHelper.rendererHelpers; 29 | }, 30 | 31 | getLoadingEventsInRange: function(rangeOfInterest) { 32 | return this.getAllAsyncSlicesMatching(function(slice) { 33 | return slice.title.indexOf('WebContentsImpl Loading') === 0 && 34 | rangeOfInterest.intersectsExplicitRangeInclusive( 35 | slice.start, slice.end); 36 | }); 37 | }, 38 | 39 | getCommitProvisionalLoadEventsInRange: function(rangeOfInterest) { 40 | return this.getAllAsyncSlicesMatching(function(slice) { 41 | return slice.title === 'RenderFrameImpl::didCommitProvisionalLoad' && 42 | rangeOfInterest.intersectsExplicitRangeInclusive( 43 | slice.start, slice.end); 44 | }); 45 | }, 46 | 47 | get hasLatencyEvents() { 48 | var hasLatency = false; 49 | this.modelHelper.model.getAllThreads().some(function(thread) { 50 | thread.iterateAllEvents(function(event) { 51 | if (!event.isTopLevel) 52 | return; 53 | if (!(event instanceof tr.e.cc.InputLatencyAsyncSlice)) 54 | return; 55 | hasLatency = true; 56 | }); 57 | return hasLatency; 58 | }); 59 | return hasLatency; 60 | }, 61 | 62 | getLatencyEventsInRange: function(rangeOfInterest) { 63 | return this.getAllAsyncSlicesMatching(function(slice) { 64 | return (slice.title.indexOf('InputLatency') === 0) && 65 | rangeOfInterest.intersectsExplicitRangeInclusive( 66 | slice.start, slice.end); 67 | }); 68 | }, 69 | 70 | getAllAsyncSlicesMatching: function(pred, opt_this) { 71 | var events = []; 72 | this.iterAllThreads(function(thread) { 73 | thread.iterateAllEvents(function(slice) { 74 | if (pred.call(opt_this, slice)) 75 | events.push(slice); 76 | }); 77 | }); 78 | return events; 79 | }, 80 | 81 | getAllNetworkEventsInRange: function(rangeOfInterest) { 82 | var networkEvents = []; 83 | this.modelHelper.model.getAllThreads().forEach(function(thread) { 84 | thread.asyncSliceGroup.slices.forEach(function(slice) { 85 | var match = false; 86 | if (slice.category == 'net' || // old-style URLRequest/Resource 87 | slice.category == 'disabled-by-default-netlog' || 88 | slice.category == 'netlog') { 89 | match = true; 90 | } 91 | 92 | if (!match) 93 | return; 94 | 95 | if (rangeOfInterest.intersectsExplicitRangeInclusive( 96 | slice.start, slice.end)) 97 | networkEvents.push(slice); 98 | }); 99 | }); 100 | return networkEvents; 101 | }, 102 | 103 | iterAllThreads: function(func, opt_this) { 104 | tr.b.iterItems(this.process.threads, function(tid, thread) { 105 | func.call(opt_this, thread); 106 | }); 107 | 108 | tr.b.iterItems(this.rendererHelpers, function(pid, rendererHelper) { 109 | var rendererProcess = rendererHelper.process; 110 | tr.b.iterItems(rendererProcess.threads, function(tid, thread) { 111 | func.call(opt_this, thread); 112 | }); 113 | }, this); 114 | } 115 | }; 116 | 117 | return { 118 | ChromeBrowserHelper: ChromeBrowserHelper 119 | }; 120 | }); 121 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/trace_code_map.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2015 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./trace_code_entry.js"); 8 | 9 | 'use strict'; 10 | 11 | global.tr.exportTo('tr.e.importer', function() { 12 | // This code is a tracification of: 13 | // devtools/front_end/timeline/TimelineJSProfile.js 14 | function TraceCodeMap() { 15 | this.banks_ = new Map(); 16 | } 17 | 18 | TraceCodeMap.prototype = { 19 | addEntry: function(addressHex, size, name, scriptId) { 20 | var entry = new tr.e.importer.TraceCodeEntry( 21 | this.getAddress_(addressHex), size, name, scriptId); 22 | 23 | this.addEntry_(addressHex, entry); 24 | }, 25 | 26 | moveEntry: function(oldAddressHex, newAddressHex, size) { 27 | var entry = this.getBank_(oldAddressHex) 28 | .removeEntry(this.getAddress_(oldAddressHex)); 29 | if (!entry) 30 | return; 31 | 32 | entry.address = this.getAddress_(newAddressHex); 33 | entry.size = size; 34 | this.addEntry_(newAddressHex, entry); 35 | }, 36 | 37 | lookupEntry: function(addressHex) { 38 | return this.getBank_(addressHex) 39 | .lookupEntry(this.getAddress_(addressHex)); 40 | }, 41 | 42 | addEntry_: function(addressHex, entry) { 43 | // FIXME: Handle bank spanning addresses ... 44 | this.getBank_(addressHex).addEntry(entry); 45 | }, 46 | 47 | getAddress_: function(addressHex) { 48 | // 13 hex digits == 52 bits, double mantissa fits 53 bits. 49 | var bankSizeHexDigits = 13; 50 | addressHex = addressHex.slice(2); // cut 0x prefix. 51 | return parseInt(addressHex.slice(-bankSizeHexDigits), 16); 52 | }, 53 | 54 | getBank_: function(addressHex) { 55 | addressHex = addressHex.slice(2); // cut 0x prefix. 56 | 57 | // 13 hex digits == 52 bits, double mantissa fits 53 bits. 58 | var bankSizeHexDigits = 13; 59 | var maxHexDigits = 16; 60 | var bankName = addressHex.slice(-maxHexDigits, -bankSizeHexDigits); 61 | var bank = this.banks_.get(bankName); 62 | if (!bank) { 63 | bank = new TraceCodeBank(); 64 | this.banks_.set(bankName, bank); 65 | } 66 | return bank; 67 | } 68 | }; 69 | 70 | function TraceCodeBank() { 71 | this.entries_ = []; 72 | } 73 | 74 | TraceCodeBank.prototype = { 75 | removeEntry: function(address) { 76 | // findLowIndexInSortedArray returns 1 for empty. Just handle the 77 | // empty list and bail early. 78 | if (this.entries_.length === 0) 79 | return undefined; 80 | 81 | var index = tr.b.findLowIndexInSortedArray( 82 | this.entries_, function(entry) { return entry.address; }, address); 83 | var entry = this.entries_[index]; 84 | if (!entry || entry.address !== address) 85 | return undefined; 86 | 87 | this.entries_.splice(index, 1); 88 | return entry; 89 | }, 90 | 91 | lookupEntry: function(address) { 92 | var index = tr.b.findHighIndexInSortedArray( 93 | this.entries_, function(e) { return address - e.address; }) - 1; 94 | var entry = this.entries_[index]; 95 | return entry && 96 | address < entry.address + entry.size ? entry : undefined; 97 | }, 98 | 99 | addEntry: function(newEntry) { 100 | // findLowIndexInSortedArray returns 1 for empty list. Just push the 101 | // new address as it's the only item. 102 | if (this.entries_.length === 0) 103 | this.entries_.push(newEntry); 104 | 105 | var endAddress = newEntry.address + newEntry.size; 106 | var lastIndex = tr.b.findLowIndexInSortedArray( 107 | this.entries_, function(entry) { return entry.address; }, endAddress); 108 | var index; 109 | for (index = lastIndex - 1; index >= 0; --index) { 110 | var entry = this.entries_[index]; 111 | var entryEndAddress = entry.address + entry.size; 112 | if (entryEndAddress <= newEntry.address) 113 | break; 114 | } 115 | ++index; 116 | this.entries_.splice(index, lastIndex - index, newEntry); 117 | } 118 | }; 119 | 120 | return { 121 | TraceCodeMap: TraceCodeMap 122 | }; 123 | }); 124 | 125 | -------------------------------------------------------------------------------- /lib/third_party/tracing/extras/importer/linux_perf/exynos_parser.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("./parser.js"); 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * @fileoverview Parses exynos events in the Linux event trace format. 13 | */ 14 | global.tr.exportTo('tr.e.importer.linux_perf', function() { 15 | 16 | var ColorScheme = tr.b.ColorScheme; 17 | var Parser = tr.e.importer.linux_perf.Parser; 18 | 19 | /** 20 | * Parses linux exynos trace events. 21 | * @constructor 22 | */ 23 | function ExynosParser(importer) { 24 | Parser.call(this, importer); 25 | 26 | importer.registerEventHandler('exynos_busfreq_target_int', 27 | ExynosParser.prototype.busfreqTargetIntEvent.bind(this)); 28 | importer.registerEventHandler('exynos_busfreq_target_mif', 29 | ExynosParser.prototype.busfreqTargetMifEvent.bind(this)); 30 | 31 | importer.registerEventHandler('exynos_page_flip_state', 32 | ExynosParser.prototype.pageFlipStateEvent.bind(this)); 33 | } 34 | 35 | ExynosParser.prototype = { 36 | __proto__: Parser.prototype, 37 | 38 | exynosBusfreqSample: function(name, ts, frequency) { 39 | var targetCpu = this.importer.getOrCreateCpu(0); 40 | var counter = targetCpu.getOrCreateCounter('', name); 41 | if (counter.numSeries === 0) { 42 | counter.addSeries(new tr.model.CounterSeries('frequency', 43 | ColorScheme.getColorIdForGeneralPurposeString( 44 | counter.name + '.' + 'frequency'))); 45 | } 46 | counter.series.forEach(function(series) { 47 | series.addCounterSample(ts, frequency); 48 | }); 49 | }, 50 | 51 | /** 52 | * Parses exynos_busfreq_target_int events and sets up state. 53 | */ 54 | busfreqTargetIntEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 55 | var event = /frequency=(\d+)/.exec(eventBase.details); 56 | if (!event) 57 | return false; 58 | 59 | this.exynosBusfreqSample('INT Frequency', ts, parseInt(event[1])); 60 | return true; 61 | }, 62 | 63 | /** 64 | * Parses exynos_busfreq_target_mif events and sets up state. 65 | */ 66 | busfreqTargetMifEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 67 | var event = /frequency=(\d+)/.exec(eventBase.details); 68 | if (!event) 69 | return false; 70 | 71 | this.exynosBusfreqSample('MIF Frequency', ts, parseInt(event[1])); 72 | return true; 73 | }, 74 | 75 | exynosPageFlipStateOpenSlice: function(ts, pipe, fb, state) { 76 | var kthread = this.importer.getOrCreatePseudoThread( 77 | 'exynos_flip_state (pipe:' + pipe + ', fb:' + fb + ')'); 78 | kthread.openSliceTS = ts; 79 | kthread.openSlice = state; 80 | }, 81 | 82 | exynosPageFlipStateCloseSlice: function(ts, pipe, fb, args) { 83 | var kthread = this.importer.getOrCreatePseudoThread( 84 | 'exynos_flip_state (pipe:' + pipe + ', fb:' + fb + ')'); 85 | if (kthread.openSlice) { 86 | var slice = new tr.model.Slice('', kthread.openSlice, 87 | ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice), 88 | kthread.openSliceTS, 89 | args, 90 | ts - kthread.openSliceTS); 91 | kthread.thread.sliceGroup.pushSlice(slice); 92 | } 93 | kthread.openSlice = undefined; 94 | }, 95 | 96 | /** 97 | * Parses page_flip_state events and sets up state in the importer. 98 | */ 99 | pageFlipStateEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 100 | var event = /pipe=(\d+), fb=(\d+), state=(.*)/.exec(eventBase.details); 101 | if (!event) 102 | return false; 103 | 104 | var pipe = parseInt(event[1]); 105 | var fb = parseInt(event[2]); 106 | var state = event[3]; 107 | 108 | this.exynosPageFlipStateCloseSlice(ts, pipe, fb, 109 | { 110 | pipe: pipe, 111 | fb: fb 112 | }); 113 | if (state !== 'flipped') 114 | this.exynosPageFlipStateOpenSlice(ts, pipe, fb, state); 115 | return true; 116 | } 117 | }; 118 | 119 | Parser.register(ExynosParser); 120 | 121 | return { 122 | ExynosParser: ExynosParser 123 | }; 124 | }); 125 | -------------------------------------------------------------------------------- /lib/third_party/tracing/model/async_slice.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright (c) 2013 The Chromium Authors. All rights reserved. 3 | Use of this source code is governed by a BSD-style license that can be 4 | found in the LICENSE file. 5 | **/ 6 | 7 | require("../base/extension_registry.js"); 8 | require("../base/units/time_stamp.js"); 9 | require("./timed_event.js"); 10 | 11 | 'use strict'; 12 | 13 | /** 14 | * @fileoverview Provides the AsyncSlice class. 15 | */ 16 | global.tr.exportTo('tr.model', function() { 17 | /** 18 | * A AsyncSlice represents an interval of time during which an 19 | * asynchronous operation is in progress. An AsyncSlice consumes no CPU time 20 | * itself and so is only associated with Threads at its start and end point. 21 | * 22 | * @constructor 23 | */ 24 | function AsyncSlice(category, title, colorId, start, args, duration, 25 | opt_isTopLevel, opt_cpuStart, opt_cpuDuration, 26 | opt_argsStripped) { 27 | tr.model.TimedEvent.call(this, start); 28 | 29 | this.category = category || ''; 30 | // We keep the original title from the trace file in originalTitle since 31 | // some sub-classes, e.g. NetAsyncSlice, change the title field. 32 | this.originalTitle = title; 33 | this.title = title; 34 | this.colorId = colorId; 35 | this.args = args; 36 | this.startStackFrame = undefined; 37 | this.endStackFrame = undefined; 38 | this.didNotFinish = false; 39 | this.important = false; 40 | this.subSlices = []; 41 | this.parentContainer = undefined; 42 | 43 | this.id = undefined; 44 | this.startThread = undefined; 45 | this.endThread = undefined; 46 | this.cpuStart = undefined; 47 | this.cpuDuration = undefined; 48 | this.argsStripped = false; 49 | 50 | this.startStackFrame = undefined; 51 | this.endStackFrame = undefined; 52 | 53 | this.duration = duration; 54 | 55 | 56 | // TODO(nduca): Forgive me for what I must do. 57 | this.isTopLevel = (opt_isTopLevel === true); 58 | 59 | if (opt_cpuStart !== undefined) 60 | this.cpuStart = opt_cpuStart; 61 | 62 | if (opt_cpuDuration !== undefined) 63 | this.cpuDuration = opt_cpuDuration; 64 | 65 | if (opt_argsStripped !== undefined) 66 | this.argsStripped = opt_argsStripped; 67 | }; 68 | 69 | AsyncSlice.prototype = { 70 | __proto__: tr.model.TimedEvent.prototype, 71 | 72 | get analysisTypeName() { 73 | return this.title; 74 | }, 75 | 76 | get viewSubGroupTitle() { 77 | return this.title; 78 | }, 79 | 80 | get userFriendlyName() { 81 | return 'Async slice ' + this.title + ' at ' + 82 | tr.b.u.TimeStamp.format(this.start); 83 | }, 84 | 85 | get stableId() { 86 | var parentAsyncSliceGroup = this.parentContainer.asyncSliceGroup; 87 | return parentAsyncSliceGroup.stableId + '.' + 88 | parentAsyncSliceGroup.slices.indexOf(this); 89 | }, 90 | 91 | findDescendentSlice: function(targetTitle) { 92 | if (!this.subSlices) 93 | return undefined; 94 | 95 | for (var i = 0; i < this.subSlices.length; i++) { 96 | if (this.subSlices[i].title == targetTitle) 97 | return this.subSlices[i]; 98 | var slice = this.subSlices[i].findDescendentSlice(targetTitle); 99 | if (slice) return slice; 100 | } 101 | return undefined; 102 | }, 103 | 104 | iterateAllDescendents: function(callback, opt_this) { 105 | this.subSlices.forEach(callback, opt_this); 106 | this.subSlices.forEach(function(subSlice) { 107 | subSlice.iterateAllDescendents(callback, opt_this); 108 | }, opt_this); 109 | }, 110 | 111 | compareTo: function(that) { 112 | return this.title.localeCompare(that.title); 113 | } 114 | }; 115 | 116 | tr.model.EventRegistry.register( 117 | AsyncSlice, 118 | { 119 | name: 'asyncSlice', 120 | pluralName: 'asyncSlices', 121 | singleViewElementName: 'tr-ui-a-single-async-slice-sub-view', 122 | multiViewElementName: 'tr-ui-a-multi-async-slice-sub-view' 123 | }); 124 | 125 | 126 | var options = new tr.b.ExtensionRegistryOptions( 127 | tr.b.TYPE_BASED_REGISTRY_MODE); 128 | options.mandatoryBaseClass = AsyncSlice; 129 | options.defaultConstructor = AsyncSlice; 130 | tr.b.decorateExtensionRegistry(AsyncSlice, options); 131 | 132 | return { 133 | AsyncSlice: AsyncSlice 134 | }; 135 | }); 136 | --------------------------------------------------------------------------------