Distinguish profile types and show different UI labels for each
This is a source of confusion, so let's make it go away by cleanly
labeling what the users are looking at.
While at it, small refactoring to avoid the stringified type.
Bug: 239044591
Change-Id: Iae46bd593e09429fee6f1bc532b85deffc3f9050
diff --git a/docs/case-studies/memory.md b/docs/case-studies/memory.md
index ce23193..de4e401 100644
--- a/docs/case-studies/memory.md
+++ b/docs/case-studies/memory.md
@@ -353,14 +353,14 @@
The tabs that are available are
-* **space**: how many bytes were allocated but not freed at this callstack the
- moment the dump was created.
-* **alloc\_space**: how many bytes were allocated (including ones freed at the
+* **Unreleased size**: how many bytes were allocated but not freed at this
+ callstack the moment the dump was created.
+* **Total size**: how many bytes were allocated (including ones freed at the
moment of the dump) at this callstack
-* **objects**: how many allocations without matching frees were sampled at this
- callstack.
-* **alloc\_objects**: how many allocations (including ones with matching frees)
- were sampled at this callstack.
+* **Unreleased count**: how many allocations without matching frees were done at
+ this callstack.
+* **Total count**: how many allocations (including ones with matching frees)
+ were done at this callstack.
The default view will show you all allocations that were done while the
profile was running but that weren't freed (the **space** tab).
diff --git a/docs/data-sources/native-heap-profiler.md b/docs/data-sources/native-heap-profiler.md
index 0d9b5b9..720b806 100644
--- a/docs/data-sources/native-heap-profiler.md
+++ b/docs/data-sources/native-heap-profiler.md
@@ -80,13 +80,13 @@
The resulting profile proto contains four views on the data
-* **space**: how many bytes were allocated but not freed at this callstack the
- moment the dump was created.
-* **alloc\_space**: how many bytes were allocated (including ones freed at the
+* **Unreleased size**: how many bytes were allocated but not freed at this
+ callstack the moment the dump was created.
+* **Total size**: how many bytes were allocated (including ones freed at the
moment of the dump) at this callstack
-* **objects**: how many allocations without matching frees were done at this
- callstack.
-* **alloc\_objects**: how many allocations (including ones with matching frees)
+* **Unreleased count**: how many allocations without matching frees were done at
+ this callstack.
+* **Total count**: how many allocations (including ones with matching frees)
were done at this callstack.
_(Googlers: You can also open the gzipped protos using http://pprof/)_
diff --git a/src/trace_processor/dynamic/experimental_flamegraph_generator.cc b/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
index e695c40..a1d7bc6 100644
--- a/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
+++ b/src/trace_processor/dynamic/experimental_flamegraph_generator.cc
@@ -37,7 +37,7 @@
return ExperimentalFlamegraphGenerator::ProfileType::kGraph;
}
if (profile_name == "native") {
- return ExperimentalFlamegraphGenerator::ProfileType::kNative;
+ return ExperimentalFlamegraphGenerator::ProfileType::kHeapProfile;
}
if (profile_name == "perf") {
return ExperimentalFlamegraphGenerator::ProfileType::kPerf;
@@ -335,9 +335,9 @@
if (values.profile_type == ProfileType::kGraph) {
auto* tracker = HeapGraphTracker::GetOrCreate(context_);
table = tracker->BuildFlamegraph(values.ts, *values.upid);
- } else if (values.profile_type == ProfileType::kNative) {
- table = BuildNativeHeapProfileFlamegraph(context_->storage.get(),
- *values.upid, values.ts);
+ } else if (values.profile_type == ProfileType::kHeapProfile) {
+ table = BuildHeapProfileFlamegraph(context_->storage.get(), *values.upid,
+ values.ts);
} else if (values.profile_type == ProfileType::kPerf) {
table = BuildNativeCallStackSamplingFlamegraph(
context_->storage.get(), values.upid, values.upid_group,
diff --git a/src/trace_processor/dynamic/experimental_flamegraph_generator.h b/src/trace_processor/dynamic/experimental_flamegraph_generator.h
index 11e7f3f..20eb20d 100644
--- a/src/trace_processor/dynamic/experimental_flamegraph_generator.h
+++ b/src/trace_processor/dynamic/experimental_flamegraph_generator.h
@@ -28,7 +28,7 @@
class ExperimentalFlamegraphGenerator : public DynamicTableGenerator {
public:
- enum class ProfileType { kGraph, kNative, kPerf };
+ enum class ProfileType { kGraph, kHeapProfile, kPerf };
struct InputValues {
ProfileType profile_type;
diff --git a/src/trace_processor/dynamic/flamegraph_construction_algorithms.cc b/src/trace_processor/dynamic/flamegraph_construction_algorithms.cc
index ec0e5d4..d13a78d 100644
--- a/src/trace_processor/dynamic/flamegraph_construction_algorithms.cc
+++ b/src/trace_processor/dynamic/flamegraph_construction_algorithms.cc
@@ -321,9 +321,9 @@
}
std::unique_ptr<tables::ExperimentalFlamegraphNodesTable>
-BuildNativeHeapProfileFlamegraph(TraceStorage* storage,
- UniquePid upid,
- int64_t timestamp) {
+BuildHeapProfileFlamegraph(TraceStorage* storage,
+ UniquePid upid,
+ int64_t timestamp) {
const tables::HeapProfileAllocationTable& allocation_tbl =
storage->heap_profile_allocation_table();
// PASS OVER ALLOCATIONS:
diff --git a/src/trace_processor/dynamic/flamegraph_construction_algorithms.h b/src/trace_processor/dynamic/flamegraph_construction_algorithms.h
index f8ce87c..bc89145 100644
--- a/src/trace_processor/dynamic/flamegraph_construction_algorithms.h
+++ b/src/trace_processor/dynamic/flamegraph_construction_algorithms.h
@@ -29,9 +29,9 @@
};
std::unique_ptr<tables::ExperimentalFlamegraphNodesTable>
-BuildNativeHeapProfileFlamegraph(TraceStorage* storage,
- UniquePid upid,
- int64_t timestamp);
+BuildHeapProfileFlamegraph(TraceStorage* storage,
+ UniquePid upid,
+ int64_t timestamp);
std::unique_ptr<tables::ExperimentalFlamegraphNodesTable>
BuildNativeCallStackSamplingFlamegraph(
diff --git a/ui/src/common/actions.ts b/ui/src/common/actions.ts
index 75af830..b90055f 100644
--- a/ui/src/common/actions.ts
+++ b/ui/src/common/actions.ts
@@ -23,6 +23,7 @@
columnKey,
TableColumn,
} from '../frontend/pivot_table_redux_types';
+
import {randomColor} from './colorizer';
import {createEmptyState} from './empty_state';
import {DEFAULT_VIEWING_OPTION, PERF_SAMPLES_KEY} from './flamegraph_util';
@@ -38,6 +39,7 @@
OmniboxState,
PivotTableReduxResult,
PrimaryTrackSortKey,
+ ProfileType,
RecordingTarget,
SCROLLING_TRACK_GROUP,
SortDirection,
@@ -666,7 +668,7 @@
selectHeapProfile(
state: StateDraft,
- args: {id: number, upid: number, ts: number, type: string}): void {
+ args: {id: number, upid: number, ts: number, type: ProfileType}): void {
state.currentSelection = {
kind: 'HEAP_PROFILE',
id: args.id,
@@ -685,7 +687,7 @@
selectPerfSamples(
state: StateDraft,
- args: {id: number, upid: number, ts: number, type: string}): void {
+ args: {id: number, upid: number, ts: number, type: ProfileType}): void {
state.currentSelection = {
kind: 'PERF_SAMPLES',
id: args.id,
@@ -706,7 +708,7 @@
upids: number[],
startNs: number,
endNs: number,
- type: string,
+ type: ProfileType,
viewingOption: FlamegraphStateViewingOption
}): void {
state.currentFlamegraphState = {
diff --git a/ui/src/common/actions_unittest.ts b/ui/src/common/actions_unittest.ts
index ebcafc1..26f1e2f 100644
--- a/ui/src/common/actions_unittest.ts
+++ b/ui/src/common/actions_unittest.ts
@@ -27,6 +27,7 @@
import {
InThreadTrackSortKey,
PrimaryTrackSortKey,
+ ProfileType,
SCROLLING_TRACK_GROUP,
State,
TraceUrlSource,
@@ -447,26 +448,24 @@
test('perf samples open flamegraph', () => {
const state = createEmptyState();
- const perfType = 'perf';
const afterSelectingPerf = produce(state, (draft) => {
StateActions.selectPerfSamples(
- draft, {id: 0, upid: 0, ts: 0, type: perfType});
+ draft, {id: 0, upid: 0, ts: 0, type: ProfileType.PERF_SAMPLE});
});
expect(assertExists(afterSelectingPerf.currentFlamegraphState).type)
- .toBe(perfType);
+ .toBe(ProfileType.PERF_SAMPLE);
});
test('heap profile opens flamegraph', () => {
const state = createEmptyState();
- const heapType = 'graph';
const afterSelectingPerf = produce(state, (draft) => {
StateActions.selectHeapProfile(
- draft, {id: 0, upid: 0, ts: 0, type: heapType});
+ draft, {id: 0, upid: 0, ts: 0, type: ProfileType.JAVA_HEAP_GRAPH});
});
expect(assertExists(afterSelectingPerf.currentFlamegraphState).type)
- .toBe(heapType);
+ .toBe(ProfileType.JAVA_HEAP_GRAPH);
});
diff --git a/ui/src/common/state.ts b/ui/src/common/state.ts
index 7c32a9f..bfaa40f 100644
--- a/ui/src/common/state.ts
+++ b/ui/src/common/state.ts
@@ -148,6 +148,14 @@
}
}
+export enum ProfileType {
+ HEAP_PROFILE = 'heap_profile',
+ NATIVE_HEAP_PROFILE = 'heap_profile:libc.malloc',
+ JAVA_HEAP_PROFILE = 'heap_profile:com.android.art',
+ JAVA_HEAP_GRAPH = 'graph',
+ PERF_SAMPLE = 'perf',
+}
+
export type FlamegraphStateViewingOption =
'SPACE'|'ALLOC_SPACE'|'OBJECTS'|'ALLOC_OBJECTS'|'PERF_SAMPLES';
@@ -295,7 +303,7 @@
id: number;
upid: number;
ts: number;
- type: string;
+ type: ProfileType;
}
export interface PerfSamplesSelection {
@@ -303,7 +311,7 @@
id: number;
upid: number;
ts: number;
- type: string;
+ type: ProfileType;
}
export interface FlamegraphState {
@@ -311,7 +319,7 @@
upids: number[];
startNs: number;
endNs: number;
- type: string;
+ type: ProfileType;
viewingOption: FlamegraphStateViewingOption;
focusRegex: string;
expandedCallsite?: CallsiteInfo;
diff --git a/ui/src/controller/flamegraph_controller.ts b/ui/src/controller/flamegraph_controller.ts
index 05d680a..bbbecb4 100644
--- a/ui/src/controller/flamegraph_controller.ts
+++ b/ui/src/controller/flamegraph_controller.ts
@@ -26,7 +26,7 @@
SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY,
} from '../common/flamegraph_util';
import {NUM, STR} from '../common/query_result';
-import {CallsiteInfo, FlamegraphState} from '../common/state';
+import {CallsiteInfo, FlamegraphState, ProfileType} from '../common/state';
import {toNs} from '../common/time';
import {
FlamegraphDetails,
@@ -42,6 +42,35 @@
import {Controller} from './controller';
import {globals} from './globals';
+export function profileType(s: string): ProfileType {
+ if (isProfileType(s)) {
+ return s;
+ }
+ if (s.startsWith('heap_profile')) {
+ return ProfileType.HEAP_PROFILE;
+ }
+ throw new Error('Unknown type ${s}');
+}
+
+function isProfileType(s: string): s is ProfileType {
+ return Object.values(ProfileType).includes(s as ProfileType);
+}
+
+function getFlamegraphType(type: ProfileType) {
+ switch (type) {
+ case ProfileType.HEAP_PROFILE:
+ case ProfileType.NATIVE_HEAP_PROFILE:
+ case ProfileType.JAVA_HEAP_PROFILE:
+ return 'native';
+ case ProfileType.JAVA_HEAP_GRAPH:
+ return 'graph';
+ case ProfileType.PERF_SAMPLE:
+ return 'perf';
+ default:
+ throw new Error(`Unexpected profile type ${profileType}`);
+ }
+}
+
export interface FlamegraphControllerArgs {
engine: Engine;
}
@@ -122,7 +151,7 @@
upids,
startNs: toNs(area.startSec),
endNs: toNs(area.endSec),
- type: 'perf',
+ type: ProfileType.PERF_SAMPLE,
viewingOption: PERF_SAMPLES_KEY,
}));
}
@@ -243,7 +272,7 @@
async getFlamegraphData(
baseKey: string, viewingOption: string, startNs: number, endNs: number,
- upids: number[], type: string,
+ upids: number[], type: ProfileType,
focusRegex: string): Promise<CallsiteInfo[]> {
let currentData: CallsiteInfo[];
const key = `${baseKey}-${viewingOption}`;
@@ -388,7 +417,7 @@
}
private async prepareViewsAndTables(
- startNs: number, endNs: number, upids: number[], type: string,
+ startNs: number, endNs: number, upids: number[], type: ProfileType,
focusRegex: string): Promise<string> {
// Creating unique names for views so we can reuse and not delete them
// for each marker.
@@ -396,11 +425,12 @@
if (focusRegex !== '') {
focusRegexConditional = `and focus_str = '${focusRegex}'`;
}
+ const flamegraphType = getFlamegraphType(type);
/*
* TODO(octaviant) this branching should be eliminated for simplicity.
*/
- if (type === 'perf') {
+ if (type === ProfileType.PERF_SAMPLE) {
let upidConditional = `upid = ${upids[0]}`;
if (upids.length > 1) {
upidConditional =
@@ -411,8 +441,8 @@
cumulative_alloc_size, cumulative_count, cumulative_alloc_count,
size, alloc_size, count, alloc_count, source_file, line_number
from experimental_flamegraph
- where profile_type = '${type}' and ${startNs} <= ts and ts <= ${
- endNs} and ${upidConditional}
+ where profile_type = '${flamegraphType}' and ${startNs} <= ts and
+ ts <= ${endNs} and ${upidConditional}
${focusRegexConditional}`);
}
return this.cache.getTableName(
@@ -420,7 +450,7 @@
cumulative_alloc_size, cumulative_count, cumulative_alloc_count,
size, alloc_size, count, alloc_count, source_file, line_number
from experimental_flamegraph
- where profile_type = '${type}'
+ where profile_type = '${flamegraphType}'
and ts = ${endNs}
and upid = ${upids[0]}
${focusRegexConditional}`);
@@ -439,7 +469,7 @@
}
async getFlamegraphMetadata(
- type: string, startNs: number, endNs: number, upids: number[]) {
+ type: ProfileType, startNs: number, endNs: number, upids: number[]) {
// Don't do anything if selection of the marker stayed the same.
if ((this.lastSelectedFlamegraphState !== undefined &&
((this.lastSelectedFlamegraphState.startNs === startNs &&
diff --git a/ui/src/controller/trace_controller.ts b/ui/src/controller/trace_controller.ts
index e3ad2fe..513c5f4 100644
--- a/ui/src/controller/trace_controller.ts
+++ b/ui/src/controller/trace_controller.ts
@@ -23,7 +23,7 @@
import {featureFlags, Flag, PERF_SAMPLE_FLAG} from '../common/feature_flags';
import {HttpRpcEngine} from '../common/http_rpc_engine';
import {NUM, NUM_NULL, QueryError, STR, STR_NULL} from '../common/query_result';
-import {defaultTraceTime, EngineMode} from '../common/state';
+import {defaultTraceTime, EngineMode, ProfileType} from '../common/state';
import {TimeSpan, toNs, toNsCeil, toNsFloor} from '../common/time';
import {resetEngineWorker, WasmEngineProxy} from '../common/wasm_engine_proxy';
import {
@@ -65,6 +65,7 @@
import {
FlamegraphController,
FlamegraphControllerArgs,
+ profileType,
} from './flamegraph_controller';
import {
FlowEventsController,
@@ -437,22 +438,27 @@
const row = profile.firstRow({ts: NUM, upid: NUM});
const ts = row.ts;
const upid = row.upid;
- globals.dispatch(
- Actions.selectPerfSamples({id: 0, upid, ts, type: 'perf'}));
+ globals.dispatch(Actions.selectPerfSamples(
+ {id: 0, upid, ts, type: ProfileType.PERF_SAMPLE}));
}
private async selectFirstHeapProfile() {
- const query = `select * from
- (select distinct(ts) as ts, 'native' as type,
- upid from heap_profile_allocation
- union
- select distinct(graph_sample_ts) as ts, 'graph' as type, upid from
- heap_graph_object) order by ts limit 1`;
+ const query = `select * from (
+ select
+ min(ts) AS ts,
+ 'heap_profile:' || group_concat(distinct heap_name) AS type,
+ upid
+ from heap_profile_allocation
+ group by upid
+ union
+ select distinct graph_sample_ts as ts, 'graph' as type, upid
+ from heap_graph_object)
+ order by ts limit 1`;
const profile = await assertExists(this.engine).query(query);
if (profile.numRows() !== 1) return;
const row = profile.firstRow({ts: NUM, type: STR, upid: NUM});
const ts = row.ts;
- const type = row.type;
+ const type = profileType(row.type);
const upid = row.upid;
globals.dispatch(Actions.selectHeapProfile({id: 0, upid, ts, type}));
}
diff --git a/ui/src/frontend/flamegraph_panel.ts b/ui/src/frontend/flamegraph_panel.ts
index 5958cdd..cadee12 100644
--- a/ui/src/frontend/flamegraph_panel.ts
+++ b/ui/src/frontend/flamegraph_panel.ts
@@ -23,8 +23,13 @@
PERF_SAMPLES_KEY,
SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY,
} from '../common/flamegraph_util';
-import {CallsiteInfo, FlamegraphStateViewingOption} from '../common/state';
+import {
+ CallsiteInfo,
+ FlamegraphStateViewingOption,
+ ProfileType,
+} from '../common/state';
import {timeToCode} from '../common/time';
+import {profileType} from '../controller/flamegraph_controller';
import {PerfettoMouseEvent} from './events';
import {Flamegraph, NodeRendering} from './flamegraph';
@@ -40,23 +45,6 @@
const HEADER_HEIGHT = 30;
-enum ProfileType {
- NATIVE_HEAP_PROFILE = 'native',
- JAVA_HEAP_GRAPH = 'graph',
- PERF_SAMPLE = 'perf'
-}
-
-function isProfileType(s: string): s is ProfileType {
- return Object.values(ProfileType).includes(s as ProfileType);
-}
-
-function toProfileType(s: string): ProfileType {
- if (!isProfileType(s)) {
- throw new Error('Unknown type ${s}');
- }
- return s;
-}
-
function toSelectedCallsite(c: CallsiteInfo|undefined): string {
if (c !== undefined && c.name !== undefined) {
return c.name;
@@ -90,7 +78,7 @@
flamegraphDetails.durNs !== undefined &&
flamegraphDetails.pids !== undefined &&
flamegraphDetails.upids !== undefined) {
- this.profileType = toProfileType(flamegraphDetails.type);
+ this.profileType = profileType(flamegraphDetails.type);
this.ts = flamegraphDetails.durNs;
this.pids = flamegraphDetails.pids;
if (flamegraphDetails.flamegraph) {
@@ -197,10 +185,14 @@
private getTitle(): string {
switch (this.profileType!) {
+ case ProfileType.HEAP_PROFILE:
+ return 'Heap profile:';
case ProfileType.NATIVE_HEAP_PROFILE:
- return 'Heap Profile:';
+ return 'Native heap profile:';
+ case ProfileType.JAVA_HEAP_PROFILE:
+ return 'Java heap profile:';
case ProfileType.JAVA_HEAP_GRAPH:
- return 'Java Heap:';
+ return 'Java heap graph:';
case ProfileType.PERF_SAMPLE:
return 'Profile:';
default:
@@ -220,7 +212,9 @@
} else {
return RENDER_SELF_AND_TOTAL;
}
+ case ProfileType.HEAP_PROFILE:
case ProfileType.NATIVE_HEAP_PROFILE:
+ case ProfileType.JAVA_HEAP_PROFILE:
case ProfileType.PERF_SAMPLE:
return RENDER_SELF_AND_TOTAL;
default:
@@ -293,21 +287,39 @@
private static selectViewingOptions(profileType: ProfileType) {
switch (profileType) {
case ProfileType.PERF_SAMPLE:
- return [this.buildButtonComponent(PERF_SAMPLES_KEY, 'samples')];
+ return [this.buildButtonComponent(PERF_SAMPLES_KEY, 'Samples')];
case ProfileType.JAVA_HEAP_GRAPH:
return [
this.buildButtonComponent(
- SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY, 'space'),
- this.buildButtonComponent(OBJECTS_ALLOCATED_NOT_FREED_KEY, 'objects'),
+ SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY, 'Size'),
+ this.buildButtonComponent(OBJECTS_ALLOCATED_NOT_FREED_KEY, 'Objects'),
+ ];
+ case ProfileType.HEAP_PROFILE:
+ return [
+ this.buildButtonComponent(
+ SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY, 'Unreleased size'),
+ this.buildButtonComponent(OBJECTS_ALLOCATED_NOT_FREED_KEY, 'Count'),
+ this.buildButtonComponent(
+ ALLOC_SPACE_MEMORY_ALLOCATED_KEY, 'Total size'),
+ this.buildButtonComponent(OBJECTS_ALLOCATED_KEY, 'Total count'),
];
case ProfileType.NATIVE_HEAP_PROFILE:
return [
this.buildButtonComponent(
- SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY, 'space'),
- this.buildButtonComponent(OBJECTS_ALLOCATED_NOT_FREED_KEY, 'objects'),
+ SPACE_MEMORY_ALLOCATED_NOT_FREED_KEY, 'Unreleased malloc size'),
this.buildButtonComponent(
- ALLOC_SPACE_MEMORY_ALLOCATED_KEY, 'alloc space'),
- this.buildButtonComponent(OBJECTS_ALLOCATED_KEY, 'alloc objects'),
+ OBJECTS_ALLOCATED_NOT_FREED_KEY, 'Unreleased malloc count'),
+ this.buildButtonComponent(
+ ALLOC_SPACE_MEMORY_ALLOCATED_KEY, 'Total malloc size'),
+ this.buildButtonComponent(
+ OBJECTS_ALLOCATED_KEY, 'Total malloc count'),
+ ];
+ case ProfileType.JAVA_HEAP_PROFILE:
+ return [
+ this.buildButtonComponent(
+ ALLOC_SPACE_MEMORY_ALLOCATED_KEY, 'Total allocation size'),
+ this.buildButtonComponent(
+ OBJECTS_ALLOCATED_KEY, 'Total allocation count'),
];
default:
throw new Error(`Unexpected profile type ${profileType}`);
diff --git a/ui/src/frontend/globals.ts b/ui/src/frontend/globals.ts
index 76423e9..7bb5ad2 100644
--- a/ui/src/frontend/globals.ts
+++ b/ui/src/frontend/globals.ts
@@ -24,7 +24,7 @@
import {Engine} from '../common/engine';
import {MetricResult} from '../common/metric_data';
import {CurrentSearchResults, SearchSummary} from '../common/search_data';
-import {CallsiteInfo, EngineConfig, State} from '../common/state';
+import {CallsiteInfo, EngineConfig, ProfileType, State} from '../common/state';
import {fromNs, toNs} from '../common/time';
import {Analytics, initAnalytics} from './analytics';
@@ -121,7 +121,7 @@
}
export interface FlamegraphDetails {
- type?: string;
+ type?: ProfileType;
id?: number;
startNs?: number;
durNs?: number;
diff --git a/ui/src/tracks/heap_profile/index.ts b/ui/src/tracks/heap_profile/index.ts
index c0b3b44..b3eb40a 100644
--- a/ui/src/tracks/heap_profile/index.ts
+++ b/ui/src/tracks/heap_profile/index.ts
@@ -12,12 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+import {ProfileType} from 'src/common/state';
+
import {searchSegment} from '../../base/binary_search';
import {Actions} from '../../common/actions';
import {PluginContext} from '../../common/plugin_api';
import {NUM, STR} from '../../common/query_result';
import {fromNs, toNs} from '../../common/time';
import {TrackData} from '../../common/track_data';
+import {profileType} from '../../controller/flamegraph_controller';
import {
TrackController,
} from '../../controller/track_controller';
@@ -30,7 +33,7 @@
export interface Data extends TrackData {
tsStarts: Float64Array;
- types: string[];
+ types: ProfileType[];
}
export interface Config {
@@ -48,17 +51,22 @@
resolution,
length: 0,
tsStarts: new Float64Array(),
- types: new Array<string>(),
+ types: new Array<ProfileType>(),
};
}
const queryRes = await this.query(`
- select * from
- (select distinct(ts) as ts, 'native' as type from heap_profile_allocation
- where upid = ${this.config.upid}
- union
- select distinct(graph_sample_ts) as ts, 'graph' as type from
- heap_graph_object
- where upid = ${this.config.upid}) order by ts`);
+ select * from (
+ select distinct
+ ts,
+ 'heap_profile:' ||
+ (select group_concat(distinct heap_name) from heap_profile_allocation
+ where upid = ${this.config.upid}) AS type
+ from heap_profile_allocation
+ where upid = ${this.config.upid}
+ union
+ select distinct graph_sample_ts as ts, 'graph' as type
+ from heap_graph_object
+ where upid = ${this.config.upid}) order by ts`);
const numRows = queryRes.numRows();
const data: Data = {
start,
@@ -66,13 +74,13 @@
resolution,
length: numRows,
tsStarts: new Float64Array(numRows),
- types: new Array<string>(numRows),
+ types: new Array<ProfileType>(numRows),
};
const it = queryRes.iter({ts: NUM, type: STR});
for (let row = 0; it.valid(); it.next(), row++) {
data.tsStarts[row] = it.ts;
- data.types[row] = it.type;
+ data.types[row] = profileType(it.type);
}
return data;
}
diff --git a/ui/src/tracks/perf_samples_profile/index.ts b/ui/src/tracks/perf_samples_profile/index.ts
index 5e96f71..f3ddd74 100644
--- a/ui/src/tracks/perf_samples_profile/index.ts
+++ b/ui/src/tracks/perf_samples_profile/index.ts
@@ -16,6 +16,7 @@
import {Actions} from '../../common/actions';
import {PluginContext} from '../../common/plugin_api';
import {NUM} from '../../common/query_result';
+import {ProfileType} from '../../common/state';
import {fromNs, toNs} from '../../common/time';
import {TrackData} from '../../common/track_data';
import {
@@ -165,8 +166,12 @@
if (index !== -1) {
const ts = data.tsStartsNs[index];
- globals.makeSelection(Actions.selectPerfSamples(
- {id: index, upid: this.config.upid, ts, type: 'perf'}));
+ globals.makeSelection(Actions.selectPerfSamples({
+ id: index,
+ upid: this.config.upid,
+ ts,
+ type: ProfileType.PERF_SAMPLE,
+ }));
return true;
}
return false;