Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(381)

Unified Diff: pkg/compiler/tool/track_memory.dart

Issue 1384833002: add tool to track memory watermark (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/tool/track_memory.dart
diff --git a/pkg/compiler/tool/track_memory.dart b/pkg/compiler/tool/track_memory.dart
new file mode 100644
index 0000000000000000000000000000000000000000..1442b4dce8429aad8afa036d29d8fbde1b1b563f
--- /dev/null
+++ b/pkg/compiler/tool/track_memory.dart
@@ -0,0 +1,187 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// A script to track the high water-mark of memory usage of an application.
+/// To monitor how much memory dart2js is using, run dart2js as follows:
+///
+/// DART_VM_OPTIONS=--observe dart2js ...
+///
+/// and run this script immediately after.
+library compiler.tool.track_memory;
+
+import 'dart:math' show max;
+import 'dart:io';
+import 'dart:async';
+
+import 'dart:convert';
+
+/// Socket to connect to the vm observatory service.
+WebSocket socket;
+
+main() async {
+ _printHeader();
+ _showProgress(0, 0, 0, 0);
+ try {
+ socket = await WebSocket.connect('ws://localhost:8181/ws');
sra1 2015/10/05 17:04:58 TODO: you might need to change the port if another
Siggi Cherem (dart-lang) 2015/10/05 17:19:44 Done. Just made it an arg which defaults to 8181
+ socket.listen(_handleResponse);
+ await _resumeMainIsolateIfPaused();
+ _streamListen('GC');
+ _streamListen('Isolate');
+ _streamListen('Debug');
+ } on SocketException catch (e) {
+ // TODO(sigmund): add better error messages, maybe option to retry.
+ print('\n${_RED}error${_NONE}: $e');
+ }
+}
+
+/// Internal counter for request ids.
+int _requestId = 0;
+Map _pendingResponses = {};
+
+/// Subscribe to listen to a vm service data stream.
+_streamListen(String streamId) =>
+ _sendMessage("streamListen", {"streamId": "$streamId"});
+
+/// Tell the vm service to resume a specific isolate.
+_resumeIsolate(String isolateId) =>
+ _sendMessage("resume", {"isolateId": "$isolateId"});
+
+/// Resumes the main isolate if it was paused on start.
+_resumeMainIsolateIfPaused() async {
+ var vm = await _sendMessage('getVM');
+ var isolateId = vm["isolates"][0]["id"];
+ var isolate = await _sendMessage('getIsolate', {'isolateId': isolateId});
sra1 2015/10/05 17:04:58 Some strings are 'x' others "x". I assume the inte
Siggi Cherem (dart-lang) 2015/10/05 17:19:44 Good point - yeah, I had started with ', then copi
+ bool isPaused = isolate["pauseEvent"]["kind"] == "PauseStart";
+ if (isPaused) _resumeIsolate(isolateId);
+}
+
+/// Send a message to the vm service.
+Future _sendMessage(String method, [Map args= const {}]) {
+ var id = _requestId++;
+ _pendingResponses[id] = new Completer();
+ socket.add(JSON.encode({
+ "jsonrpc": "2.0",
+ "id": "$id",
+ "method": "$method",
+ "params": args,
+ }));
+ return _pendingResponses[id].future;
+}
+
+/// Handle all responses
+_handleResponse(String s) {
+ var json = JSON.decode(s);
+ if (json['method'] != "streamNotify") {
+ var id = json['id'];
+ if (id is String) id = int.parse(id);
+ if (id == null || !_pendingResponses.containsKey(id)) return;
+ _pendingResponses.remove(id).complete(json["result"]);
+ return;
+ }
+
+ // isolate pauses on exit automatically. We detect this to stop and exit.
+ if (json["params"]["streamId"] == "Debug") {
+ _handleDebug(json);
+ } else if (json["params"]["streamId"] == "Isolate") {
+ _handleIsolate(json);
+ } else if (json["params"]["streamId"] == "GC") {
+ _handleGC(json);
+ }
+}
+
+/// Handle a `Debug` notification.
+_handleDebug(Map json) {
+ var isolateId = json["params"]["event"]["isolate"]["id"];
+ if (json["params"]["event"]["kind"] == "PauseStart") {
+ _resumeIsolate(isolateId);
+ } if (json["params"]["event"]["kind"] == "PauseExit") {
+ _resumeIsolate(isolateId);
+ }
+}
+
+/// Handle a `Isolate` notification.
+_handleIsolate(Map json) {
+ if (json["params"]["event"]["kind"] == "IsolateExit") {
+ print('');
+ socket.close();
+ }
+}
+
+/// Handle a `GC` notification.
+_handleGC(Map json) {
+ // print(new JsonEncoder.withIndent(" ").convert(json));
+ var event = json["params"]["event"];
+ var newUsed = event["new"]["used"];
+ var newCapacity = event["new"]["capacity"];
+ var oldUsed = event["old"]["used"];
+ var oldCapacity = event["old"]["capacity"];
+ _showProgress(newUsed, newCapacity, oldUsed, oldCapacity);
+}
+
+int lastNewUsed = 0;
+int lastOldUsed = 0;
+int lastMaxUsed = 0;
+int lastNewCapacity = 0;
+int lastOldCapacity = 0;
+int lastMaxCapacity = 0;
+
+/// Shows a status line with use/capacity numbers for new/old/total/max,
+/// highlighting in red when capacity increases, and in green when it decreases.
+_showProgress(newUsed, newCapacity, oldUsed, oldCapacity) {
+ var sb = new StringBuffer();
+ sb.write('\r '); // replace the status-line in place
+ _writeNumber(sb, lastNewUsed, newUsed);
+ _writeNumber(sb, lastNewCapacity, newCapacity, color: true);
+
+ sb.write(' | ');
+ _writeNumber(sb, lastOldUsed, oldUsed);
+ _writeNumber(sb, lastOldCapacity, oldCapacity, color: true);
+
+ sb.write(' | ');
+ _writeNumber(sb, lastNewUsed + lastOldUsed, newUsed + oldUsed);
+ _writeNumber(sb, lastNewCapacity + lastOldCapacity, newCapacity + oldCapacity,
+ color: true);
+
+ sb.write(' | ');
+ var maxUsed = max(lastMaxUsed, newUsed + oldUsed);
+ var maxCapacity = max(lastMaxCapacity, newCapacity + oldCapacity);
+ _writeNumber(sb, lastMaxUsed, maxUsed);
+ _writeNumber(sb, lastMaxCapacity, maxCapacity, color: true);
+ stdout.write('$sb');
+
+ lastNewUsed = newUsed;
+ lastOldUsed = oldUsed;
+ lastMaxUsed = maxUsed;
+ lastNewCapacity = newCapacity;
+ lastOldCapacity = oldCapacity;
+ lastMaxCapacity = maxCapacity;
+}
+
+const mega = 1024 * 1024;
+_writeNumber(sb, before, now, {color: false}) {
+ if (color) sb.write(before < now ? _RED : before > now ? _GREEN : '');
+ var string;
+ if (now < 1024) {
+ string = ' ${now}b';
+ } else if (now < mega) {
+ string = ' ${(now/1024).toStringAsFixed(0)}K';
+ } else {
+ string = ' ${(now/mega).toStringAsFixed(1)}M';
+ }
+ if (string.length < 10) string = '${" " * (8 - string.length)}$string';
+ sb.write(string);
+ if (color) sb.write(before != now ? _NONE : '');
+ return before > now;
+}
+
+_printHeader() {
+ print('''
+Memory usage:
+ new generation | old generation | total | max
+ in-use/capacity | in-use/capacity | in-use/capacity | in-use/capacity ''');
+}
+
+const _RED = "\x1b[31m";
+const _GREEN = "\x1b[32m";
+const _NONE = "\x1b[0m";
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698