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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 /// A script to track the high water-mark of memory usage of an application.
6 /// To monitor how much memory dart2js is using, run dart2js as follows:
7 ///
8 /// DART_VM_OPTIONS=--observe dart2js ...
9 ///
10 /// and run this script immediately after.
11 library compiler.tool.track_memory;
12
13 import 'dart:math' show max;
14 import 'dart:io';
15 import 'dart:async';
16
17 import 'dart:convert';
18
19 /// Socket to connect to the vm observatory service.
20 WebSocket socket;
21
22 main(args) async {
23 _printHeader();
24 _showProgress(0, 0, 0, 0);
25 try {
26 var port = args.length > 0 ? int.parse(args[0]) : 8181;
27 socket = await WebSocket.connect('ws://localhost:$port/ws');
28 socket.listen(_handleResponse);
29 await _resumeMainIsolateIfPaused();
30 _streamListen('GC');
31 _streamListen('Isolate');
32 _streamListen('Debug');
33 } catch (e) {
34 // TODO(sigmund): add better error messages, maybe option to retry.
35 print('\n${_RED}error${_NONE}: $e');
36 print('usage:\n'
37 ' Start a Dart process with the --observe flag (and optionally '
38 'the --pause_isolates_on_start flag), then invoke:\n'
39 ' dart tool/track_memory.dart [<port>]\n'
40 ' by default port is 8181');
41 }
42 }
43
44 /// Internal counter for request ids.
45 int _requestId = 0;
46 Map _pendingResponses = {};
47
48 /// Subscribe to listen to a vm service data stream.
49 _streamListen(String streamId) =>
50 _sendMessage('streamListen', {'streamId': '$streamId'});
51
52 /// Tell the vm service to resume a specific isolate.
53 _resumeIsolate(String isolateId) =>
54 _sendMessage('resume', {'isolateId': '$isolateId'});
55
56 /// Resumes the main isolate if it was paused on start.
57 _resumeMainIsolateIfPaused() async {
58 var vm = await _sendMessage('getVM');
59 var isolateId = vm['isolates'][0]['id'];
60 var isolate = await _sendMessage('getIsolate', {'isolateId': isolateId});
61 bool isPaused = isolate['pauseEvent']['kind'] == 'PauseStart';
62 if (isPaused) _resumeIsolate(isolateId);
63 }
64
65 /// Send a message to the vm service.
66 Future _sendMessage(String method, [Map args= const {}]) {
67 var id = _requestId++;
68 _pendingResponses[id] = new Completer();
69 socket.add(JSON.encode({
70 'jsonrpc': '2.0',
71 'id': '$id',
72 'method': '$method',
73 'params': args,
74 }));
75 return _pendingResponses[id].future;
76 }
77
78 /// Handle all responses
79 _handleResponse(String s) {
80 var json = JSON.decode(s);
81 if (json['method'] != 'streamNotify') {
82 var id = json['id'];
83 if (id is String) id = int.parse(id);
84 if (id == null || !_pendingResponses.containsKey(id)) return;
85 _pendingResponses.remove(id).complete(json['result']);
86 return;
87 }
88
89 // isolate pauses on exit automatically. We detect this to stop and exit.
90 if (json['params']['streamId'] == 'Debug') {
91 _handleDebug(json);
92 } else if (json['params']['streamId'] == 'Isolate') {
93 _handleIsolate(json);
94 } else if (json['params']['streamId'] == 'GC') {
95 _handleGC(json);
96 }
97 }
98
99 /// Handle a `Debug` notification.
100 _handleDebug(Map json) {
101 var isolateId = json['params']['event']['isolate']['id'];
102 if (json['params']['event']['kind'] == 'PauseStart') {
103 _resumeIsolate(isolateId);
104 } if (json['params']['event']['kind'] == 'PauseExit') {
105 _resumeIsolate(isolateId);
106 }
107 }
108
109 /// Handle a `Isolate` notification.
110 _handleIsolate(Map json) {
111 if (json['params']['event']['kind'] == 'IsolateExit') {
112 print('');
113 socket.close();
114 }
115 }
116
117 /// Handle a `GC` notification.
118 _handleGC(Map json) {
119 // print(new JsonEncoder.withIndent(' ').convert(json));
120 var event = json['params']['event'];
121 var newUsed = event['new']['used'];
122 var newCapacity = event['new']['capacity'];
123 var oldUsed = event['old']['used'];
124 var oldCapacity = event['old']['capacity'];
125 _showProgress(newUsed, newCapacity, oldUsed, oldCapacity);
126 }
127
128 int lastNewUsed = 0;
129 int lastOldUsed = 0;
130 int lastMaxUsed = 0;
131 int lastNewCapacity = 0;
132 int lastOldCapacity = 0;
133 int lastMaxCapacity = 0;
134
135 /// Shows a status line with use/capacity numbers for new/old/total/max,
136 /// highlighting in red when capacity increases, and in green when it decreases.
137 _showProgress(newUsed, newCapacity, oldUsed, oldCapacity) {
138 var sb = new StringBuffer();
139 sb.write('\r '); // replace the status-line in place
140 _writeNumber(sb, lastNewUsed, newUsed);
141 _writeNumber(sb, lastNewCapacity, newCapacity, color: true);
142
143 sb.write(' | ');
144 _writeNumber(sb, lastOldUsed, oldUsed);
145 _writeNumber(sb, lastOldCapacity, oldCapacity, color: true);
146
147 sb.write(' | ');
148 _writeNumber(sb, lastNewUsed + lastOldUsed, newUsed + oldUsed);
149 _writeNumber(sb, lastNewCapacity + lastOldCapacity, newCapacity + oldCapacity,
150 color: true);
151
152 sb.write(' | ');
153 var maxUsed = max(lastMaxUsed, newUsed + oldUsed);
154 var maxCapacity = max(lastMaxCapacity, newCapacity + oldCapacity);
155 _writeNumber(sb, lastMaxUsed, maxUsed);
156 _writeNumber(sb, lastMaxCapacity, maxCapacity, color: true);
157 stdout.write('$sb');
158
159 lastNewUsed = newUsed;
160 lastOldUsed = oldUsed;
161 lastMaxUsed = maxUsed;
162 lastNewCapacity = newCapacity;
163 lastOldCapacity = oldCapacity;
164 lastMaxCapacity = maxCapacity;
165 }
166
167 const mega = 1024 * 1024;
168 _writeNumber(sb, before, now, {color: false}) {
169 if (color) sb.write(before < now ? _RED : before > now ? _GREEN : '');
170 var string;
171 if (now < 1024) {
172 string = ' ${now}b';
173 } else if (now < mega) {
174 string = ' ${(now/1024).toStringAsFixed(0)}K';
175 } else {
176 string = ' ${(now/mega).toStringAsFixed(1)}M';
177 }
178 if (string.length < 10) string = '${' ' * (8 - string.length)}$string';
179 sb.write(string);
180 if (color) sb.write(before != now ? _NONE : '');
181 return before > now;
182 }
183
184 _printHeader() {
185 print('''
186 Memory usage:
187 new generation | old generation | total | max
188 in-use/capacity | in-use/capacity | in-use/capacity | in-use/capacity ''');
189 }
190
191 const _RED = '\x1b[31m';
192 const _GREEN = '\x1b[32m';
193 const _NONE = '\x1b[0m';
OLDNEW
« 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