From 8b612e87805374ff570fa20ff4e023600d6f2ef3 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Wed, 28 May 2014 13:29:51 +0000 Subject: [PATCH] Add read/write stats to Socket and RandomAccessFile. BUG= R=johnmccutchan@google.com Review URL: https://codereview.chromium.org//298353002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36738 260f80e4-7a28-3924-810f-c04153c831b5 --- runtime/bin/socket_patch.dart | 182 ++++++++++------------------------ sdk/lib/io/file_impl.dart | 29 ++++++ 2 files changed, 83 insertions(+), 128 deletions(-) diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart index 485d1e52f4e..4f285503c20 100644 --- a/runtime/bin/socket_patch.dart +++ b/runtime/bin/socket_patch.dart @@ -207,131 +207,6 @@ class _NetworkInterface implements NetworkInterface { } -class _Rate { - final int buckets; - final data; - int lastValue = 0; - int nextBucket = 0; - - _Rate(int buckets) : buckets = buckets, data = new List.filled(buckets, 0); - - void update(int value) { - data[nextBucket] = value - lastValue; - lastValue = value; - nextBucket = (nextBucket + 1) % buckets; - } - - int get rate { - int sum = data.fold(0, (prev, element) => prev + element); - return sum ~/ buckets; - } -} - -// Statics information for the observatory. -class _SocketStat { - _Rate readRate = new _Rate(5); - _Rate writeRate = new _Rate(5); - - void update(_NativeSocket socket) { - readRate.update(socket.totalRead); - writeRate.update(socket.totalWritten); - } -} - -class _SocketsObservatory { - static int socketCount = 0; - static Map sockets = new Map<_NativeSocket, _SocketStat>(); - static Timer timer; - - static add(_NativeSocket socket) { - if (socketCount == 0) startTimer(); - sockets[socket] = new _SocketStat(); - socketCount++; - } - - static remove(_NativeSocket socket) { - _SocketStat stats = sockets.remove(socket); - assert(stats != null); - socketCount--; - if (socketCount == 0) stopTimer(); - } - - static update(_) { - sockets.forEach((socket, stat) { - stat.update(socket); - }); - } - - static startTimer() { - if (timer != null) return; - // TODO(sgjesse): Enable the rate timer. - // timer = new Timer.periodic(new Duration(seconds: 1), update); - } - - static stopTimer() { - if (timer == null) return; - timer.cancel(); - timer = null; - } - - static String generateResponse() { - var response = new Map(); - response['type'] = 'SocketList'; - var members = new List(); - response['members'] = members; - sockets.forEach((socket, stat) { - var kind = - socket.isListening ? "LISTENING" : - socket.isPipe ? "PIPE" : - socket.isInternal ? "INTERNAL" : "NORMAL"; - var protocol = - socket.isTcp ? "tcp" : - socket.isUdp ? "udp" : ""; - var localAddress; - var localPort; - var remoteAddress; - var remotePort; - try { - localAddress = socket.address.address; - } catch (e) { - localAddress = "n/a"; - } - try { - localPort = socket.port; - } catch (e) { - localPort = "n/a"; - } - try { - remoteAddress = socket.remoteAddress.address; - } catch (e) { - remoteAddress = "n/a"; - } - try { - remotePort = socket.remotePort; - } catch (e) { - remotePort = "n/a"; - } - members.add({'type': 'Socket', 'kind': kind, 'protocol': protocol, - 'localAddress': localAddress, 'localPort': localPort, - 'remoteAddress': remoteAddress, 'remotePort': remotePort, - 'totalRead': socket.totalRead, - 'totalWritten': socket.totalWritten, - 'readPerSec': stat.readRate.rate, - 'writePerSec': stat.writeRate.rate}); - }); - return JSON.encode(response);; - } - - static String toJSON() { - try { - return generateResponse(); - } catch (e, s) { - return '{"type":"Error","text":"$e","stacktrace":"$s"}'; - } - } -} - - // The NativeFieldWrapperClass1 can not be used with a mixin, due to missing // implicit constructor. class _NativeSocketNativeWrapper extends NativeFieldWrapperClass1 {} @@ -432,14 +307,21 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { bool writeEventIssued = false; bool writeAvailable = false; + static final Stopwatch sw = new Stopwatch()..start(); // Statistics. int totalRead = 0; int totalWritten = 0; + int readCount = 0; + int writeCount = 0; + double lastRead; + double lastWrite; // The owner object is the object that the Socket is being used by, e.g. // a HttpServer, a WebSocket connection, a process pipe, etc. Object owner; + static double get timestamp => sw.elapsedMicroseconds / 1000000.0; + static Future> lookup( String host, {InternetAddressType type: InternetAddressType.ANY}) { return _IOService.dispatch(_SOCKET_LOOKUP, [host, type._value]) @@ -644,6 +526,8 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { available -= result.length; totalRead += result.length; } + readCount++; + lastRead = timestamp; return result; } @@ -662,7 +546,10 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { } else { available -= result.data.length; } + totalRead += result.data.length; } + readCount++; + lastRead = timestamp; return result; } @@ -702,6 +589,8 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { // Negate the result, as stated above. if (result < 0) result = -result; totalWritten += result; + writeCount++; + lastWrite = timestamp; return result; } @@ -718,6 +607,9 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { scheduleMicrotask(() => reportError(result, "Send failed")); result = 0; } + totalWritten += result; + writeCount++; + lastWrite = timestamp; return result; } @@ -733,6 +625,7 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { socket.localPort = localPort; socket.address = address; totalRead += 1; + lastRead = timestamp; return socket; } @@ -1092,7 +985,26 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { r['readClosed'] = isClosedRead; r['writeClosed'] = isClosedWrite; r['closing'] = isClosing; - r['listening'] = isListening; + r['fd'] = nativeGetSocketId(); + if (owner != null) { + r['owner'] = owner._toJSON(true); + } + return r; + } + + Map _toJSONInternal(bool ref) { + var name = 'Internal'; + var r = { + 'id': _servicePath, + 'type': _serviceType(ref), + 'name': name, + 'user_name': name, + 'kind': _JSONKind(), + }; + if (ref) { + return r; + } + r['closing'] = isClosing; r['fd'] = nativeGetSocketId(); if (owner != null) { r['owner'] = owner._toJSON(true); @@ -1147,10 +1059,24 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject { } Map _toJSON(bool ref) { + var map; if (isPipe) { - return _toJSONPipe(ref); + map = _toJSONPipe(ref); + } else if (isInternal) { + map = _toJSONInternal(ref); + } else { + map = _toJSONNetwork(ref); } - return _toJSONNetwork(ref); + if (!ref) { + map['available'] = available; + map['totalRead'] = totalRead; + map['totalWritten'] = totalWritten; + map['readCount'] = totalWritten; + map['writeCount'] = writeCount; + map['lastRead'] = lastRead; + map['lastWrite'] = lastWrite; + } + return map; } void nativeSetSocketId(int id) native "Socket_SetSocketId"; diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart index c43b4cf60e9..cd1ad334f35 100644 --- a/sdk/lib/io/file_impl.dart +++ b/sdk/lib/io/file_impl.dart @@ -567,6 +567,11 @@ class _RandomAccessFile bool _asyncDispatched = false; SendPort _fileService; + int _totalRead = 0; + int _totalWritten = 0; + int _readCount = 0; + int _writeCount = 0; + _RandomAccessFile(this._id, this.path) { _files[_serviceId] = this; @@ -587,6 +592,10 @@ class _RandomAccessFile } r['asyncDispatched'] = _asyncDispatched; r['fd'] = _getFD(_id); + r['totalRead'] = _totalRead; + r['totalWritten'] = _totalWritten; + r['readCount'] = _totalWritten; + r['writeCount'] = _writeCount; return r; } @@ -627,6 +636,8 @@ class _RandomAccessFile if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "readByte failed", path); } + _readCount++; + _totalRead++; return response; }); } @@ -639,6 +650,8 @@ class _RandomAccessFile if (result is OSError) { throw new FileSystemException("readByte failed", path, result); } + _readCount++; + _totalRead++; return result; } @@ -650,6 +663,8 @@ class _RandomAccessFile if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "read failed", path); } + _readCount++; + _totalRead += response[1].length; return response[1]; }); } @@ -665,6 +680,8 @@ class _RandomAccessFile if (result is OSError) { throw new FileSystemException("readSync failed", path, result); } + _readCount++; + _totalRead += result.length; return result; } @@ -684,6 +701,8 @@ class _RandomAccessFile var read = response[1]; var data = response[2]; buffer.setRange(start, start + read, data); + _readCount++; + _totalRead += read; return read; }); } @@ -713,6 +732,8 @@ class _RandomAccessFile if (result is OSError) { throw new FileSystemException("readInto failed", path, result); } + _readCount++; + _totalRead += result; return result; } @@ -724,6 +745,8 @@ class _RandomAccessFile if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "writeByte failed", path); } + _writeCount++; + _totalWritten++; return this; }); } @@ -739,6 +762,8 @@ class _RandomAccessFile if (result is OSError) { throw new FileSystemException("writeByte failed", path, result); } + _writeCount++; + _totalWritten++; return result; } @@ -765,6 +790,8 @@ class _RandomAccessFile if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "writeFrom failed", path); } + _writeCount++; + _totalWritten += end - (start - result.start); return this; }); } @@ -791,6 +818,8 @@ class _RandomAccessFile if (result is OSError) { throw new FileSystemException("writeFrom failed", path, result); } + _writeCount++; + _totalWritten += end - (start - bufferAndStart.start); } Future writeString(String string,