Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed RSS plotting and plotting RasterCache data. #2389

Merged
merged 7 commits into from
Sep 30, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 131 additions & 42 deletions packages/devtools_app/lib/src/memory/memory_chart.dart
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,26 @@ class MemoryChartState extends State<MemoryChart> with AutoDisposeMixin {
chartDatasets[ChartDataSets.externalHeapSet.index] = dataset;
}

// Trace #4 Resident Set Size.
LineDataSet get rssSetTrace => chartDatasets[ChartDataSets.rssSet.index];
set rssSetTrace(LineDataSet dataset) {
chartDatasets[ChartDataSets.rssSet.index] = dataset;
}

// Trace #5 Raster Layer.
LineDataSet get rasterLayerSet =>
chartDatasets[ChartDataSets.rasterLayerSet.index];
set rasterLayerSet(LineDataSet dataset) {
chartDatasets[ChartDataSets.rasterLayerSet.index] = dataset;
}

// Trace #6 Raster Picture.
LineDataSet get rasterPictureSet =>
chartDatasets[ChartDataSets.rasterPictureSet.index];
set rasterPictureSet(LineDataSet dataset) {
chartDatasets[ChartDataSets.rasterPictureSet.index] = dataset;
}

/// Loads all heap samples (live data or offline).
void _processAndUpdate([bool reloadAllData = false]) {
setState(() {
Expand Down Expand Up @@ -680,12 +700,56 @@ class MemoryChartState extends State<MemoryChart> with AutoDisposeMixin {
..setFillColor(externalColor)
..setFillAlpha(190);

// Resident Set Size dataset.
rssSetTrace = LineDataSet(dartChartData.residentSetSize, 'RSS')
..setAxisDependency(AxisDependency.LEFT)
..setColor1(ColorUtils.HOLO_ORANGE_LIGHT)
..setValueTextColor(ColorUtils.HOLO_ORANGE_LIGHT)
..setLineWidth(.5)
..enableDashedLine(5, 5, 0)
..setDrawCircles(false)
..setDrawValues(false)
..setFillAlpha(65)
..setFillColor(ColorUtils.HOLO_ORANGE_LIGHT)
..setDrawCircleHole(false);

// Raster Layer dataset.
rasterLayerSet =
LineDataSet(dartChartData.rasterLayerSetSize, 'RasterLayer')
..setAxisDependency(AxisDependency.LEFT)
..setColor1(ColorUtils.HOLO_GREEN_LIGHT)
..setValueTextColor(ColorUtils.HOLO_GREEN_LIGHT)
..setLineWidth(.5)
..enableDashedLine(5, 5, 0)
..setDrawCircles(false)
..setDrawValues(false)
..setFillAlpha(65)
..setFillColor(ColorUtils.HOLO_GREEN_LIGHT)
..setDrawCircleHole(false);

// Raster Picture dataset.
rasterPictureSet =
LineDataSet(dartChartData.rasterPictureSetSize, 'RasterPicture')
..setAxisDependency(AxisDependency.LEFT)
..setColor1(ColorUtils.HOLO_RED_LIGHT)
..setValueTextColor(ColorUtils.HOLO_RED_LIGHT)
..setLineWidth(.5)
..enableDashedLine(5, 5, 0)
..setDrawCircles(false)
..setDrawValues(false)
..setFillAlpha(65)
..setFillColor(ColorUtils.HOLO_RED_LIGHT)
..setDrawCircleHole(false);

// Create a data object with all the data sets.
dartChartController.data = LineData.fromList(
[
usedHeapSet,
externalMemorySet,
capacityHeapSet,
rssSetTrace,
rasterLayerSet,
rasterPictureSet,
],
);

Expand All @@ -704,6 +768,13 @@ class XAxisFormatter extends ValueFormatter {
}
}

class LegendColor {
LegendColor(this.color, this.dashed);

final Color color;
final bool dashed;
}

typedef SelectionCallback = void Function(int timestamp);

typedef SelectSampleCallback = HeapSample Function(int timestamp);
Expand Down Expand Up @@ -773,6 +844,8 @@ class SelectedDataPoint extends LineChartMarker {
final num heapUsed = values.used.toDouble();
final num external = values.external.toDouble();
final num rss = values.rss.toDouble();
final num rasterLayer = values.rasterCache.layerBytes.toDouble();
final num rasterPicture = values.rasterCache.pictureBytes.toDouble();
final bool isGced = values.isGC;

// Alpha filled stacked:
Expand Down Expand Up @@ -808,7 +881,9 @@ class SelectedDataPoint extends LineChartMarker {
'${_formatter.getFormattedValue1(heapUsed)}\n'
'${_formatter.getFormattedValue1(external)}\n'
'${_formatter.getFormattedValue1(rss)}\n'
'$isGced',
'$isGced\n'
'${_formatter.getFormattedValue1(rasterLayer)}\n'
'${_formatter.getFormattedValue1(rasterPicture)}',
textColor,
fontSize,
)
Expand Down Expand Up @@ -895,19 +970,24 @@ class SelectedDataPoint extends LineChartMarker {
'Used\n'
'External\n'
'RSS\n'
'GC';
'GC\n'
'Raster Layer\n'
'Raster Picture\n';

final int _titlesDartVmLines = _titlesDartVm.split('\n').length;

// These are the alpha blended values.
final List<Color> _dartVMColors = [
final List<LegendColor> _dartVMColors = [
// TODO(terry): Dash crashes Canvas unimplemented in Flutter Web
// use a green color on Web see Flutter issue/49882.
kIsWeb
? const Color(0xff00ff00)
: ColorUtils.GRAY, // Total dashed line (Capacity)
const Color(0xff315a69), // Aqua (Used)
const Color(0xff77aed5), // Light-Blue (External)
// Total dashed line (Capacity))
LegendColor(kIsWeb ? const Color(0xff00ff00) : ColorUtils.GRAY, true),
LegendColor(const Color(0xff315a69), false), // Aqua (Used)
LegendColor(const Color(0xff77aed5), false), // Light-Blue (External)
LegendColor(ColorUtils.HOLO_ORANGE_LIGHT, true), // RSS
LegendColor(ColorUtils.BLACK, false), // RSS
LegendColor(ColorUtils.HOLO_GREEN_LIGHT, true), // Raster Layer
LegendColor(ColorUtils.HOLO_RED_LIGHT, true), // Raster Picture
];

static const _titlesAndroid = 'Time\n'
Expand All @@ -922,22 +1002,20 @@ class SelectedDataPoint extends LineChartMarker {
final int _titlesAndroidLines = _titlesAndroid.split('\n').length;

// These are the alpha blended values.
final List<Color> _androidColors = [
final List<LegendColor> _androidColors = [
// TODO(terry): Dash crashes Canvas unimplemented in Flutter Web
// use a green color on Web see Flutter issue/49882.
terrylucas marked this conversation as resolved.
Show resolved Hide resolved
kIsWeb
? const Color(0xff00ff00)
: ColorUtils.WHITE, // Total dashed line (Total)
const Color(0xff945caf), // Purple-ish (Other)
const Color(0xff6a5caf), // Gray Purple-ish (Code)
const Color(0xff607ebe), // Blue-ish (Native Heap)
const Color(0xff75b479), // Green-ish (Java Heap)
const Color(0xffe1dbea), // White-ish (Stack)
const Color(0xffec935d), // Orangy (Graphics)
// Total dashed line (Total)
LegendColor(kIsWeb ? const Color(0xff00ff00) : ColorUtils.WHITE, true),
LegendColor(const Color(0xff945caf), false), // Purple-ish (Other)
LegendColor(const Color(0xff6a5caf), false), // Gray Purple-ish (Code)
LegendColor(const Color(0xff607ebe), false), // Blue-ish (Native Heap)
LegendColor(const Color(0xff75b479), false), // Green-ish (Java Heap)
LegendColor(const Color(0xffe1dbea), false), // White-ish (Stack)
LegendColor(const Color(0xffec935d), false), // Orangy (Graphics)
];

void _drawColorLegend(
List<Color> colors,
List<LegendColor> colors,
Canvas canvas,
Paint paint,
Offset pos,
Expand All @@ -954,28 +1032,39 @@ class SelectedDataPoint extends LineChartMarker {
final xOffset = pos.dx - swatchXOffset;
var yOffset = pos.dy + swatchYOffset + swatchYHalfOffset; // Dashed line

// Draw the dashed line key.
paint.color = colors[0];
paint.strokeWidth = 2;
paint.style = PaintingStyle.stroke;
var p1 = Offset(xOffset, yOffset);
var p2 = p1.translate(dashDrawWidth, 0);
canvas.drawLine(p1, p2, paint);
p1 = p2.translate(dashSkipWidth, 0);
p2 = p1.translate(dashDrawWidth, 0);
canvas.drawLine(p1, p2, paint);

// Color swatches start vertically after time and dashed line entries.
yOffset = pos.dy + swatchYOffset * 2 + 2;

paint.style = PaintingStyle.fill;
for (var index = 1; index < colors.length; index++) {
paint.color = colors[index];
canvas.drawRect(
Rect.fromLTWH(xOffset, yOffset, swatchWidth, swatchHeight),
paint,
);
yOffset += swatchYOffset;
var firstSwatch = true;
for (var index = 0; index < colors.length; index++) {
final legendColor = colors[index];
if (legendColor.dashed) {
if (index > 0) {
yOffset += swatchYHalfOffset - 2;
}
// Draw the dashed line key.
paint.color = colors[index].color;
paint.strokeWidth = 2;
paint.style = PaintingStyle.stroke;
var p1 = Offset(xOffset, yOffset);
var p2 = p1.translate(dashDrawWidth, 0);
canvas.drawLine(p1, p2, paint);
p1 = p2.translate(dashSkipWidth, 0);
p2 = p1.translate(dashDrawWidth, 0);
canvas.drawLine(p1, p2, paint);
yOffset += swatchYHalfOffset;
} else {
if (firstSwatch) {
// Color swatches start vertically after time and dashed line entries.
yOffset = pos.dy + swatchYOffset * 2 + 2;
firstSwatch = false;
}

paint.style = PaintingStyle.fill;
paint.color = colors[index].color;
canvas.drawRect(
Rect.fromLTWH(xOffset, yOffset, swatchWidth, swatchHeight),
paint,
);
yOffset += swatchXOffset;
}
}
}
}
Expand Down
23 changes: 19 additions & 4 deletions packages/devtools_app/lib/src/memory/memory_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -354,11 +354,15 @@ class MemoryController extends DisposableController
// may not match data collected (based on display interval).
for (var arg in args) {
memoryTimeline.dartChartData.addTraceEntries(
rssValue: arg[MemoryTimeline.rssValueKey],
capacityValue: arg[MemoryTimeline.capcityValueKey],
usedValue: arg[MemoryTimeline.usedValueKey],
externalValue: arg[MemoryTimeline.externalValueKey],
rasterLayerValue: arg[MemoryTimeline.rasterLayerValueKey],
rasterPictureValue: arg[MemoryTimeline.rasterPictureValueKey],
minutesToDisplay: intervalDurationInMs,
);

memoryTimeline.androidChartData.addTraceEntries(
javaValue: arg[MemoryTimeline.javaHeapValueKey],
nativeValue: arg[MemoryTimeline.nativeHeapValueKey],
Expand Down Expand Up @@ -1111,8 +1115,10 @@ enum ChartDataSets {
capacitySet,
// Datapoint entries for each external memory value.
externalHeapSet,
// TODO(terry): Datapoint entries for each RSS value.
// rssSet,
// Datapoint entries for each RSS value.
rssSet,
rasterLayerSet,
rasterPictureSet,
}

/// Prepare data to plot in MPChart.
Expand All @@ -1131,14 +1137,20 @@ class MPChartData {
List<Entry> get used => datasets[ChartDataSets.usedSet.index];
List<Entry> get capacity => datasets[ChartDataSets.capacitySet.index];
List<Entry> get externalHeap => datasets[ChartDataSets.externalHeapSet.index];
// TODO(terry): Implement RSS plotting.
// List<Entry> get rssSet => datasets[ChartDataSets.rssSet.index];
List<Entry> get residentSetSize => datasets[ChartDataSets.rssSet.index];
List<Entry> get rasterLayerSetSize =>
datasets[ChartDataSets.rasterLayerSet.index];
List<Entry> get rasterPictureSetSize =>
datasets[ChartDataSets.rasterPictureSet.index];

/// Add each entry to its corresponding trace.
void addTraceEntries({
Entry rssValue,
Entry capacityValue,
Entry usedValue,
Entry externalValue,
Entry rasterLayerValue,
Entry rasterPictureValue,
int minutesToDisplay,
}) {
if (!_pruning &&
Expand All @@ -1157,6 +1169,9 @@ class MPChartData {
externalHeap.add(externalValue);
used.add(usedValue);
capacity.add(capacityValue);
residentSetSize.add(rssValue);
rasterLayerSetSize.add(rasterLayerValue);
rasterPictureSetSize.add(rasterPictureValue);
}

/// Remove all plotted entries in all traces.
Expand Down
2 changes: 0 additions & 2 deletions packages/devtools_app/lib/src/memory/memory_protocol.dart
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,6 @@ class MemoryTracker {

// Query the engine's rasterCache estimate.
rasterCache = await _fetchRasterCacheInfo();
// TODO(terry): Remove logging, temporarily added for testing.
logger.log('$rasterCache');

// Polls for current RSS size.
_update(await service.getVM(), isolateMemory);
Expand Down
12 changes: 11 additions & 1 deletion packages/devtools_app/lib/src/memory/memory_timeline.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class MemoryTimeline {
static const usedValueKey = 'usedValue';
static const externalValueKey = 'externalValue';
static const rssValueKey = 'rssValue';
static const rasterLayerValueKey = 'rasterLayerValue';
static const rasterPictureValueKey = 'rasterPictureValue';

/// Keys used in a map to store all the MPEngineChart Entries we construct to be plotted,
/// ADB memory info.
Expand Down Expand Up @@ -265,15 +267,21 @@ class MemoryTimeline {
final used = sample.used.toDouble();
final external = sample.external.toDouble();

// TOOD(terry): Need to plot.
final rss = (sample.rss ?? 0).toDouble();

final rasterLayer = sample.rasterCache.layerBytes.toDouble();
final rasterPicture = sample.rasterCache.pictureBytes.toDouble();

final extEntry = Entry(x: timestamp, y: external, icon: dataPointImage);
final usedEntry =
Entry(x: timestamp, y: used + external, icon: dataPointImage);
final capacityEntry =
Entry(x: timestamp, y: capacity, icon: dataPointImage);
final rssEntry = Entry(x: timestamp, y: rss, icon: dataPointImage);
final rasterLayerEntry =
Entry(x: timestamp, y: rasterLayer, icon: dataPointImage);
final rasterPictureEntry =
Entry(x: timestamp, y: rasterPicture, icon: dataPointImage);

// Engine memory values (ADB Android):
final javaHeap = sample.adbMemoryInfo.javaHeap.toDouble();
Expand Down Expand Up @@ -397,6 +405,8 @@ class MemoryTimeline {
usedValueKey: usedEntry,
externalValueKey: extEntry,
rssValueKey: rssEntry,
rasterLayerValueKey: rasterLayerEntry,
rasterPictureValueKey: rasterPictureEntry,
javaHeapValueKey: javaHeapEntry,
nativeHeapValueKey: nativeHeapEntry,
codeValueKey: codeEntry,
Expand Down