ui: Add callstack sampling flamegraph behind flag
Bug: 195934783
Change-Id: I7b1a38ea7fba379e189f1464f2ed16804033a354
diff --git a/ui/src/controller/heap_profile_controller.ts b/ui/src/controller/heap_profile_controller.ts
index 8ec8e34..ef9df65 100644
--- a/ui/src/controller/heap_profile_controller.ts
+++ b/ui/src/controller/heap_profile_controller.ts
@@ -21,6 +21,7 @@
mergeCallsites,
OBJECTS_ALLOCATED_KEY,
OBJECTS_ALLOCATED_NOT_FREED_KEY,
+ PERF_SAMPLES_KEY,
SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY
} from '../common/flamegraph_util';
import {NUM, STR} from '../common/query_result';
@@ -236,13 +237,6 @@
// Alternatively consider collapsing frames of the same label.
const maxDepth = 100;
switch (viewingOption) {
- case SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY:
- orderBy = `where cumulative_size > 0 and depth < ${
- maxDepth} order by depth, parent_id,
- cumulative_size desc, name`;
- totalColumnName = 'cumulativeSize';
- selfColumnName = 'size';
- break;
case ALLOC_SPACE_MEMORY_ALLOCATED_KEY:
orderBy = `where cumulative_alloc_size > 0 and depth < ${
maxDepth} order by depth, parent_id,
@@ -264,6 +258,14 @@
totalColumnName = 'cumulativeAllocCount';
selfColumnName = 'count';
break;
+ case PERF_SAMPLES_KEY:
+ case SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY:
+ orderBy = `where cumulative_size > 0 and depth < ${
+ maxDepth} order by depth, parent_id,
+ cumulative_size desc, name`;
+ totalColumnName = 'cumulativeSize';
+ selfColumnName = 'size';
+ break;
default:
break;
}
@@ -285,7 +287,7 @@
IFNULL(line_number, -1) as lineNumber
from ${tableName} ${orderBy}`);
- const flamegraphData: CallsiteInfo[] = new Array();
+ const flamegraphData: CallsiteInfo[] = [];
const hashToindex: Map<number, number> = new Map();
const it = callsites.iter({
hash: NUM,
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index fefb2ae..bcb2b4c 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -21,6 +21,7 @@
import {TRACE_MARGIN_TIME_S} from '../common/constants';
import {Engine} from '../common/engine';
import {featureFlags, Flag} from '../common/feature_flags';
+import {PERF_SAMPLES_KEY} from '../common/flamegraph_util';
import {HttpRpcEngine} from '../common/http_rpc_engine';
import {NUM, NUM_NULL, QueryError, STR, STR_NULL} from '../common/query_result';
import {EngineMode} from '../common/state';
@@ -116,6 +117,12 @@
return [flag, m];
});
+const PERF_SAMPLE_FLAG = featureFlags.register({
+ id: 'perfSampleFlamegraph',
+ name: 'Perf Sample Flamegraph',
+ description: 'Show flamegraph generated by a perf sample.',
+ defaultValue: false
+});
// TraceController handles handshakes with the frontend for everything that
// concerns a single trace. It owns the WASM trace processor engine, handles
@@ -391,11 +398,29 @@
globals.dispatch(Actions.removeDebugTrack({}));
globals.dispatch(Actions.sortThreadTracks({}));
+
await this.selectFirstHeapProfile();
+ if (PERF_SAMPLE_FLAG.get()) {
+ await this.selectPerfSample();
+ }
return engineMode;
}
+ private async selectPerfSample() {
+ const query = `select ts, upid
+ from perf_sample
+ join thread using (utid)
+ order by ts desc limit 1`;
+ const profile = await assertExists(this.engine).query(query);
+ if (profile.numRows() !== 1) return;
+ const row = profile.firstRow({ts: NUM, upid: NUM});
+ const ts = row.ts;
+ const upid = row.upid;
+ globals.dispatch(Actions.selectHeapProfile(
+ {id: 0, upid, ts, type: 'perf', viewingOption: PERF_SAMPLES_KEY}));
+ }
+
private async selectFirstHeapProfile() {
const query = `select * from
(select distinct(ts) as ts, 'native' as type,