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

Side by Side Diff: runtime/bin/socket_patch.dart

Issue 298353002: Add read/write stats to Socket and RandomAccessFile. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | sdk/lib/io/file_impl.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 patch class RawServerSocket { 5 patch class RawServerSocket {
6 /* patch */ static Future<RawServerSocket> bind(address, 6 /* patch */ static Future<RawServerSocket> bind(address,
7 int port, 7 int port,
8 {int backlog: 0, 8 {int backlog: 0,
9 bool v6Only: false}) { 9 bool v6Only: false}) {
10 return _RawServerSocket.bind(address, port, backlog, v6Only); 10 return _RawServerSocket.bind(address, port, backlog, v6Only);
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 final List<InternetAddress> addresses = []; 200 final List<InternetAddress> addresses = [];
201 201
202 _NetworkInterface(this.name, this.index); 202 _NetworkInterface(this.name, this.index);
203 203
204 String toString() { 204 String toString() {
205 return "NetworkInterface('$name', $addresses)"; 205 return "NetworkInterface('$name', $addresses)";
206 } 206 }
207 } 207 }
208 208
209 209
210 class _Rate {
211 final int buckets;
212 final data;
213 int lastValue = 0;
214 int nextBucket = 0;
215
216 _Rate(int buckets) : buckets = buckets, data = new List.filled(buckets, 0);
217
218 void update(int value) {
219 data[nextBucket] = value - lastValue;
220 lastValue = value;
221 nextBucket = (nextBucket + 1) % buckets;
222 }
223
224 int get rate {
225 int sum = data.fold(0, (prev, element) => prev + element);
226 return sum ~/ buckets;
227 }
228 }
229
230 // Statics information for the observatory.
231 class _SocketStat {
232 _Rate readRate = new _Rate(5);
233 _Rate writeRate = new _Rate(5);
234
235 void update(_NativeSocket socket) {
236 readRate.update(socket.totalRead);
237 writeRate.update(socket.totalWritten);
238 }
239 }
240
241 class _SocketsObservatory {
242 static int socketCount = 0;
243 static Map sockets = new Map<_NativeSocket, _SocketStat>();
244 static Timer timer;
245
246 static add(_NativeSocket socket) {
247 if (socketCount == 0) startTimer();
248 sockets[socket] = new _SocketStat();
249 socketCount++;
250 }
251
252 static remove(_NativeSocket socket) {
253 _SocketStat stats = sockets.remove(socket);
254 assert(stats != null);
255 socketCount--;
256 if (socketCount == 0) stopTimer();
257 }
258
259 static update(_) {
260 sockets.forEach((socket, stat) {
261 stat.update(socket);
262 });
263 }
264
265 static startTimer() {
266 if (timer != null) return;
267 // TODO(sgjesse): Enable the rate timer.
268 // timer = new Timer.periodic(new Duration(seconds: 1), update);
269 }
270
271 static stopTimer() {
272 if (timer == null) return;
273 timer.cancel();
274 timer = null;
275 }
276
277 static String generateResponse() {
278 var response = new Map();
279 response['type'] = 'SocketList';
280 var members = new List();
281 response['members'] = members;
282 sockets.forEach((socket, stat) {
283 var kind =
284 socket.isListening ? "LISTENING" :
285 socket.isPipe ? "PIPE" :
286 socket.isInternal ? "INTERNAL" : "NORMAL";
287 var protocol =
288 socket.isTcp ? "tcp" :
289 socket.isUdp ? "udp" : "";
290 var localAddress;
291 var localPort;
292 var remoteAddress;
293 var remotePort;
294 try {
295 localAddress = socket.address.address;
296 } catch (e) {
297 localAddress = "n/a";
298 }
299 try {
300 localPort = socket.port;
301 } catch (e) {
302 localPort = "n/a";
303 }
304 try {
305 remoteAddress = socket.remoteAddress.address;
306 } catch (e) {
307 remoteAddress = "n/a";
308 }
309 try {
310 remotePort = socket.remotePort;
311 } catch (e) {
312 remotePort = "n/a";
313 }
314 members.add({'type': 'Socket', 'kind': kind, 'protocol': protocol,
315 'localAddress': localAddress, 'localPort': localPort,
316 'remoteAddress': remoteAddress, 'remotePort': remotePort,
317 'totalRead': socket.totalRead,
318 'totalWritten': socket.totalWritten,
319 'readPerSec': stat.readRate.rate,
320 'writePerSec': stat.writeRate.rate});
321 });
322 return JSON.encode(response);;
323 }
324
325 static String toJSON() {
326 try {
327 return generateResponse();
328 } catch (e, s) {
329 return '{"type":"Error","text":"$e","stacktrace":"$s"}';
330 }
331 }
332 }
333
334
335 // The NativeFieldWrapperClass1 can not be used with a mixin, due to missing 210 // The NativeFieldWrapperClass1 can not be used with a mixin, due to missing
336 // implicit constructor. 211 // implicit constructor.
337 class _NativeSocketNativeWrapper extends NativeFieldWrapperClass1 {} 212 class _NativeSocketNativeWrapper extends NativeFieldWrapperClass1 {}
338 213
339 214
340 // The _NativeSocket class encapsulates an OS socket. 215 // The _NativeSocket class encapsulates an OS socket.
341 class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { 216 class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
342 // Bit flags used when communicating between the eventhandler and 217 // Bit flags used when communicating between the eventhandler and
343 // dart code. The EVENT flags are used to indicate events of 218 // dart code. The EVENT flags are used to indicate events of
344 // interest when sending a message from dart code to the 219 // interest when sending a message from dart code to the
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 300
426 int tokens = 0; 301 int tokens = 0;
427 302
428 bool sendReadEvents = false; 303 bool sendReadEvents = false;
429 bool readEventIssued = false; 304 bool readEventIssued = false;
430 305
431 bool sendWriteEvents = false; 306 bool sendWriteEvents = false;
432 bool writeEventIssued = false; 307 bool writeEventIssued = false;
433 bool writeAvailable = false; 308 bool writeAvailable = false;
434 309
310 static final Stopwatch sw = new Stopwatch()..start();
435 // Statistics. 311 // Statistics.
436 int totalRead = 0; 312 int totalRead = 0;
437 int totalWritten = 0; 313 int totalWritten = 0;
314 int readCount = 0;
315 int writeCount = 0;
316 double lastRead;
317 double lastWrite;
438 318
439 // The owner object is the object that the Socket is being used by, e.g. 319 // The owner object is the object that the Socket is being used by, e.g.
440 // a HttpServer, a WebSocket connection, a process pipe, etc. 320 // a HttpServer, a WebSocket connection, a process pipe, etc.
441 Object owner; 321 Object owner;
442 322
323 static double get timestamp => sw.elapsedMicroseconds / 1000000.0;
324
443 static Future<List<InternetAddress>> lookup( 325 static Future<List<InternetAddress>> lookup(
444 String host, {InternetAddressType type: InternetAddressType.ANY}) { 326 String host, {InternetAddressType type: InternetAddressType.ANY}) {
445 return _IOService.dispatch(_SOCKET_LOOKUP, [host, type._value]) 327 return _IOService.dispatch(_SOCKET_LOOKUP, [host, type._value])
446 .then((response) { 328 .then((response) {
447 if (isErrorResponse(response)) { 329 if (isErrorResponse(response)) {
448 throw createError(response, "Failed host lookup: '$host'"); 330 throw createError(response, "Failed host lookup: '$host'");
449 } else { 331 } else {
450 return response.skip(1).map((result) { 332 return response.skip(1).map((result) {
451 var type = new InternetAddressType._from(result[0]); 333 var type = new InternetAddressType._from(result[0]);
452 return new _InternetAddress(result[1], host, result[2]); 334 return new _InternetAddress(result[1], host, result[2]);
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
637 if (len == 0) return null; 519 if (len == 0) return null;
638 var result = nativeRead(len); 520 var result = nativeRead(len);
639 if (result is OSError) { 521 if (result is OSError) {
640 reportError(result, "Read failed"); 522 reportError(result, "Read failed");
641 return null; 523 return null;
642 } 524 }
643 if (result != null) { 525 if (result != null) {
644 available -= result.length; 526 available -= result.length;
645 totalRead += result.length; 527 totalRead += result.length;
646 } 528 }
529 readCount++;
530 lastRead = timestamp;
647 return result; 531 return result;
648 } 532 }
649 533
650 Datagram receive() { 534 Datagram receive() {
651 if (isClosing || isClosed) return null; 535 if (isClosing || isClosed) return null;
652 var result = nativeRecvFrom(); 536 var result = nativeRecvFrom();
653 if (result is OSError) { 537 if (result is OSError) {
654 reportError(result, "Receive failed"); 538 reportError(result, "Receive failed");
655 return null; 539 return null;
656 } 540 }
657 if (result != null) { 541 if (result != null) {
658 if (Platform.isMacOS) { 542 if (Platform.isMacOS) {
659 // Mac includes the header size, so we need to query the actual 543 // Mac includes the header size, so we need to query the actual
660 // available. 544 // available.
661 available = nativeAvailable(); 545 available = nativeAvailable();
662 } else { 546 } else {
663 available -= result.data.length; 547 available -= result.data.length;
664 } 548 }
549 totalRead += result.data.length;
665 } 550 }
551 readCount++;
552 lastRead = timestamp;
666 return result; 553 return result;
667 } 554 }
668 555
669 int write(List<int> buffer, int offset, int bytes) { 556 int write(List<int> buffer, int offset, int bytes) {
670 if (buffer is! List) throw new ArgumentError(); 557 if (buffer is! List) throw new ArgumentError();
671 if (offset == null) offset = 0; 558 if (offset == null) offset = 0;
672 if (bytes == null) { 559 if (bytes == null) {
673 if (offset > buffer.length) { 560 if (offset > buffer.length) {
674 throw new RangeError.value(offset); 561 throw new RangeError.value(offset);
675 } 562 }
(...skipping 19 matching lines...) Expand all
695 } 582 }
696 // The result may be negative, if we forced a short write for testing 583 // The result may be negative, if we forced a short write for testing
697 // purpose. In such case, don't mark writeAvailable as false, as we don't 584 // purpose. In such case, don't mark writeAvailable as false, as we don't
698 // know if we'll receive an event. It's better to just retry. 585 // know if we'll receive an event. It's better to just retry.
699 if (result >= 0 && result < bytes) { 586 if (result >= 0 && result < bytes) {
700 writeAvailable = false; 587 writeAvailable = false;
701 } 588 }
702 // Negate the result, as stated above. 589 // Negate the result, as stated above.
703 if (result < 0) result = -result; 590 if (result < 0) result = -result;
704 totalWritten += result; 591 totalWritten += result;
592 writeCount++;
593 lastWrite = timestamp;
705 return result; 594 return result;
706 } 595 }
707 596
708 int send(List<int> buffer, int offset, int bytes, 597 int send(List<int> buffer, int offset, int bytes,
709 InternetAddress address, int port) { 598 InternetAddress address, int port) {
710 if (isClosing || isClosed) return 0; 599 if (isClosing || isClosed) return 0;
711 _BufferAndStart bufferAndStart = 600 _BufferAndStart bufferAndStart =
712 _ensureFastAndSerializableByteData( 601 _ensureFastAndSerializableByteData(
713 buffer, offset, bytes); 602 buffer, offset, bytes);
714 var result = nativeSendTo( 603 var result = nativeSendTo(
715 bufferAndStart.buffer, bufferAndStart.start, bytes, 604 bufferAndStart.buffer, bufferAndStart.start, bytes,
716 address._in_addr, port); 605 address._in_addr, port);
717 if (result is OSError) { 606 if (result is OSError) {
718 scheduleMicrotask(() => reportError(result, "Send failed")); 607 scheduleMicrotask(() => reportError(result, "Send failed"));
719 result = 0; 608 result = 0;
720 } 609 }
610 totalWritten += result;
611 writeCount++;
612 lastWrite = timestamp;
721 return result; 613 return result;
722 } 614 }
723 615
724 _NativeSocket accept() { 616 _NativeSocket accept() {
725 // Don't issue accept if we're closing. 617 // Don't issue accept if we're closing.
726 if (isClosing || isClosed) return null; 618 if (isClosing || isClosed) return null;
727 assert(available > 0); 619 assert(available > 0);
728 available--; 620 available--;
729 tokens++; 621 tokens++;
730 returnTokens(LISTENING_TOKEN_BATCH_SIZE); 622 returnTokens(LISTENING_TOKEN_BATCH_SIZE);
731 var socket = new _NativeSocket.normal(); 623 var socket = new _NativeSocket.normal();
732 if (nativeAccept(socket) != true) return null; 624 if (nativeAccept(socket) != true) return null;
733 socket.localPort = localPort; 625 socket.localPort = localPort;
734 socket.address = address; 626 socket.address = address;
735 totalRead += 1; 627 totalRead += 1;
628 lastRead = timestamp;
736 return socket; 629 return socket;
737 } 630 }
738 631
739 int get port { 632 int get port {
740 if (localPort != 0) return localPort; 633 if (localPort != 0) return localPort;
741 var result = nativeGetPort(); 634 var result = nativeGetPort();
742 if (result is OSError) throw result; 635 if (result is OSError) throw result;
743 return localPort = result; 636 return localPort = result;
744 } 637 }
745 638
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 'name': name, 978 'name': name,
1086 'user_name': name, 979 'user_name': name,
1087 'kind': _JSONKind(), 980 'kind': _JSONKind(),
1088 }; 981 };
1089 if (ref) { 982 if (ref) {
1090 return r; 983 return r;
1091 } 984 }
1092 r['readClosed'] = isClosedRead; 985 r['readClosed'] = isClosedRead;
1093 r['writeClosed'] = isClosedWrite; 986 r['writeClosed'] = isClosedWrite;
1094 r['closing'] = isClosing; 987 r['closing'] = isClosing;
1095 r['listening'] = isListening;
1096 r['fd'] = nativeGetSocketId(); 988 r['fd'] = nativeGetSocketId();
1097 if (owner != null) { 989 if (owner != null) {
1098 r['owner'] = owner._toJSON(true); 990 r['owner'] = owner._toJSON(true);
991 }
992 return r;
993 }
994
995 Map _toJSONInternal(bool ref) {
996 var name = 'Internal';
997 var r = {
998 'id': _servicePath,
999 'type': _serviceType(ref),
1000 'name': name,
1001 'user_name': name,
1002 'kind': _JSONKind(),
1003 };
1004 if (ref) {
1005 return r;
1006 }
1007 r['closing'] = isClosing;
1008 r['fd'] = nativeGetSocketId();
1009 if (owner != null) {
1010 r['owner'] = owner._toJSON(true);
1099 } 1011 }
1100 return r; 1012 return r;
1101 } 1013 }
1102 1014
1103 Map _toJSONNetwork(bool ref) { 1015 Map _toJSONNetwork(bool ref) {
1104 var name = '${address.host}:$port'; 1016 var name = '${address.host}:$port';
1105 if (isTcp && !isListening) name += " <-> ${remoteAddress.host}:$remotePort"; 1017 if (isTcp && !isListening) name += " <-> ${remoteAddress.host}:$remotePort";
1106 var r = { 1018 var r = {
1107 'id': _servicePath, 1019 'id': _servicePath,
1108 'type': _serviceType(ref), 1020 'type': _serviceType(ref),
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1140 r['closing'] = isClosing; 1052 r['closing'] = isClosing;
1141 r['listening'] = isListening; 1053 r['listening'] = isListening;
1142 r['fd'] = nativeGetSocketId(); 1054 r['fd'] = nativeGetSocketId();
1143 if (owner != null) { 1055 if (owner != null) {
1144 r['owner'] = owner._toJSON(true); 1056 r['owner'] = owner._toJSON(true);
1145 } 1057 }
1146 return r; 1058 return r;
1147 } 1059 }
1148 1060
1149 Map _toJSON(bool ref) { 1061 Map _toJSON(bool ref) {
1062 var map;
1150 if (isPipe) { 1063 if (isPipe) {
1151 return _toJSONPipe(ref); 1064 map = _toJSONPipe(ref);
1065 } else if (isInternal) {
1066 map = _toJSONInternal(ref);
1067 } else {
1068 map = _toJSONNetwork(ref);
1152 } 1069 }
1153 return _toJSONNetwork(ref); 1070 if (!ref) {
1071 map['available'] = available;
1072 map['totalRead'] = totalRead;
1073 map['totalWritten'] = totalWritten;
1074 map['readCount'] = totalWritten;
1075 map['writeCount'] = writeCount;
1076 map['lastRead'] = lastRead;
1077 map['lastWrite'] = lastWrite;
1078 }
1079 return map;
1154 } 1080 }
1155 1081
1156 void nativeSetSocketId(int id) native "Socket_SetSocketId"; 1082 void nativeSetSocketId(int id) native "Socket_SetSocketId";
1157 nativeAvailable() native "Socket_Available"; 1083 nativeAvailable() native "Socket_Available";
1158 nativeRead(int len) native "Socket_Read"; 1084 nativeRead(int len) native "Socket_Read";
1159 nativeRecvFrom() native "Socket_RecvFrom"; 1085 nativeRecvFrom() native "Socket_RecvFrom";
1160 nativeWrite(List<int> buffer, int offset, int bytes) 1086 nativeWrite(List<int> buffer, int offset, int bytes)
1161 native "Socket_WriteList"; 1087 native "Socket_WriteList";
1162 nativeSendTo(List<int> buffer, int offset, int bytes, 1088 nativeSendTo(List<int> buffer, int offset, int bytes,
1163 List<int> address, int port) 1089 List<int> address, int port)
(...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after
1972 String address, 1898 String address,
1973 List<int> in_addr, 1899 List<int> in_addr,
1974 int port) { 1900 int port) {
1975 return new Datagram( 1901 return new Datagram(
1976 data, 1902 data,
1977 new _InternetAddress(address, null, in_addr), 1903 new _InternetAddress(address, null, in_addr),
1978 port); 1904 port);
1979 } 1905 }
1980 1906
1981 String _socketsStats() => _SocketsObservatory.toJSON(); 1907 String _socketsStats() => _SocketsObservatory.toJSON();
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/io/file_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698