in frontend/app/components/memory_profile/memory_timeline_graph/memory_timeline_graph.ts [44:158]
drawChart() {
if (!this.chartRef || !this.chart || this.memoryId === '' ||
!this.memoryProfileProtoOrNull ||
!this.memoryProfileProtoOrNull.memoryProfilePerAllocator) {
return;
}
this.width =
Math.min(MAX_CHART_WIDTH, this.chartRef.nativeElement.offsetWidth);
const snapshots =
this.memoryProfileProtoOrNull.memoryProfilePerAllocator[this.memoryId]
.memoryProfileSnapshots;
if (!snapshots) return;
snapshots.sort((a, b) => Number(a.timeOffsetPs) - Number(b.timeOffsetPs));
// CPU allocator does not provide the free memory bytes stats, in this case,
// do not display the free memory line in timeline graph.
let hasFreeMemoryData = false;
for (let i = 0; i < snapshots.length; i++) {
const stats = snapshots[i].aggregationStats;
if (stats && stats.freeMemoryBytes !== '0') {
hasFreeMemoryData = true;
break;
}
}
const dataTable = new google.visualization.DataTable();
dataTable.addColumn('number', 'timestamp(ps)');
dataTable.addColumn('number', 'stack');
dataTable.addColumn('number', 'heap');
dataTable.addColumn({type: 'string', role: 'tooltip'});
if (hasFreeMemoryData) {
dataTable.addColumn('number', 'free');
}
dataTable.addColumn('number', 'fragmentation');
for (let i = 0; i < snapshots.length; i++) {
const stats = snapshots[i].aggregationStats;
if (!stats || !snapshots[i].timeOffsetPs) {
continue;
}
const row = [
this.picoToMilli(snapshots[i].timeOffsetPs),
this.bytesToGiBs(stats.stackReservedBytes),
this.bytesToGiBs(stats.heapAllocatedBytes),
this.getMetadataTooltip(snapshots[i])
];
if (hasFreeMemoryData) {
row.push(this.bytesToGiBs(stats.freeMemoryBytes));
}
row.push((stats.fragmentation || 0) * 100);
dataTable.addRow(row);
}
const fragmentationProperty = {
'targetAxisIndex': 1, // Using string parameter to prevent renaming.
type: 'line',
lineDashStyle: [4, 4],
};
const lineProperty = {'targetAxisIndex': 0};
const seriesWithFreeMemory = {
0: lineProperty,
1: lineProperty,
2: lineProperty,
3: fragmentationProperty,
};
const seriesWithoutFreeMemory = {
0: lineProperty,
1: lineProperty,
2: fragmentationProperty,
};
const options = {
curveType: 'none',
chartArea: {left: 60, right: 60, width: '100%'},
hAxis: {
title: 'Timestamp (ms)',
textStyle: {bold: true},
},
vAxes: {
0: {
title: 'Memory Usage (GiBs)',
minValue: 0,
textStyle: {bold: true},
},
1: {
title: 'Fragmentation (%)',
minValue: 0,
maxValue: 100,
textStyle: {bold: true},
},
},
series: hasFreeMemoryData ? seriesWithFreeMemory :
seriesWithoutFreeMemory,
// tslint:disable-next-line:no-any
legend: {position: 'top' as any},
tooltip: {
trigger: 'selection',
},
colors: ['red', 'orange', 'green'],
height: this.height,
isStacked: true,
explorer: {
actions: ['dragToZoom', 'rightClickToReset'],
maxZoomIn: .001,
maxZoomOut: 10,
},
};
this.chart.draw(
dataTable, options as google.visualization.AreaChartOptions);
}