Merge "Support new startup tracepoint format"
diff --git a/Android.bp b/Android.bp
index d24098c..3c5e89b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -4204,6 +4204,7 @@
"protos/perfetto/trace/ftrace/net.proto",
"protos/perfetto/trace/ftrace/oom.proto",
"protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/printk.proto",
"protos/perfetto/trace/ftrace/raw_syscalls.proto",
"protos/perfetto/trace/ftrace/regulator.proto",
"protos/perfetto/trace/ftrace/sched.proto",
@@ -4430,6 +4431,7 @@
"protos/perfetto/trace/ftrace/net.proto",
"protos/perfetto/trace/ftrace/oom.proto",
"protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/printk.proto",
"protos/perfetto/trace/ftrace/raw_syscalls.proto",
"protos/perfetto/trace/ftrace/regulator.proto",
"protos/perfetto/trace/ftrace/sched.proto",
@@ -4489,6 +4491,7 @@
"external/perfetto/protos/perfetto/trace/ftrace/net.gen.cc",
"external/perfetto/protos/perfetto/trace/ftrace/oom.gen.cc",
"external/perfetto/protos/perfetto/trace/ftrace/power.gen.cc",
+ "external/perfetto/protos/perfetto/trace/ftrace/printk.gen.cc",
"external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.gen.cc",
"external/perfetto/protos/perfetto/trace/ftrace/regulator.gen.cc",
"external/perfetto/protos/perfetto/trace/ftrace/sched.gen.cc",
@@ -4548,6 +4551,7 @@
"protos/perfetto/trace/ftrace/net.proto",
"protos/perfetto/trace/ftrace/oom.proto",
"protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/printk.proto",
"protos/perfetto/trace/ftrace/raw_syscalls.proto",
"protos/perfetto/trace/ftrace/regulator.proto",
"protos/perfetto/trace/ftrace/sched.proto",
@@ -4607,6 +4611,7 @@
"external/perfetto/protos/perfetto/trace/ftrace/net.gen.h",
"external/perfetto/protos/perfetto/trace/ftrace/oom.gen.h",
"external/perfetto/protos/perfetto/trace/ftrace/power.gen.h",
+ "external/perfetto/protos/perfetto/trace/ftrace/printk.gen.h",
"external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.gen.h",
"external/perfetto/protos/perfetto/trace/ftrace/regulator.gen.h",
"external/perfetto/protos/perfetto/trace/ftrace/sched.gen.h",
@@ -4670,6 +4675,7 @@
"protos/perfetto/trace/ftrace/net.proto",
"protos/perfetto/trace/ftrace/oom.proto",
"protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/printk.proto",
"protos/perfetto/trace/ftrace/raw_syscalls.proto",
"protos/perfetto/trace/ftrace/regulator.proto",
"protos/perfetto/trace/ftrace/sched.proto",
@@ -4728,6 +4734,7 @@
"external/perfetto/protos/perfetto/trace/ftrace/net.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/oom.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/power.pb.cc",
+ "external/perfetto/protos/perfetto/trace/ftrace/printk.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/regulator.pb.cc",
"external/perfetto/protos/perfetto/trace/ftrace/sched.pb.cc",
@@ -4787,6 +4794,7 @@
"protos/perfetto/trace/ftrace/net.proto",
"protos/perfetto/trace/ftrace/oom.proto",
"protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/printk.proto",
"protos/perfetto/trace/ftrace/raw_syscalls.proto",
"protos/perfetto/trace/ftrace/regulator.proto",
"protos/perfetto/trace/ftrace/sched.proto",
@@ -4845,6 +4853,7 @@
"external/perfetto/protos/perfetto/trace/ftrace/net.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/oom.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/power.pb.h",
+ "external/perfetto/protos/perfetto/trace/ftrace/printk.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/regulator.pb.h",
"external/perfetto/protos/perfetto/trace/ftrace/sched.pb.h",
@@ -4908,6 +4917,7 @@
"protos/perfetto/trace/ftrace/net.proto",
"protos/perfetto/trace/ftrace/oom.proto",
"protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/printk.proto",
"protos/perfetto/trace/ftrace/raw_syscalls.proto",
"protos/perfetto/trace/ftrace/regulator.proto",
"protos/perfetto/trace/ftrace/sched.proto",
@@ -4967,6 +4977,7 @@
"external/perfetto/protos/perfetto/trace/ftrace/net.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/oom.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/power.pbzero.cc",
+ "external/perfetto/protos/perfetto/trace/ftrace/printk.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/regulator.pbzero.cc",
"external/perfetto/protos/perfetto/trace/ftrace/sched.pbzero.cc",
@@ -5026,6 +5037,7 @@
"protos/perfetto/trace/ftrace/net.proto",
"protos/perfetto/trace/ftrace/oom.proto",
"protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/printk.proto",
"protos/perfetto/trace/ftrace/raw_syscalls.proto",
"protos/perfetto/trace/ftrace/regulator.proto",
"protos/perfetto/trace/ftrace/sched.proto",
@@ -5085,6 +5097,7 @@
"external/perfetto/protos/perfetto/trace/ftrace/net.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/oom.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/power.pbzero.h",
+ "external/perfetto/protos/perfetto/trace/ftrace/printk.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/raw_syscalls.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/regulator.pbzero.h",
"external/perfetto/protos/perfetto/trace/ftrace/sched.pbzero.h",
@@ -9506,6 +9519,7 @@
"protos/perfetto/trace/ftrace/net.proto",
"protos/perfetto/trace/ftrace/oom.proto",
"protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/printk.proto",
"protos/perfetto/trace/ftrace/raw_syscalls.proto",
"protos/perfetto/trace/ftrace/regulator.proto",
"protos/perfetto/trace/ftrace/sched.proto",
diff --git a/BUILD b/BUILD
index 7411995..42b652d 100644
--- a/BUILD
+++ b/BUILD
@@ -2960,6 +2960,7 @@
"protos/perfetto/trace/ftrace/net.proto",
"protos/perfetto/trace/ftrace/oom.proto",
"protos/perfetto/trace/ftrace/power.proto",
+ "protos/perfetto/trace/ftrace/printk.proto",
"protos/perfetto/trace/ftrace/raw_syscalls.proto",
"protos/perfetto/trace/ftrace/regulator.proto",
"protos/perfetto/trace/ftrace/sched.proto",
diff --git a/CHANGELOG b/CHANGELOG
index 955527a..382f468 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -8,6 +8,9 @@
message.
Trace Processor:
* Added prebuilts for mac-arm64.
+ * Changed LIKE comparisions to be case-insenstive. This reverts the change
+ introduced in v22. GLOB should be used where case senstive searches are
+ desired; built-in metrics continue to require the use of GLOB.
* Added an optional dependency from trace processor onto a subset of
sources from llvm-project for function name demangling. Bazel embedders
might need to update their PERFETTO_CONFIG in perfetto_cfg.bzl to opt in
diff --git a/protos/perfetto/trace/ftrace/all_protos.gni b/protos/perfetto/trace/ftrace/all_protos.gni
index 9330b8d..a51a05f 100644
--- a/protos/perfetto/trace/ftrace/all_protos.gni
+++ b/protos/perfetto/trace/ftrace/all_protos.gni
@@ -50,6 +50,7 @@
"net.proto",
"oom.proto",
"power.proto",
+ "printk.proto",
"raw_syscalls.proto",
"regulator.proto",
"sched.proto",
diff --git a/protos/perfetto/trace/ftrace/ftrace_event.proto b/protos/perfetto/trace/ftrace/ftrace_event.proto
index e917203..b58950f 100644
--- a/protos/perfetto/trace/ftrace/ftrace_event.proto
+++ b/protos/perfetto/trace/ftrace/ftrace_event.proto
@@ -50,6 +50,7 @@
import "protos/perfetto/trace/ftrace/net.proto";
import "protos/perfetto/trace/ftrace/oom.proto";
import "protos/perfetto/trace/ftrace/power.proto";
+import "protos/perfetto/trace/ftrace/printk.proto";
import "protos/perfetto/trace/ftrace/raw_syscalls.proto";
import "protos/perfetto/trace/ftrace/regulator.proto";
import "protos/perfetto/trace/ftrace/sched.proto";
@@ -504,5 +505,6 @@
WakeupSourceDeactivateFtraceEvent wakeup_source_deactivate = 405;
UfshcdCommandFtraceEvent ufshcd_command = 406;
UfshcdClkGatingFtraceEvent ufshcd_clk_gating = 407;
+ ConsoleFtraceEvent console = 408;
}
}
diff --git a/protos/perfetto/trace/ftrace/printk.proto b/protos/perfetto/trace/ftrace/printk.proto
new file mode 100644
index 0000000..45261e6
--- /dev/null
+++ b/protos/perfetto/trace/ftrace/printk.proto
@@ -0,0 +1,10 @@
+// Autogenerated by:
+// ../../tools/ftrace_proto_gen/ftrace_proto_gen.cc
+// Do not edit.
+
+syntax = "proto2";
+package perfetto.protos;
+
+message ConsoleFtraceEvent {
+ optional string msg = 1;
+}
diff --git a/protos/perfetto/trace/perfetto_trace.proto b/protos/perfetto/trace/perfetto_trace.proto
index 27c0af2..7bee482 100644
--- a/protos/perfetto/trace/perfetto_trace.proto
+++ b/protos/perfetto/trace/perfetto_trace.proto
@@ -5559,6 +5559,14 @@
// End of protos/perfetto/trace/ftrace/power.proto
+// Begin of protos/perfetto/trace/ftrace/printk.proto
+
+message ConsoleFtraceEvent {
+ optional string msg = 1;
+}
+
+// End of protos/perfetto/trace/ftrace/printk.proto
+
// Begin of protos/perfetto/trace/ftrace/raw_syscalls.proto
message SysEnterFtraceEvent {
@@ -6378,6 +6386,7 @@
WakeupSourceDeactivateFtraceEvent wakeup_source_deactivate = 405;
UfshcdCommandFtraceEvent ufshcd_command = 406;
UfshcdClkGatingFtraceEvent ufshcd_clk_gating = 407;
+ ConsoleFtraceEvent console = 408;
}
}
diff --git a/protos/third_party/chromium/chrome_track_event.proto b/protos/third_party/chromium/chrome_track_event.proto
index c30f4cd..debe2a7 100644
--- a/protos/third_party/chromium/chrome_track_event.proto
+++ b/protos/third_party/chromium/chrome_track_event.proto
@@ -581,6 +581,7 @@
NO_RESPONSE_HEAD = 52;
ACTIVATION_NAVIGATION_DISALLOWED_FOR_BUG_1234857 = 53;
ERROR_DOCUMENT = 54;
+ FENCED_FRAMES_EMBEDDER = 55;
}
optional BackForwardCacheNotRestoredReason
diff --git a/src/trace_processor/importers/ftrace/ftrace_parser.cc b/src/trace_processor/importers/ftrace/ftrace_parser.cc
index f83aede..862f21d 100644
--- a/src/trace_processor/importers/ftrace/ftrace_parser.cc
+++ b/src/trace_processor/importers/ftrace/ftrace_parser.cc
@@ -2020,7 +2020,8 @@
protozero::ConstBytes blob) {
protos::pbzero::UfshcdCommandFtraceEvent::Decoder evt(blob.data, blob.size);
uint32_t num = evt.doorbell() > 0 ?
- static_cast<uint32_t>(PERFETTO_POPCOUNT(evt.doorbell())) : 1;
+ static_cast<uint32_t>(PERFETTO_POPCOUNT(evt.doorbell())) :
+ (evt.str_t() == 1 ? 0 : 1);
TrackId track = context_->track_tracker->InternGlobalCounterTrack(
ufs_command_count_id_);
diff --git a/src/trace_processor/trace_processor_impl.cc b/src/trace_processor/trace_processor_impl.cc
index 9ace9ee..a1660ff 100644
--- a/src/trace_processor/trace_processor_impl.cc
+++ b/src/trace_processor/trace_processor_impl.cc
@@ -108,11 +108,6 @@
if (error) {
PERFETTO_FATAL("Error setting pragma temp_store: %s", error);
}
- sqlite3_exec(db, "PRAGMA case_sensitive_like = 1", 0, 0, &error);
- if (error) {
- PERFETTO_FATAL("Error setting pragma case_sensitive_like: %s", error);
- }
-
sqlite3_str_split_init(db);
// In Android tree builds, we don't have the percentile module.
// Just don't include it.
diff --git a/src/traced/probes/ftrace/event_info.cc b/src/traced/probes/ftrace/event_info.cc
index ae030ab..65012de 100644
--- a/src/traced/probes/ftrace/event_info.cc
+++ b/src/traced/probes/ftrace/event_info.cc
@@ -6648,6 +6648,16 @@
kUnsetFtraceId,
405,
kUnsetSize},
+ {"console",
+ "printk",
+ {
+ {kUnsetOffset, kUnsetSize, FtraceFieldType::kInvalidFtraceFieldType,
+ "msg", 1, ProtoSchemaType::kString,
+ TranslationStrategy::kInvalidTranslationStrategy},
+ },
+ kUnsetFtraceId,
+ 408,
+ kUnsetSize},
{"sys_enter",
"raw_syscalls",
{
diff --git a/tools/ftrace_proto_gen/event_list b/tools/ftrace_proto_gen/event_list
index 11bd455..9189c95 100644
--- a/tools/ftrace_proto_gen/event_list
+++ b/tools/ftrace_proto_gen/event_list
@@ -402,3 +402,4 @@
power/wakeup_source_deactivate
ufs/ufshcd_command
ufs/ufshcd_clk_gating
+printk/console
diff --git a/ui/release/channels.json b/ui/release/channels.json
index bdcd0ce..68d1252 100644
--- a/ui/release/channels.json
+++ b/ui/release/channels.json
@@ -2,7 +2,7 @@
"channels": [
{
"name": "stable",
- "rev": "b574f45ca4f3ae63100c9868a65f9381b0d16c82"
+ "rev": "525b3b84e74e372dd33969edd2f43dbb7080b23c"
},
{
"name": "canary",
diff --git a/ui/src/frontend/base_slice_track.ts b/ui/src/frontend/base_slice_track.ts
index 55eed50..0b11366 100644
--- a/ui/src/frontend/base_slice_track.ts
+++ b/ui/src/frontend/base_slice_track.ts
@@ -109,6 +109,12 @@
private computedSliceHeight = 0;
private computedRowSpacing = 0;
+ // True if this track (and any views tables it might have created) has been
+ // destroyed. This is unfortunately error prone (since we must manually check
+ // this between each query).
+ // TODO(hjd): Replace once we have cancellable query sequences.
+ private isDestroyed = false;
+
// TODO(hjd): Remove when updating selection.
// We shouldn't know here about CHROME_SLICE. Maybe should be set by
// whatever deals with that. Dunno the namespace of selection is weird. For
@@ -357,6 +363,12 @@
} // if (howSlice)
}
+ onDestroy() {
+ super.onDestroy();
+ this.isDestroyed = true;
+ this.engine.query(`DROP VIEW IF EXISTS ${this.tableName}`);
+ }
+
// This method figures out if the visible window is outside the bounds of
// the cached data and if so issues new queries (i.e. sorta subsumes the
// onBoundsChange).
@@ -366,16 +378,14 @@
if (this.sqlState === 'UNINITIALIZED') {
this.sqlState = 'INITIALIZING';
- // TODO(hjd): we need an onDestroy. Right now if you contract and expand a
- // track group this will crash, because the 2nd time we create the track
- // we end up re-issuing the CREATE VIEW table_name.
- // Right now this DROP VIEW is a hack, because it: (1) assumes that
- // tableName is a VIEW and not a TABLE; (2) assume the impl track didn't
- // create any other TABLE/VIEW (which happens to be true right now but
- // might now be in future).
- await this.engine.query(`DROP VIEW IF EXISTS ${this.tableName}`);
+ if (this.isDestroyed) {
+ return;
+ }
await this.initSqlTable(this.tableName);
+ if (this.isDestroyed) {
+ return;
+ }
const queryRes = await this.engine.query(`select
ifnull(max(dur), 0) as maxDur, count(1) as rowCount
from ${this.tableName}`);
@@ -424,6 +434,9 @@
// - Materialize the unfinished slices one off.
// - Avoid the union if we know we don't have any -1 slices.
// - Maybe we don't need the union at all and can deal in TS?
+ if (this.isDestroyed) {
+ return;
+ }
const queryRes = await this.engine.query(`
with q1 as (
select
diff --git a/ui/src/frontend/details_panel.ts b/ui/src/frontend/details_panel.ts
index da5298e..30f536e 100644
--- a/ui/src/frontend/details_panel.ts
+++ b/ui/src/frontend/details_panel.ts
@@ -332,9 +332,10 @@
detailsPanels.push({
key: 'pivot_table_redux',
name: 'Pivot Table',
- vnode:
- m(PivotTableRedux,
- {selectionArea: globals.state.pivotTableRedux.selectionArea})
+ vnode: m(PivotTableRedux, {
+ key: 'pivot_table_redux',
+ selectionArea: globals.state.pivotTableRedux.selectionArea
+ })
});
}
@@ -379,7 +380,7 @@
detailsPanels.push({
key: 'selected_flows',
name: 'Flow Events',
- vnode: m(FlowEventsAreaSelectedPanel)
+ vnode: m(FlowEventsAreaSelectedPanel, {key: 'flow_events_area'})
});
}
diff --git a/ui/src/frontend/panel_container.ts b/ui/src/frontend/panel_container.ts
index 662cd54..2131c10 100644
--- a/ui/src/frontend/panel_container.ts
+++ b/ui/src/frontend/panel_container.ts
@@ -14,7 +14,7 @@
import * as m from 'mithril';
-import {assertExists, assertFalse, assertTrue} from '../base/logging';
+import {assertExists, assertTrue} from '../base/logging';
import {TOPBAR_HEIGHT, TRACK_SHELL_WIDTH} from './css_constants';
import {
@@ -22,7 +22,7 @@
FlowEventsRendererArgs
} from './flow_events_renderer';
import {globals} from './globals';
-import {isPanelVNode, Panel, PanelSize} from './panel';
+import {isPanelVNode, Panel, PanelSize, PanelVNode} from './panel';
import {
debugNow,
perfDebug,
@@ -47,9 +47,8 @@
kind: 'TRACKS'|'OVERVIEW'|'DETAILS';
}
-interface PanelInfo {
- id: string; // Can be == '' for singleton panels.
- vnode: AnyAttrsVnode;
+interface PanelPosition {
+ id: string;
height: number;
width: number;
x: number;
@@ -61,8 +60,7 @@
private parentWidth = 0;
private parentHeight = 0;
private scrollTop = 0;
- private panelInfos: PanelInfo[] = [];
- private panelByKey = new Map<string, AnyAttrsVnode>();
+ private panelPositions: PanelPosition[] = [];
private totalPanelHeight = 0;
private canvasHeight = 0;
@@ -97,13 +95,13 @@
const minY = Math.min(startY, endY);
const maxY = Math.max(startY, endY);
const panels: AnyAttrsVnode[] = [];
- for (let i = 0; i < this.panelInfos.length; i++) {
- const pos = this.panelInfos[i];
+ for (let i = 0; i < this.panelPositions.length; i++) {
+ const pos = this.panelPositions[i];
const realPosX = pos.x - TRACK_SHELL_WIDTH;
if (realPosX + pos.width >= minX && realPosX <= maxX &&
pos.y + pos.height >= minY && pos.y <= maxY &&
- pos.vnode.attrs.selectable) {
- panels.push(pos.vnode);
+ this.attrs.panels[i].attrs.selectable) {
+ panels.push(this.attrs.panels[i]);
}
}
return panels;
@@ -116,14 +114,15 @@
if (area === undefined ||
globals.frontendLocalState.areaY.start === undefined ||
globals.frontendLocalState.areaY.end === undefined ||
- this.panelInfos.length === 0) {
+ this.panelPositions.length === 0) {
return;
}
// Only get panels from the current panel container if the selection began
// in this container.
- const panelContainerTop = this.panelInfos[0].y;
- const panelContainerBottom = this.panelInfos[this.panelInfos.length - 1].y +
- this.panelInfos[this.panelInfos.length - 1].height;
+ const panelContainerTop = this.panelPositions[0].y;
+ const panelContainerBottom =
+ this.panelPositions[this.panelPositions.length - 1].y +
+ this.panelPositions[this.panelPositions.length - 1].height;
if (globals.frontendLocalState.areaY.start + TOPBAR_HEIGHT <
panelContainerTop ||
globals.frontendLocalState.areaY.start + TOPBAR_HEIGHT >
@@ -218,26 +217,18 @@
view({attrs}: m.CVnode<Attrs>) {
this.attrs = attrs;
- this.panelByKey.clear();
- const children = [];
- for (const panel of attrs.panels) {
- const key = assertExists(panel.key) as string;
- assertFalse(this.panelByKey.has(key));
- this.panelByKey.set(key, panel);
- children.push(
- m('.panel',
- {key: panel.key, 'data-key': panel.key},
- perfDebug() ?
- [panel, m('.debug-panel-border', {key: 'debug-panel-border'})] :
- panel));
- }
+ const renderPanel = (panel: m.Vnode) => perfDebug() ?
+ m('.panel',
+ {key: panel.key},
+ [panel, m('.debug-panel-border', {key: 'debug-panel-border'})]) :
+ m('.panel', {key: panel.key}, panel);
return [
m(
'.scroll-limiter',
m('canvas.main-canvas'),
),
- m('.panels', children)
+ m('.panels', attrs.panels.map(renderPanel))
];
}
@@ -310,26 +301,19 @@
*/
private readPanelHeightsFromDom(dom: Element): boolean {
const prevHeight = this.totalPanelHeight;
- this.panelInfos = [];
+ this.panelPositions = [];
this.totalPanelHeight = 0;
- dom.parentElement!.querySelectorAll('.panel').forEach(panel => {
- const key = assertExists(panel.getAttribute('data-key'));
- const vnode = assertExists(this.panelByKey.get(key));
-
- // NOTE: the id can be undefined for singletons like overview timeline.
- const id = vnode.attrs.id || vnode.attrs.trackGroupId || '';
- const rect = panel.getBoundingClientRect();
- this.panelInfos.push({
- id,
- height: rect.height,
- width: rect.width,
- x: rect.x,
- y: rect.y,
- vnode
- });
+ const panels = dom.parentElement!.querySelectorAll('.panel');
+ assertTrue(panels.length === this.attrs.panels.length);
+ for (let i = 0; i < panels.length; i++) {
+ const rect = panels[i].getBoundingClientRect();
+ const id = this.attrs.panels[i].attrs.id ||
+ this.attrs.panels[i].attrs.trackGroupId;
+ this.panelPositions[i] =
+ {id, height: rect.height, width: rect.width, x: rect.x, y: rect.y};
this.totalPanelHeight += rect.height;
- });
+ }
return this.totalPanelHeight !== prevHeight;
}
@@ -348,19 +332,23 @@
this.handleAreaSelection();
let panelYStart = 0;
+ const panels = assertExists(this.attrs).panels;
+ assertTrue(panels.length === this.panelPositions.length);
let totalOnCanvas = 0;
const flowEventsRendererArgs =
new FlowEventsRendererArgs(this.parentWidth, this.canvasHeight);
- for (let i = 0; i < this.panelInfos.length; i++) {
- const panel = this.panelInfos[i].vnode;
- const panelHeight = this.panelInfos[i].height;
+ for (let i = 0; i < panels.length; i++) {
+ const panel = panels[i];
+ const panelHeight = this.panelPositions[i].height;
const yStartOnCanvas = panelYStart - canvasYStart;
if (!isPanelVNode(panel)) {
throw new Error('Vnode passed to panel container is not a panel');
}
- flowEventsRendererArgs.registerPanel(panel, yStartOnCanvas, panelHeight);
+ // TODO(hjd): This cast should be unnecessary given the type guard above.
+ const p = panel as PanelVNode<{}>;
+ flowEventsRendererArgs.registerPanel(p, yStartOnCanvas, panelHeight);
if (!this.overlapsCanvas(yStartOnCanvas, yStartOnCanvas + panelHeight)) {
panelYStart += panelHeight;
@@ -376,9 +364,9 @@
clipRect.rect(0, 0, size.width, size.height);
this.ctx.clip(clipRect);
const beforeRender = debugNow();
- panel.state.renderCanvas(this.ctx, size, panel);
+ p.state.renderCanvas(this.ctx, size, p);
this.updatePanelStats(
- i, panel.state, debugNow() - beforeRender, this.ctx, size);
+ i, p.state, debugNow() - beforeRender, this.ctx, size);
this.ctx.restore();
panelYStart += panelHeight;
}
@@ -387,7 +375,7 @@
this.flowEventsRenderer.render(this.ctx, flowEventsRendererArgs);
// Collect performance as the last thing we do.
const redrawDur = debugNow() - redrawStart;
- this.updatePerfStats(redrawDur, this.panelInfos.length, totalOnCanvas);
+ this.updatePerfStats(redrawDur, panels.length, totalOnCanvas);
}
// The panels each draw on the canvas but some details need to be drawn across
@@ -400,22 +388,24 @@
globals.frontendLocalState.areaY.end === undefined) {
return;
}
- if (this.panelInfos.length === 0 || area.tracks.length === 0) return;
+ if (this.panelPositions.length === 0 || area.tracks.length === 0) return;
// Find the minY and maxY of the selected tracks in this panel container.
- const panelContainerTop = this.panelInfos[0].y;
- const panelContainerBottom = this.panelInfos[this.panelInfos.length - 1].y +
- this.panelInfos[this.panelInfos.length - 1].height;
+ const panelContainerTop = this.panelPositions[0].y;
+ const panelContainerBottom =
+ this.panelPositions[this.panelPositions.length - 1].y +
+ this.panelPositions[this.panelPositions.length - 1].height;
let selectedTracksMinY = panelContainerBottom;
let selectedTracksMaxY = panelContainerTop;
let trackFromCurrentContainerSelected = false;
- for (let i = 0; i < this.panelInfos.length; i++) {
- if (area.tracks.includes(this.panelInfos[i].id)) {
+ for (let i = 0; i < this.panelPositions.length; i++) {
+ if (area.tracks.includes(this.panelPositions[i].id)) {
trackFromCurrentContainerSelected = true;
- selectedTracksMinY = Math.min(selectedTracksMinY, this.panelInfos[i].y);
+ selectedTracksMinY =
+ Math.min(selectedTracksMinY, this.panelPositions[i].y);
selectedTracksMaxY = Math.max(
selectedTracksMaxY,
- this.panelInfos[i].y + this.panelInfos[i].height);
+ this.panelPositions[i].y + this.panelPositions[i].height);
}
}
diff --git a/ui/src/frontend/track.ts b/ui/src/frontend/track.ts
index 5cd1e9b..0c5716a 100644
--- a/ui/src/frontend/track.ts
+++ b/ui/src/frontend/track.ts
@@ -77,6 +77,10 @@
this.lastTrackState = assertExists(globals.state.tracks[this.trackId]);
}
+ // Last call the track will receive. Called just before the last reference to
+ // this object is removed.
+ onDestroy() {}
+
protected abstract renderCanvas(ctx: CanvasRenderingContext2D): void;
protected get trackState(): TrackState {
diff --git a/ui/src/frontend/track_group_panel.ts b/ui/src/frontend/track_group_panel.ts
index e5f6631..7f0b4e9 100644
--- a/ui/src/frontend/track_group_panel.ts
+++ b/ui/src/frontend/track_group_panel.ts
@@ -172,6 +172,13 @@
}
}
+ onremove() {
+ if (this.summaryTrack !== undefined) {
+ this.summaryTrack.onDestroy();
+ this.summaryTrack = undefined;
+ }
+ }
+
highlightIfTrackSelected(ctx: CanvasRenderingContext2D, size: PanelSize) {
const localState = globals.frontendLocalState;
const selection = globals.state.currentSelection;
diff --git a/ui/src/frontend/track_panel.ts b/ui/src/frontend/track_panel.ts
index a916e93..e479628 100644
--- a/ui/src/frontend/track_panel.ts
+++ b/ui/src/frontend/track_panel.ts
@@ -326,6 +326,13 @@
}
}
+ onremove() {
+ if (this.track !== undefined) {
+ this.track.onDestroy();
+ this.track = undefined;
+ }
+ }
+
highlightIfTrackSelected(ctx: CanvasRenderingContext2D, size: PanelSize) {
const localState = globals.frontendLocalState;
const selection = globals.state.currentSelection;