Commit 9b250cb6 authored by Zachary Anderson's avatar Zachary Anderson Committed by GitHub

[fuchsia_reload] More information from --list (#9503)

parent 5b02aaab
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:collection';
import 'dart:math'; import 'dart:math';
import '../base/common.dart'; import '../base/common.dart';
...@@ -93,7 +94,7 @@ class FuchsiaReloadCommand extends FlutterCommand { ...@@ -93,7 +94,7 @@ class FuchsiaReloadCommand extends FlutterCommand {
printTrace('Fuchsia service port: $port'); printTrace('Fuchsia service port: $port');
if (_list) { if (_list) {
await _listViews(servicePorts); await _listVMs(servicePorts);
return; return;
} }
...@@ -125,12 +126,23 @@ class FuchsiaReloadCommand extends FlutterCommand { ...@@ -125,12 +126,23 @@ class FuchsiaReloadCommand extends FlutterCommand {
await hotRunner.attach(observatoryUris, isolateFilter: isolateName); await hotRunner.attach(observatoryUris, isolateFilter: isolateName);
} }
Future<List<FlutterView>> _getViews(List<int> ports) async { // A cache of VMService connections.
final List<FlutterView> views = <FlutterView>[]; HashMap<int, VMService> _vmServiceCache = new HashMap<int, VMService>();
for (int port in ports) {
VMService _getVMService(int port) {
if (!_vmServiceCache.containsKey(port)) {
final String addr = 'http://$_address:$port'; final String addr = 'http://$_address:$port';
final Uri uri = Uri.parse(addr); final Uri uri = Uri.parse(addr);
final VMService vmService = VMService.connect(uri); final VMService vmService = VMService.connect(uri);
_vmServiceCache[port] = vmService;
}
return _vmServiceCache[port];
}
Future<List<FlutterView>> _getViews(List<int> ports) async {
final List<FlutterView> views = <FlutterView>[];
for (int port in ports) {
final VMService vmService = _getVMService(port);
await vmService.getVM(); await vmService.getVM();
await vmService.waitForViews(); await vmService.waitForViews();
views.addAll(vmService.vm.views); views.addAll(vmService.vm.views);
...@@ -150,31 +162,89 @@ class FuchsiaReloadCommand extends FlutterCommand { ...@@ -150,31 +162,89 @@ class FuchsiaReloadCommand extends FlutterCommand {
return result; return result;
} }
Future<Null> _listViews(List<int> ports) async { static const String _bold = '\u001B[0;1m';
const String bold = '\u001B[0;1m'; static const String _reset = '\u001B[0m';
const String reset = '\u001B[0m';
for (FlutterView v in await _getViews(ports)) { String _vmServiceToString(VMService vmService, {int tabDepth: 0}) {
final Uri addr = v.owner.vmService.httpAddress; final Uri addr = vmService.httpAddress;
final Isolate i = v.uiIsolate; final int numIsolates = vmService.vm.isolates.length;
final String name = i.name; final String maxRSS = getSizeAsMB(vmService.vm.maxRSS);
final String shortName = name.substring(0, name.indexOf('\$')); final String heapSize = getSizeAsMB(vmService.vm.heapAllocatedMemoryUsage);
final String main = '\$main-'; int totalNewUsed = 0;
final String number = name.substring(name.indexOf(main) + main.length); int totalNewCap = 0;
final String newUsed = getSizeAsMB(i.newSpace.used); int totalOldUsed = 0;
final String newCap = getSizeAsMB(i.newSpace.capacity); int totalOldCap = 0;
final String newFreq = '${i.newSpace.avgCollectionTime.inMilliseconds}ms'; int totalExternal = 0;
final String newPer = '${i.newSpace.avgCollectionPeriod.inSeconds}s'; for (Isolate i in vmService.vm.isolates) {
final String oldUsed = getSizeAsMB(i.oldSpace.used); totalNewUsed += i.newSpace.used;
final String oldCap = getSizeAsMB(i.oldSpace.capacity); totalNewCap += i.newSpace.capacity;
final String oldFreq = '${i.oldSpace.avgCollectionTime.inMilliseconds}ms'; totalOldUsed += i.oldSpace.used;
final String oldPer = '${i.oldSpace.avgCollectionPeriod.inSeconds}s'; totalOldCap += i.oldSpace.capacity;
printStatus( totalExternal += i.newSpace.external;
'$bold$shortName$reset\n' totalExternal += i.oldSpace.external;
'\tIsolate number: $number\n' }
'\tObservatory: $addr\n' final String newUsed = getSizeAsMB(totalNewUsed);
'\tNew gen: $newUsed used of $newCap, GC: $newFreq every $newPer\n' final String newCap = getSizeAsMB(totalNewCap);
'\tOld gen: $oldUsed used of $oldCap, GC: $oldFreq every $oldPer\n' final String oldUsed = getSizeAsMB(totalOldUsed);
); final String oldCap = getSizeAsMB(totalOldCap);
final String external = getSizeAsMB(totalExternal);
final String tabs = '\t' * tabDepth;
final String extraTabs = '\t' * (tabDepth + 1);
final StringBuffer stringBuffer = new StringBuffer(
'$tabs${_bold}VM at $addr$_reset\n'
'${extraTabs}RSS: $maxRSS\n'
'${extraTabs}Native allocations: $heapSize\n'
'${extraTabs}New Spaces: $newUsed of $newCap\n'
'${extraTabs}Old Spaces: $oldUsed of $oldCap\n'
'${extraTabs}External: $external\n'
'${extraTabs}Isolates: $numIsolates\n'
);
for (Isolate isolate in vmService.vm.isolates) {
stringBuffer.write(_isolateToString(isolate, tabDepth: tabDepth + 1));
}
return stringBuffer.toString();
}
String _isolateToString(Isolate isolate, {int tabDepth: 0}) {
final Uri vmServiceAddr = isolate.owner.vmService.httpAddress;
final String name = isolate.name;
final String shortName = name.substring(0, name.indexOf('\$'));
final String main = '\$main-';
final String number = name.substring(name.indexOf(main) + main.length);
// The Observatory requires somewhat non-standard URIs that the Uri class
// can't build for us, so instead we build them by hand.
final String isolateIdQuery = "?isolateId=isolates%2F$number";
final String isolateAddr = "$vmServiceAddr/#/inspect$isolateIdQuery";
final String debuggerAddr = "$vmServiceAddr/#/debugger$isolateIdQuery";
final String newUsed = getSizeAsMB(isolate.newSpace.used);
final String newCap = getSizeAsMB(isolate.newSpace.capacity);
final String newFreq = '${isolate.newSpace.avgCollectionTime.inMilliseconds}ms';
final String newPer = '${isolate.newSpace.avgCollectionPeriod.inSeconds}s';
final String oldUsed = getSizeAsMB(isolate.oldSpace.used);
final String oldCap = getSizeAsMB(isolate.oldSpace.capacity);
final String oldFreq = '${isolate.oldSpace.avgCollectionTime.inMilliseconds}ms';
final String oldPer = '${isolate.oldSpace.avgCollectionPeriod.inSeconds}s';
final String external = getSizeAsMB(isolate.newSpace.external + isolate.oldSpace.external);
final String tabs = '\t' * tabDepth;
final String extraTabs = '\t' * (tabDepth + 1);
return
'$tabs$_bold$shortName$_reset\n'
'${extraTabs}Isolate number: $number\n'
'${extraTabs}Observatory: $isolateAddr\n'
'${extraTabs}Debugger: $debuggerAddr\n'
'${extraTabs}New gen: $newUsed used of $newCap, GC: $newFreq every $newPer\n'
'${extraTabs}Old gen: $oldUsed used of $oldCap, GC: $oldFreq every $oldPer\n'
'${extraTabs}External: $external\n';
}
Future<Null> _listVMs(List<int> ports) async {
for (int port in ports) {
final VMService vmService = _getVMService(port);
await vmService.getVM();
await vmService.waitForViews();
printStatus(_vmServiceToString(vmService));
} }
} }
......
...@@ -512,6 +512,10 @@ class VM extends ServiceObjectOwner { ...@@ -512,6 +512,10 @@ class VM extends ServiceObjectOwner {
// TODO(johnmccutchan): Extract any properties we care about here. // TODO(johnmccutchan): Extract any properties we care about here.
_pid = map['pid']; _pid = map['pid'];
if (map['_heapAllocatedMemoryUsage'] != null) {
_heapAllocatedMemoryUsage = map['_heapAllocatedMemoryUsage'];
}
_maxRSS = map['_maxRSS'];
// Remove any isolates which are now dead from the isolate cache. // Remove any isolates which are now dead from the isolate cache.
_removeDeadIsolates(map['isolates']); _removeDeadIsolates(map['isolates']);
...@@ -528,9 +532,18 @@ class VM extends ServiceObjectOwner { ...@@ -528,9 +532,18 @@ class VM extends ServiceObjectOwner {
/// The pid of the VM's process. /// The pid of the VM's process.
int _pid; int _pid;
int get pid => _pid; int get pid => _pid;
/// The number of bytes allocated (e.g. by malloc) in the native heap.
int _heapAllocatedMemoryUsage;
int get heapAllocatedMemoryUsage {
return _heapAllocatedMemoryUsage == null ? 0 : _heapAllocatedMemoryUsage;
}
/// The peak resident set size for the process.
int _maxRSS;
int get maxRSS => _maxRSS == null ? 0 : _maxRSS;
int _compareIsolates(Isolate a, Isolate b) { int _compareIsolates(Isolate a, Isolate b) {
final DateTime aStart = a.startTime; final DateTime aStart = a.startTime;
final DateTime bStart = b.startTime; final DateTime bStart = b.startTime;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment