├── .awsbox.json ├── .gitignore ├── README.md ├── config.js ├── doc ├── leak-allocations.png └── leak-gc-events.png ├── package.json ├── server.js ├── something.txt ├── static ├── client.js ├── d3.v2.min.js ├── graph.js ├── head.min.js ├── index.html ├── jquery-1.7.1.min.js ├── jquery.noisy.min.js ├── style.css └── svg.css └── worker.js /.awsbox.json: -------------------------------------------------------------------------------- 1 | { 2 | "processes": [ "server.js" ] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /talk 3 | *~ 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Discovering and Finding Memory Leaks with `node-memwatch` 2 | ========================================================= 3 | 4 | Memory leaks are bad. They are also notoriously hard to detect. 5 | 6 | We present [node-memwatch](https://github.com/lloyd/node-memwatch) as 7 | a tool to help detect and track down memory leaks. 8 | 9 | This document is the outline of a presentation to be given at 10 | [NodeConf 2012](http://nodeconf/). It describes some examples of 11 | memory leaks and the problems they can cause, lists some well-known 12 | tools and methods for detecting and finding Node.JS memory leaks, and 13 | introduces `node-memwatch`, which we believe has some unique 14 | advantages. 15 | 16 | To run this demonstration: 17 | 18 | - Clone this repo (`git clone git://github.com/jedp/node-memwatch-demo.git`) 19 | - `npm install` 20 | - Edit `config.js` (instructions inside) 21 | - `npm start` 22 | - Visit http://localhost:3000/ 23 | 24 | Don't forget to kill the server if you're running in 'leak' mode or 25 | your computer will hate you! 26 | 27 | Memory Leaks? So What? 28 | ----------------------- 29 | 30 | Cool story, bro, but I've got 2 GB of RAM on this box. Why should I 31 | bother spending days tracking down hard-to-find leaks when I can just 32 | restart? 33 | 34 | Well, there are at least three things you should be concerned about: 35 | 36 | 1. As memory heap size grows, V8 becomes increasingly sluggish. (In 37 | part, this is because V8's survival instincts kick in and it starts 38 | performing full garbage-collections very aggressively.) Memory 39 | leaks hurt performance. 40 | 41 | 2. Leaks can be a vector for other types of failure. If your leaky 42 | code is hanging onto references to other resources, you may find 43 | you run out of file descriptors, for example, before you run out of 44 | memory. So your app might still trudge along, but your database 45 | might be inaccessible. 46 | 47 | 3. Eventually, your stuff will crash. And it will probably happen 48 | right when you're getting popular. And then everybody will laugh 49 | and it will be horrid. 50 | 51 | Some Examples of Leaks 52 | ---------------------- 53 | 54 | Closures are the most notorious source of memory leaks in JavaScript. 55 | This is because closures maintain references to their scope and all 56 | variables therein. For example: 57 | 58 | ```javascript 59 | function Leaky() { 60 | var leaked = new InnocentBystander(); 61 | var x = 42; 62 | return function() { 63 | return x; 64 | }; 65 | } 66 | ``` 67 | 68 | Leaks like this will probably be spotted eventually if somebody's 69 | looking for them. But in Node's asynchronous world, we generate 70 | closures all the time in the form of callbacks. If these callbacks 71 | are not handled as fast as they are created, memory allocations will 72 | build up and code that doesn't look leaky will act leaky. That's 73 | harder to spot. 74 | 75 | And what if your application is leaking due to a bug in upstream code? 76 | You may be able to track down the location in your code from where the 77 | leak is emanating, but you might just stare in bewilderment at your 78 | perfectly-written code wondering how in the world it can be leaking! 79 | For example, until fairly recently, anyone using `http.ClientRequest` 80 | was leaking a teensy bit of memory. Long-running services under heavy 81 | load were leaking a lot of memory. (The fix in the Node codebase was 82 | a change of a [mere two 83 | characters](https://github.com/vvo/node/commit/e138f76ab243ba3579ac859f08261a721edc20fe), replacing the method `on()` with the method `once()`.) 84 | 85 | 86 | Tools for Finding Leaks 87 | ----------------------- 88 | 89 | The classic approach is at this point to make a huge pot of coffee, 90 | lock yourself in a closet, and start bisecting code for hours or days 91 | until you find the offender. 92 | 93 | Since this is a memory problem, we can start by looking at `top` or 94 | `htop` or some system utility to discover our memory footprint. 95 | 96 | Within Node itself, there is `process.memoryUsage()`, which will 97 | report Node's heap footprint. 98 | 99 | But that won't get us far. We need tools to help us find leaks. 100 | Happily, there is a growing collection of good collection of tools for 101 | finding leaks in Node.JS applications. 102 | 103 | - Jimb Esser's 104 | [node-mtrace](https://github.com/Jimbly/node-mtrace), which uses the 105 | GCC `mtrace` utility to profile heap usage. 106 | 107 | - Dave Pacheco's 108 | [node-heap-dump](https://github.com/davepacheco/node-heap-dump) 109 | takes a snapshot of the V8 heap and serializes the whole thing out 110 | in a huge JSON file. It includes tools to traverse and investigate 111 | the resulting snapshot in JavaScript. 112 | 113 | - Danny Coates's 114 | [v8-profiler](https://github.com/dannycoates/v8-profiler) and 115 | [node-inspector](https://github.com/dannycoates/node-inspector) 116 | provide Node bindings for the V8 profiler and a Node debugging 117 | interface using the WebKit Web Inspector. 118 | 119 | - Felix Gnass's fork of the same that [un-disables the retainers 120 | graph](http://fgnass.posterous.com/finding-memory-leaks-in-nodejs-applications) 121 | 122 | - Felix Geisendörfer's [Node Memory Leak 123 | Tutorial](https://github.com/felixge/node-memory-leak-tutorial) is a 124 | short and sweet explanation of how to use the `v8-profiler` and 125 | `node-debugger`, and is presently the state-of-the-art for most 126 | Node.JS memory leak debugging. 127 | 128 | - Joyent's SmartOS platform, which furnishes an arsenal of tools at 129 | your disposal for [debugging Node.JS memory 130 | leaks](http://dtrace.org/blogs/bmc/2012/05/05/debugging-node-js-memory-leaks/) 131 | 132 | All these tools are brilliant, but they also have some drawbacks. The 133 | Web Inspector approach is suitable for applications in development, 134 | but is difficult to use on a live deployment, especially when multiple 135 | servers and subprocess are involved in the mix. As such, it may be 136 | difficult to reproduce memory leaks that bite in long-running and 137 | heavily-loaded production environments. Tools like `dtrace` and 138 | `libumem` are awe-inspiring, but only work on certain platforms. 139 | 140 | Goal of `node-memwatch` 141 | ----------------------- 142 | 143 | We would like to have a platform-independent debugging library 144 | requiring no instrumentation that can alert us when our programs might 145 | be leaking memory, and help us find where they are leaking. 146 | 147 | The API will provide three main things: 148 | 149 | - A `'leak'` event emitter 150 | 151 | ```javascript 152 | memwatch.on('leak', function(info) { 153 | // look at info to find out about top contributors 154 | }); 155 | ``` 156 | 157 | - A `'stats'` event emitter 158 | 159 | ```javascript 160 | var memwatch = require('memwatch'); 161 | memwatch.on('stats', function(stats) { 162 | // do something with post-gc memory usage stats 163 | }); 164 | ``` 165 | 166 | - A heap diff class 167 | 168 | ```javascript 169 | var hd = new memwatch.HeapDiff(); 170 | // ... stuff happens ... 171 | var diff = hd.end(); 172 | ``` 173 | 174 | - There is also a function to trigger garbage collection which can be 175 | useful in testing. 176 | 177 | ```javascript 178 | var stats = memwatch.gc(); 179 | ``` 180 | 181 | This is what we want to arrive at. Now let's begin at the beginning. 182 | 183 | Tracking Memory Usage 184 | --------------------- 185 | 186 | Starting with the most basic approach, a simple way to look for leaks 187 | would be to repeatedly call `memoryUsage()` at a fixed interval and 188 | see if there's a positive delta in heap allocations. 189 | 190 | To try this we'll make a simple EventEmitter that emits the memory 191 | usage every minute or so, and plot the usage over time. We'll write a 192 | simple, well-behaved program and track its memory usage: 193 | 194 | - run example 1 195 | 196 | Heap usage spikes up and down chaotically, and it may be difficult to 197 | find a meaningful trend. How long will we have to wait to know that 198 | we have a leak? How long to convince ourselves that we don't have a 199 | leak? 200 | 201 | 202 | `memwatch.on('stats', ...)`: Post-GC Heap Statistics 203 | ---------------------------------------------------- 204 | 205 | We can do a lot better. We can sample memory usage directlyafter a 206 | full garbage-collection and memory compaction, before any new JS 207 | objects have been allocated. 208 | 209 | We'll make a native module utilizing V8's post-gc hook, 210 | `V8::AddGCEpilogueCallback`, and gather heap usage statistics every 211 | time GC occurs. We'll emit this data up to our graph whenever it 212 | arrives. 213 | 214 | This is the first part of our API, the `'stats'` event emitter. It 215 | will emit a message containing the following: 216 | 217 | - usage_trend 218 | - current_base 219 | - estimated_base 220 | - num_full_gc 221 | - num_inc_gc 222 | - heap_compactions 223 | - min 224 | - max 225 | 226 | 227 | - run example 2 228 | 229 | This seems promising. We can see the base memory usage over time much 230 | more clearly. 231 | 232 | We can also prove that `memwatch` itself doesn't leak memory. 233 | 234 | 235 | `memwatch.on('leak', ...)`: Heap Allocation Trends 236 | -------------------------------------------------- 237 | 238 | In this example, we introduce a leaky function to see how our profiler 239 | behaves. 240 | 241 | We can add some analysis to this data and try to establish a trend in 242 | usage over time. 243 | 244 | So let's try this with a leaky program and see what happens. 245 | 246 |  247 | 248 | We can see clearly that the base heap usage only goes up and up. The 249 | indicator `usage_trend` remains positive, showing us that we're 250 | allocating more and more heap over time. 251 | 252 | `memwatch` will keep an eye on this for you, and emit a `'leak'` event 253 | if heap allocation has grown through five consecutive GCs. It tells 254 | you in nice, human-readable form what's going on. 255 | 256 | ```javascript 257 | { start: Fri, 29 Jun 2012 14:12:13 GMT, 258 | end: Fri, 29 Jun 2012 14:12:33 GMT, 259 | growth: 67984, 260 | reason: 'heap growth over 5 consecutive GCs (20s) - 11.67 mb/hr' } 261 | ``` 262 | 263 | `memwatch.HeapDiff()`: Finding Leaks 264 | ------------------------------------ 265 | 266 | Now that we have a leak detector, we want a leak identifier. 267 | 268 | By traversing the V8 heap graph, `memwatch` can collect the names and 269 | allocation counts for all objects on the heap. By comparing two 270 | successive heap snapshots, we can produce a diff. 271 | 272 | The API is: 273 | 274 | ```javascript 275 | var hd = new memwatch.HeapDiff(); 276 | 277 | // do something ... 278 | 279 | var diff = hd.end(); 280 | ``` 281 | 282 | The contents of `diff` will look something like this: 283 | 284 | ```javascript 285 | { 286 | "before": { 287 | "nodes": 11625, 288 | "size_bytes": 1869904, 289 | "size": "1.78 mb" 290 | }, 291 | "after": { 292 | "nodes": 21435, 293 | "size_bytes": 2119136, 294 | "size": "2.02 mb" 295 | }, 296 | "change": { 297 | "size_bytes": 249232, 298 | "size": "243.39 kb", 299 | "freed_nodes": 197, 300 | "allocated_nodes": 10007, 301 | "details": [ 302 | { 303 | "what": "Array", 304 | "size_bytes": 66688, 305 | "size": "65.13 kb", 306 | "+": 4, 307 | "-": 78 308 | }, 309 | { 310 | "what": "Code", 311 | "size_bytes": -55296, 312 | "size": "-54 kb", 313 | "+": 1, 314 | "-": 57 315 | }, 316 | { 317 | "what": "LeakingClass", 318 | "size_bytes": 239952, 319 | "size": "234.33 kb", 320 | "+": 9998, 321 | "-": 0 322 | }, 323 | { 324 | "what": "String", 325 | "size_bytes": -2120, 326 | "size": "-2.07 kb", 327 | "+": 3, 328 | "-": 62 329 | } 330 | ] 331 | } 332 | } 333 | ``` 334 | 335 | `HeapDiff` triggers a full GC before taking its samples, so the data 336 | won't be full of a lot of junk. `memwatch`'s event emitters will not 337 | notify of `HeapDiff` GC events, so you can safely put `HeapDiff` calls 338 | in your `'stats'` handler. 339 | 340 |  341 | 342 | 343 | Future Work 344 | ----------- 345 | 346 | Our next steps will be to provide a list of a few example instances of 347 | a leaked object - names of variables it's been assigned to, index in 348 | an array, closure code, etc. 349 | 350 | Summary 351 | ------- 352 | 353 | With `node-gcstats` we present 354 | 355 | - Accurate memory usage tracking 356 | - Notifications about probable leaks 357 | - A means to produce a heap diff 358 | - That is cross-platform 359 | - And that does not require any extra instrumentation 360 | 361 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /* 3 | * leak 4 | * (boolean) Set to true to leak memory 5 | */ 6 | leak: false, 7 | 8 | /* 9 | * hdInterval 10 | * (integer) Minimum interval in ms to perform heapdump 11 | * comparisons. Note that heapdump triggers gc, 12 | * so you can't do heapdump on gc without getting 13 | * yourself into a pretty tight loop. 14 | */ 15 | hdInterval: 1000 * 5, 16 | 17 | /* 18 | * clientConfig 19 | * (dict) What to show in the client 20 | * 21 | * 'usage' specifies a comma-separated list of 22 | * "events", "usage", and "allocations". Because 23 | * of space constraints and my laziness, "usage" 24 | * and "allocations" are mutually exclusive. So 25 | * you can have "events", "envents,usage", 26 | * "events,allocations", or just plain "usage" or 27 | * "allocations". 28 | * 29 | * 'title' specifies the title at the top of the 30 | * page. Useful if you're demo'ing to an audience. 31 | */ 32 | clientConfig: { 33 | title: "Memory Usage of a Well-Behaved (?) Program", 34 | show: "events,allocations" 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /doc/leak-allocations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jedp/node-memwatch-demo/9f8ecefcffa2815f45e65eb50268eb0000d1694d/doc/leak-allocations.png -------------------------------------------------------------------------------- /doc/leak-gc-events.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jedp/node-memwatch-demo/9f8ecefcffa2815f45e65eb50268eb0000d1694d/doc/leak-gc-events.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "leaky", 3 | "version": "0.0.1", 4 | "private": true, 5 | 6 | "dependencies": { 7 | "express": "2.5.10", 8 | "socket.io": "0.9.6", 9 | "node-gcstats": "git://github.com/jedp/node-memwatch#incremental" 10 | }, 11 | 12 | "scripts": { 13 | "start": "node server.js" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'), 2 | app = express.createServer(), 3 | io = require('socket.io').listen(app), 4 | config = require('./config'), 5 | memwatch = require('memwatch'), 6 | worker = require('./worker'); 7 | 8 | var hd = new memwatch.HeapDiff(); 9 | var lastHD = Date.now(); 10 | var clients = []; 11 | 12 | app.configure(function(){ 13 | app.use(express.static(__dirname + '/static')); 14 | app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 15 | }); 16 | 17 | app.listen(process.env['PORT'] || 3000, function() { 18 | console.log("server listening on port %d", app.address().port); 19 | }); 20 | 21 | // reduce socket.io logging noise 22 | io.set('log level', 1); 23 | 24 | io.sockets.on('connection', function(socket) { 25 | clients.push(socket); 26 | 27 | socket.emit('configure', config.clientConfig); 28 | 29 | socket.on('disconnect', function() { 30 | clients.splice(clients.indexOf(socket), 1); 31 | }); 32 | 33 | // The buttons in the console can cause us to force GC or do a bunch of work 34 | socket.on('message', function(message) { 35 | switch (message) { 36 | case "do_gc": 37 | memwatch.gc(); 38 | break; 39 | 40 | case "add_load": 41 | worker.doStuff(); 42 | break; 43 | 44 | case "pause": 45 | io.sockets.emit('pause', {paused: worker.togglePause()}); 46 | break; 47 | 48 | default: 49 | console.log("what is " + message + "?"); 50 | break; 51 | } 52 | }); 53 | }); 54 | 55 | // every interval, send sample data to the server 56 | 57 | var allocations = {}; 58 | var snoitacolla = {}; 59 | function updateHeapDiff(diff) { 60 | var oldValue; 61 | var newValue; 62 | diff.change.details.forEach(function(data) { 63 | if (allocations[data.what] !== undefined) { 64 | oldValue = allocations[data.what]; 65 | snoitacolla[oldValue].pop(snoitacolla[oldValue].indexOf(oldValue)); 66 | if (!snoitacolla[oldValue].length) { 67 | delete snoitacolla[oldValue]; 68 | } 69 | } else { 70 | oldValue = 0; 71 | } 72 | newValue = oldValue + data["+"] - data["-"]; 73 | allocations[data.what] = newValue; 74 | if (!snoitacolla[newValue]) snoitacolla[newValue] = []; 75 | snoitacolla[newValue].push(data.what); 76 | }); 77 | } 78 | 79 | function topHeapAllocations(howMany) { 80 | howMany = howMany || 6; 81 | var result = []; 82 | // annoyingly, we have to convert the keys to integers first 83 | var keys = []; 84 | Object.keys(snoitacolla).forEach(function(key) { keys.push(parseInt(key, 10)); }); 85 | // sort greatest to least 86 | keys.sort(function(a,b) {return b-a;}); 87 | 88 | keys.slice(0, howMany).forEach(function(key) { 89 | result.push([key, snoitacolla[key]]); 90 | }); 91 | return result; 92 | } 93 | 94 | setInterval(function() { 95 | io.sockets.emit('temporal-sample', process.memoryUsage()); 96 | }, 333); 97 | 98 | // and also emit post-gc stats 99 | memwatch.on('stats', function(data) { 100 | if (data.type === 'inc') { 101 | io.sockets.emit('post-incremental-gc-sample', data); 102 | } else { 103 | if ((Date.now() - lastHD) > config.hdInterval) { 104 | updateHeapDiff(hd.end()); 105 | hd = new memwatch.HeapDiff(); 106 | lastHD = Date.now(); 107 | io.sockets.emit('heap-allocations', topHeapAllocations()); 108 | } 109 | io.sockets.emit('post-full-gc-sample', data); 110 | } 111 | }); 112 | -------------------------------------------------------------------------------- /something.txt: -------------------------------------------------------------------------------- 1 | # Network services, Internet style 2 | # 3 | # Note that it is presently the policy of IANA to assign a single well-known 4 | # port number for both TCP and UDP; hence, officially ports have two entries 5 | # even if the protocol doesn't support UDP operations. 6 | # 7 | # Updated from http://www.iana.org/assignments/port-numbers and other 8 | # sources like http://www.freebsd.org/cgi/cvsweb.cgi/src/etc/services . 9 | # New ports will be added on request if they have been officially assigned 10 | # by IANA and used in the real-world or are needed by a debian package. 11 | # If you need a huge list of used numbers please install the nmap package. 12 | 13 | tcpmux 1/tcp # TCP port service multiplexer 14 | echo 7/tcp 15 | echo 7/udp 16 | discard 9/tcp sink null 17 | discard 9/udp sink null 18 | systat 11/tcp users 19 | daytime 13/tcp 20 | daytime 13/udp 21 | netstat 15/tcp 22 | qotd 17/tcp quote 23 | msp 18/tcp # message send protocol 24 | msp 18/udp 25 | chargen 19/tcp ttytst source 26 | chargen 19/udp ttytst source 27 | ftp-data 20/tcp 28 | ftp 21/tcp 29 | fsp 21/udp fspd 30 | ssh 22/tcp # SSH Remote Login Protocol 31 | ssh 22/udp 32 | telnet 23/tcp 33 | smtp 25/tcp mail 34 | time 37/tcp timserver 35 | time 37/udp timserver 36 | rlp 39/udp resource # resource location 37 | nameserver 42/tcp name # IEN 116 38 | whois 43/tcp nicname 39 | tacacs 49/tcp # Login Host Protocol (TACACS) 40 | tacacs 49/udp 41 | re-mail-ck 50/tcp # Remote Mail Checking Protocol 42 | re-mail-ck 50/udp 43 | domain 53/tcp # Domain Name Server 44 | domain 53/udp 45 | mtp 57/tcp # deprecated 46 | tacacs-ds 65/tcp # TACACS-Database Service 47 | tacacs-ds 65/udp 48 | bootps 67/tcp # BOOTP server 49 | bootps 67/udp 50 | bootpc 68/tcp # BOOTP client 51 | bootpc 68/udp 52 | tftp 69/udp 53 | gopher 70/tcp # Internet Gopher 54 | gopher 70/udp 55 | rje 77/tcp netrjs 56 | finger 79/tcp 57 | http 80/tcp www # WorldWideWeb HTTP 58 | http 80/udp # HyperText Transfer Protocol 59 | link 87/tcp ttylink 60 | kerberos 88/tcp kerberos5 krb5 kerberos-sec # Kerberos v5 61 | kerberos 88/udp kerberos5 krb5 kerberos-sec # Kerberos v5 62 | supdup 95/tcp 63 | hostnames 101/tcp hostname # usually from sri-nic 64 | iso-tsap 102/tcp tsap # part of ISODE 65 | acr-nema 104/tcp dicom # Digital Imag. & Comm. 300 66 | acr-nema 104/udp dicom 67 | csnet-ns 105/tcp cso-ns # also used by CSO name server 68 | csnet-ns 105/udp cso-ns 69 | rtelnet 107/tcp # Remote Telnet 70 | rtelnet 107/udp 71 | pop2 109/tcp postoffice pop-2 # POP version 2 72 | pop2 109/udp pop-2 73 | pop3 110/tcp pop-3 # POP version 3 74 | pop3 110/udp pop-3 75 | sunrpc 111/tcp portmapper # RPC 4.0 portmapper 76 | sunrpc 111/udp portmapper 77 | auth 113/tcp authentication tap ident 78 | sftp 115/tcp 79 | uucp-path 117/tcp 80 | nntp 119/tcp readnews untp # USENET News Transfer Protocol 81 | ntp 123/tcp 82 | ntp 123/udp # Network Time Protocol 83 | pwdgen 129/tcp # PWDGEN service 84 | pwdgen 129/udp 85 | loc-srv 135/tcp epmap # Location Service 86 | loc-srv 135/udp epmap 87 | netbios-ns 137/tcp # NETBIOS Name Service 88 | netbios-ns 137/udp 89 | netbios-dgm 138/tcp # NETBIOS Datagram Service 90 | netbios-dgm 138/udp 91 | netbios-ssn 139/tcp # NETBIOS session service 92 | netbios-ssn 139/udp 93 | imap2 143/tcp imap # Interim Mail Access P 2 and 4 94 | imap2 143/udp imap 95 | snmp 161/tcp # Simple Net Mgmt Protocol 96 | snmp 161/udp 97 | snmp-trap 162/tcp snmptrap # Traps for SNMP 98 | snmp-trap 162/udp snmptrap 99 | cmip-man 163/tcp # ISO mgmt over IP (CMOT) 100 | cmip-man 163/udp 101 | cmip-agent 164/tcp 102 | cmip-agent 164/udp 103 | mailq 174/tcp # Mailer transport queue for Zmailer 104 | mailq 174/udp 105 | xdmcp 177/tcp # X Display Mgr. Control Proto 106 | xdmcp 177/udp 107 | nextstep 178/tcp NeXTStep NextStep # NeXTStep window 108 | nextstep 178/udp NeXTStep NextStep # server 109 | bgp 179/tcp # Border Gateway Protocol 110 | bgp 179/udp 111 | prospero 191/tcp # Cliff Neuman's Prospero 112 | prospero 191/udp 113 | irc 194/tcp # Internet Relay Chat 114 | irc 194/udp 115 | smux 199/tcp # SNMP Unix Multiplexer 116 | smux 199/udp 117 | at-rtmp 201/tcp # AppleTalk routing 118 | at-rtmp 201/udp 119 | at-nbp 202/tcp # AppleTalk name binding 120 | at-nbp 202/udp 121 | at-echo 204/tcp # AppleTalk echo 122 | at-echo 204/udp 123 | at-zis 206/tcp # AppleTalk zone information 124 | at-zis 206/udp 125 | qmtp 209/tcp # Quick Mail Transfer Protocol 126 | qmtp 209/udp 127 | z3950 210/tcp wais # NISO Z39.50 database 128 | z3950 210/udp wais 129 | ipx 213/tcp # IPX 130 | ipx 213/udp 131 | imap3 220/tcp # Interactive Mail Access 132 | imap3 220/udp # Protocol v3 133 | pawserv 345/tcp # Perf Analysis Workbench 134 | pawserv 345/udp 135 | zserv 346/tcp # Zebra server 136 | zserv 346/udp 137 | fatserv 347/tcp # Fatmen Server 138 | fatserv 347/udp 139 | rpc2portmap 369/tcp 140 | rpc2portmap 369/udp # Coda portmapper 141 | codaauth2 370/tcp 142 | codaauth2 370/udp # Coda authentication server 143 | clearcase 371/tcp Clearcase 144 | clearcase 371/udp Clearcase 145 | ulistserv 372/tcp # UNIX Listserv 146 | ulistserv 372/udp 147 | ldap 389/tcp # Lightweight Directory Access Protocol 148 | ldap 389/udp 149 | imsp 406/tcp # Interactive Mail Support Protocol 150 | imsp 406/udp 151 | svrloc 427/tcp # Server Location 152 | svrloc 427/udp 153 | https 443/tcp # http protocol over TLS/SSL 154 | https 443/udp 155 | snpp 444/tcp # Simple Network Paging Protocol 156 | snpp 444/udp 157 | microsoft-ds 445/tcp # Microsoft Naked CIFS 158 | microsoft-ds 445/udp 159 | kpasswd 464/tcp 160 | kpasswd 464/udp 161 | saft 487/tcp # Simple Asynchronous File Transfer 162 | saft 487/udp 163 | isakmp 500/tcp # IPsec - Internet Security Association 164 | isakmp 500/udp # and Key Management Protocol 165 | rtsp 554/tcp # Real Time Stream Control Protocol 166 | rtsp 554/udp 167 | nqs 607/tcp # Network Queuing system 168 | nqs 607/udp 169 | npmp-local 610/tcp dqs313_qmaster # npmp-local / DQS 170 | npmp-local 610/udp dqs313_qmaster 171 | npmp-gui 611/tcp dqs313_execd # npmp-gui / DQS 172 | npmp-gui 611/udp dqs313_execd 173 | hmmp-ind 612/tcp dqs313_intercell # HMMP Indication / DQS 174 | hmmp-ind 612/udp dqs313_intercell 175 | qmqp 628/tcp 176 | qmqp 628/udp 177 | ipp 631/tcp # Internet Printing Protocol 178 | ipp 631/udp 179 | # 180 | # UNIX specific services 181 | # 182 | exec 512/tcp 183 | biff 512/udp comsat 184 | login 513/tcp 185 | who 513/udp whod 186 | shell 514/tcp cmd # no passwords used 187 | syslog 514/udp 188 | printer 515/tcp spooler # line printer spooler 189 | talk 517/udp 190 | ntalk 518/udp 191 | route 520/udp router routed # RIP 192 | timed 525/udp timeserver 193 | tempo 526/tcp newdate 194 | courier 530/tcp rpc 195 | conference 531/tcp chat 196 | netnews 532/tcp readnews 197 | netwall 533/udp # for emergency broadcasts 198 | gdomap 538/tcp # GNUstep distributed objects 199 | gdomap 538/udp 200 | uucp 540/tcp uucpd # uucp daemon 201 | klogin 543/tcp # Kerberized `rlogin' (v5) 202 | kshell 544/tcp krcmd # Kerberized `rsh' (v5) 203 | dhcpv6-client 546/tcp 204 | dhcpv6-client 546/udp 205 | dhcpv6-server 547/tcp 206 | dhcpv6-server 547/udp 207 | afpovertcp 548/tcp # AFP over TCP 208 | afpovertcp 548/udp 209 | idfp 549/tcp 210 | idfp 549/udp 211 | remotefs 556/tcp rfs_server rfs # Brunhoff remote filesystem 212 | nntps 563/tcp snntp # NNTP over SSL 213 | nntps 563/udp snntp 214 | submission 587/tcp # Submission [RFC4409] 215 | submission 587/udp 216 | ldaps 636/tcp # LDAP over SSL 217 | ldaps 636/udp 218 | tinc 655/tcp # tinc control port 219 | tinc 655/udp 220 | silc 706/tcp 221 | silc 706/udp 222 | kerberos-adm 749/tcp # Kerberos `kadmin' (v5) 223 | # 224 | webster 765/tcp # Network dictionary 225 | webster 765/udp 226 | rsync 873/tcp 227 | rsync 873/udp 228 | ftps-data 989/tcp # FTP over SSL (data) 229 | ftps 990/tcp 230 | telnets 992/tcp # Telnet over SSL 231 | telnets 992/udp 232 | imaps 993/tcp # IMAP over SSL 233 | imaps 993/udp 234 | ircs 994/tcp # IRC over SSL 235 | ircs 994/udp 236 | pop3s 995/tcp # POP-3 over SSL 237 | pop3s 995/udp 238 | # 239 | # From ``Assigned Numbers'': 240 | # 241 | #> The Registered Ports are not controlled by the IANA and on most systems 242 | #> can be used by ordinary user processes or programs executed by ordinary 243 | #> users. 244 | # 245 | #> Ports are used in the TCP [45,106] to name the ends of logical 246 | #> connections which carry long term conversations. For the purpose of 247 | #> providing services to unknown callers, a service contact port is 248 | #> defined. This list specifies the port used by the server process as its 249 | #> contact port. While the IANA can not control uses of these ports it 250 | #> does register or list uses of these ports as a convienence to the 251 | #> community. 252 | # 253 | socks 1080/tcp # socks proxy server 254 | socks 1080/udp 255 | proofd 1093/tcp 256 | proofd 1093/udp 257 | rootd 1094/tcp 258 | rootd 1094/udp 259 | openvpn 1194/tcp 260 | openvpn 1194/udp 261 | rmiregistry 1099/tcp # Java RMI Registry 262 | rmiregistry 1099/udp 263 | kazaa 1214/tcp 264 | kazaa 1214/udp 265 | nessus 1241/tcp # Nessus vulnerability 266 | nessus 1241/udp # assessment scanner 267 | lotusnote 1352/tcp lotusnotes # Lotus Note 268 | lotusnote 1352/udp lotusnotes 269 | ms-sql-s 1433/tcp # Microsoft SQL Server 270 | ms-sql-s 1433/udp 271 | ms-sql-m 1434/tcp # Microsoft SQL Monitor 272 | ms-sql-m 1434/udp 273 | ingreslock 1524/tcp 274 | ingreslock 1524/udp 275 | prospero-np 1525/tcp # Prospero non-privileged 276 | prospero-np 1525/udp 277 | datametrics 1645/tcp old-radius 278 | datametrics 1645/udp old-radius 279 | sa-msg-port 1646/tcp old-radacct 280 | sa-msg-port 1646/udp old-radacct 281 | kermit 1649/tcp 282 | kermit 1649/udp 283 | groupwise 1677/tcp 284 | groupwise 1677/udp 285 | l2f 1701/tcp l2tp 286 | l2f 1701/udp l2tp 287 | radius 1812/tcp 288 | radius 1812/udp 289 | radius-acct 1813/tcp radacct # Radius Accounting 290 | radius-acct 1813/udp radacct 291 | msnp 1863/tcp # MSN Messenger 292 | msnp 1863/udp 293 | unix-status 1957/tcp # remstats unix-status server 294 | log-server 1958/tcp # remstats log server 295 | remoteping 1959/tcp # remstats remoteping server 296 | cisco-sccp 2000/tcp # Cisco SCCP 297 | cisco-sccp 2000/udp 298 | search 2010/tcp ndtp 299 | pipe-server 2010/tcp pipe_server 300 | nfs 2049/tcp # Network File System 301 | nfs 2049/udp # Network File System 302 | gnunet 2086/tcp 303 | gnunet 2086/udp 304 | rtcm-sc104 2101/tcp # RTCM SC-104 IANA 1/29/99 305 | rtcm-sc104 2101/udp 306 | gsigatekeeper 2119/tcp 307 | gsigatekeeper 2119/udp 308 | gris 2135/tcp # Grid Resource Information Server 309 | gris 2135/udp 310 | cvspserver 2401/tcp # CVS client/server operations 311 | cvspserver 2401/udp 312 | venus 2430/tcp # codacon port 313 | venus 2430/udp # Venus callback/wbc interface 314 | venus-se 2431/tcp # tcp side effects 315 | venus-se 2431/udp # udp sftp side effect 316 | codasrv 2432/tcp # not used 317 | codasrv 2432/udp # server port 318 | codasrv-se 2433/tcp # tcp side effects 319 | codasrv-se 2433/udp # udp sftp side effect 320 | mon 2583/tcp # MON traps 321 | mon 2583/udp 322 | dict 2628/tcp # Dictionary server 323 | dict 2628/udp 324 | f5-globalsite 2792/tcp 325 | f5-globalsite 2792/udp 326 | gsiftp 2811/tcp 327 | gsiftp 2811/udp 328 | gpsd 2947/tcp 329 | gpsd 2947/udp 330 | gds-db 3050/tcp gds_db # InterBase server 331 | gds-db 3050/udp gds_db 332 | icpv2 3130/tcp icp # Internet Cache Protocol 333 | icpv2 3130/udp icp 334 | mysql 3306/tcp 335 | mysql 3306/udp 336 | nut 3493/tcp # Network UPS Tools 337 | nut 3493/udp 338 | distcc 3632/tcp # distributed compiler 339 | distcc 3632/udp 340 | daap 3689/tcp # Digital Audio Access Protocol 341 | daap 3689/udp 342 | svn 3690/tcp subversion # Subversion protocol 343 | svn 3690/udp subversion 344 | suucp 4031/tcp # UUCP over SSL 345 | suucp 4031/udp 346 | sysrqd 4094/tcp # sysrq daemon 347 | sysrqd 4094/udp 348 | sieve 4190/tcp # ManageSieve Protocol 349 | epmd 4369/tcp # Erlang Port Mapper Daemon 350 | epmd 4369/udp 351 | remctl 4373/tcp # Remote Authenticated Command Service 352 | remctl 4373/udp 353 | f5-iquery 4353/tcp # F5 iQuery 354 | f5-iquery 4353/udp 355 | iax 4569/tcp # Inter-Asterisk eXchange 356 | iax 4569/udp 357 | mtn 4691/tcp # monotone Netsync Protocol 358 | mtn 4691/udp 359 | radmin-port 4899/tcp # RAdmin Port 360 | radmin-port 4899/udp 361 | rfe 5002/udp # Radio Free Ethernet 362 | rfe 5002/tcp 363 | mmcc 5050/tcp # multimedia conference control tool (Yahoo IM) 364 | mmcc 5050/udp 365 | sip 5060/tcp # Session Initiation Protocol 366 | sip 5060/udp 367 | sip-tls 5061/tcp 368 | sip-tls 5061/udp 369 | aol 5190/tcp # AIM 370 | aol 5190/udp 371 | xmpp-client 5222/tcp jabber-client # Jabber Client Connection 372 | xmpp-client 5222/udp jabber-client 373 | xmpp-server 5269/tcp jabber-server # Jabber Server Connection 374 | xmpp-server 5269/udp jabber-server 375 | cfengine 5308/tcp 376 | cfengine 5308/udp 377 | mdns 5353/tcp # Multicast DNS 378 | mdns 5353/udp 379 | postgresql 5432/tcp postgres # PostgreSQL Database 380 | postgresql 5432/udp postgres 381 | freeciv 5556/tcp rptp # Freeciv gameplay 382 | freeciv 5556/udp 383 | amqp 5672/tcp 384 | amqp 5672/udp 385 | amqp 5672/sctp 386 | ggz 5688/tcp # GGZ Gaming Zone 387 | ggz 5688/udp 388 | x11 6000/tcp x11-0 # X Window System 389 | x11 6000/udp x11-0 390 | x11-1 6001/tcp 391 | x11-1 6001/udp 392 | x11-2 6002/tcp 393 | x11-2 6002/udp 394 | x11-3 6003/tcp 395 | x11-3 6003/udp 396 | x11-4 6004/tcp 397 | x11-4 6004/udp 398 | x11-5 6005/tcp 399 | x11-5 6005/udp 400 | x11-6 6006/tcp 401 | x11-6 6006/udp 402 | x11-7 6007/tcp 403 | x11-7 6007/udp 404 | gnutella-svc 6346/tcp # gnutella 405 | gnutella-svc 6346/udp 406 | gnutella-rtr 6347/tcp # gnutella 407 | gnutella-rtr 6347/udp 408 | sge-qmaster 6444/tcp sge_qmaster # Grid Engine Qmaster Service 409 | sge-qmaster 6444/udp sge_qmaster 410 | sge-execd 6445/tcp sge_execd # Grid Engine Execution Service 411 | sge-execd 6445/udp sge_execd 412 | mysql-proxy 6446/tcp # MySQL Proxy 413 | mysql-proxy 6446/udp 414 | afs3-fileserver 7000/tcp bbs # file server itself 415 | afs3-fileserver 7000/udp bbs 416 | afs3-callback 7001/tcp # callbacks to cache managers 417 | afs3-callback 7001/udp 418 | afs3-prserver 7002/tcp # users & groups database 419 | afs3-prserver 7002/udp 420 | afs3-vlserver 7003/tcp # volume location database 421 | afs3-vlserver 7003/udp 422 | afs3-kaserver 7004/tcp # AFS/Kerberos authentication 423 | afs3-kaserver 7004/udp 424 | afs3-volser 7005/tcp # volume managment server 425 | afs3-volser 7005/udp 426 | afs3-errors 7006/tcp # error interpretation service 427 | afs3-errors 7006/udp 428 | afs3-bos 7007/tcp # basic overseer process 429 | afs3-bos 7007/udp 430 | afs3-update 7008/tcp # server-to-server updater 431 | afs3-update 7008/udp 432 | afs3-rmtsys 7009/tcp # remote cache manager service 433 | afs3-rmtsys 7009/udp 434 | font-service 7100/tcp xfs # X Font Service 435 | font-service 7100/udp xfs 436 | http-alt 8080/tcp webcache # WWW caching service 437 | http-alt 8080/udp 438 | bacula-dir 9101/tcp # Bacula Director 439 | bacula-dir 9101/udp 440 | bacula-fd 9102/tcp # Bacula File Daemon 441 | bacula-fd 9102/udp 442 | bacula-sd 9103/tcp # Bacula Storage Daemon 443 | bacula-sd 9103/udp 444 | xmms2 9667/tcp # Cross-platform Music Multiplexing System 445 | xmms2 9667/udp 446 | nbd 10809/tcp # Linux Network Block Device 447 | zabbix-agent 10050/tcp # Zabbix Agent 448 | zabbix-agent 10050/udp 449 | zabbix-trapper 10051/tcp # Zabbix Trapper 450 | zabbix-trapper 10051/udp 451 | amanda 10080/tcp # amanda backup services 452 | amanda 10080/udp 453 | hkp 11371/tcp # OpenPGP HTTP Keyserver 454 | hkp 11371/udp 455 | bprd 13720/tcp # VERITAS NetBackup 456 | bprd 13720/udp 457 | bpdbm 13721/tcp # VERITAS NetBackup 458 | bpdbm 13721/udp 459 | bpjava-msvc 13722/tcp # BP Java MSVC Protocol 460 | bpjava-msvc 13722/udp 461 | vnetd 13724/tcp # Veritas Network Utility 462 | vnetd 13724/udp 463 | bpcd 13782/tcp # VERITAS NetBackup 464 | bpcd 13782/udp 465 | vopied 13783/tcp # VERITAS NetBackup 466 | vopied 13783/udp 467 | dcap 22125/tcp # dCache Access Protocol 468 | gsidcap 22128/tcp # GSI dCache Access Protocol 469 | wnn6 22273/tcp # wnn6 470 | wnn6 22273/udp 471 | 472 | # 473 | # Datagram Delivery Protocol services 474 | # 475 | rtmp 1/ddp # Routing Table Maintenance Protocol 476 | nbp 2/ddp # Name Binding Protocol 477 | echo 4/ddp # AppleTalk Echo Protocol 478 | zip 6/ddp # Zone Information Protocol 479 | 480 | #========================================================================= 481 | # The remaining port numbers are not as allocated by IANA. 482 | #========================================================================= 483 | 484 | # Kerberos (Project Athena/MIT) services 485 | # Note that these are for Kerberos v4, and are unofficial. Sites running 486 | # v4 should uncomment these and comment out the v5 entries above. 487 | # 488 | kerberos4 750/udp kerberos-iv kdc # Kerberos (server) 489 | kerberos4 750/tcp kerberos-iv kdc 490 | kerberos-master 751/udp kerberos_master # Kerberos authentication 491 | kerberos-master 751/tcp 492 | passwd-server 752/udp passwd_server # Kerberos passwd server 493 | krb-prop 754/tcp krb_prop krb5_prop hprop # Kerberos slave propagation 494 | krbupdate 760/tcp kreg # Kerberos registration 495 | swat 901/tcp # swat 496 | kpop 1109/tcp # Pop with Kerberos 497 | knetd 2053/tcp # Kerberos de-multiplexor 498 | zephyr-srv 2102/udp # Zephyr server 499 | zephyr-clt 2103/udp # Zephyr serv-hm connection 500 | zephyr-hm 2104/udp # Zephyr hostmanager 501 | eklogin 2105/tcp # Kerberos encrypted rlogin 502 | # Hmmm. Are we using Kv4 or Kv5 now? Worrying. 503 | # The following is probably Kerberos v5 --- ajt@debian.org (11/02/2000) 504 | kx 2111/tcp # X over Kerberos 505 | iprop 2121/tcp # incremental propagation 506 | # 507 | # Unofficial but necessary (for NetBSD) services 508 | # 509 | supfilesrv 871/tcp # SUP server 510 | supfiledbg 1127/tcp # SUP debugging 511 | 512 | # 513 | # Services added for the Debian GNU/Linux distribution 514 | # 515 | linuxconf 98/tcp # LinuxConf 516 | poppassd 106/tcp # Eudora 517 | poppassd 106/udp 518 | ssmtp 465/tcp smtps # SMTP over SSL 519 | moira-db 775/tcp moira_db # Moira database 520 | moira-update 777/tcp moira_update # Moira update protocol 521 | moira-ureg 779/udp moira_ureg # Moira user registration 522 | spamd 783/tcp # spamassassin daemon 523 | omirr 808/tcp omirrd # online mirror 524 | omirr 808/udp omirrd 525 | customs 1001/tcp # pmake customs server 526 | customs 1001/udp 527 | skkserv 1178/tcp # skk jisho server port 528 | predict 1210/udp # predict -- satellite tracking 529 | rmtcfg 1236/tcp # Gracilis Packeten remote config server 530 | wipld 1300/tcp # Wipl network monitor 531 | xtel 1313/tcp # french minitel 532 | xtelw 1314/tcp # french minitel 533 | support 1529/tcp # GNATS 534 | cfinger 2003/tcp # GNU Finger 535 | frox 2121/tcp # frox: caching ftp proxy 536 | ninstall 2150/tcp # ninstall service 537 | ninstall 2150/udp 538 | zebrasrv 2600/tcp # zebra service 539 | zebra 2601/tcp # zebra vty 540 | ripd 2602/tcp # ripd vty (zebra) 541 | ripngd 2603/tcp # ripngd vty (zebra) 542 | ospfd 2604/tcp # ospfd vty (zebra) 543 | bgpd 2605/tcp # bgpd vty (zebra) 544 | ospf6d 2606/tcp # ospf6d vty (zebra) 545 | ospfapi 2607/tcp # OSPF-API 546 | isisd 2608/tcp # ISISd vty (zebra) 547 | afbackup 2988/tcp # Afbackup system 548 | afbackup 2988/udp 549 | afmbackup 2989/tcp # Afmbackup system 550 | afmbackup 2989/udp 551 | xtell 4224/tcp # xtell server 552 | fax 4557/tcp # FAX transmission service (old) 553 | hylafax 4559/tcp # HylaFAX client-server protocol (new) 554 | distmp3 4600/tcp # distmp3host daemon 555 | munin 4949/tcp lrrd # Munin 556 | enbd-cstatd 5051/tcp # ENBD client statd 557 | enbd-sstatd 5052/tcp # ENBD server statd 558 | pcrd 5151/tcp # PCR-1000 Daemon 559 | noclog 5354/tcp # noclogd with TCP (nocol) 560 | noclog 5354/udp # noclogd with UDP (nocol) 561 | hostmon 5355/tcp # hostmon uses TCP (nocol) 562 | hostmon 5355/udp # hostmon uses UDP (nocol) 563 | rplay 5555/udp # RPlay audio service 564 | nrpe 5666/tcp # Nagios Remote Plugin Executor 565 | nsca 5667/tcp # Nagios Agent - NSCA 566 | mrtd 5674/tcp # MRT Routing Daemon 567 | bgpsim 5675/tcp # MRT Routing Simulator 568 | canna 5680/tcp # cannaserver 569 | sane-port 6566/tcp sane saned # SANE network scanner daemon 570 | ircd 6667/tcp # Internet Relay Chat 571 | zope-ftp 8021/tcp # zope management by ftp 572 | tproxy 8081/tcp # Transparent Proxy 573 | omniorb 8088/tcp # OmniORB 574 | omniorb 8088/udp 575 | clc-build-daemon 8990/tcp # Common lisp build daemon 576 | xinetd 9098/tcp 577 | mandelspawn 9359/udp mandelbrot # network mandelbrot 578 | git 9418/tcp # Git Version Control System 579 | zope 9673/tcp # zope server 580 | webmin 10000/tcp 581 | kamanda 10081/tcp # amanda backup services (Kerberos) 582 | kamanda 10081/udp 583 | amandaidx 10082/tcp # amanda backup services 584 | amidxtape 10083/tcp # amanda backup services 585 | smsqp 11201/tcp # Alamin SMS gateway 586 | smsqp 11201/udp 587 | xpilot 15345/tcp # XPilot Contact Port 588 | xpilot 15345/udp 589 | sgi-cmsd 17001/udp # Cluster membership services daemon 590 | sgi-crsd 17002/udp 591 | sgi-gcd 17003/udp # SGI Group membership daemon 592 | sgi-cad 17004/tcp # Cluster Admin daemon 593 | isdnlog 20011/tcp # isdn logging system 594 | isdnlog 20011/udp 595 | vboxd 20012/tcp # voice box system 596 | vboxd 20012/udp 597 | binkp 24554/tcp # binkp fidonet protocol 598 | asp 27374/tcp # Address Search Protocol 599 | asp 27374/udp 600 | csync2 30865/tcp # cluster synchronization tool 601 | dircproxy 57000/tcp # Detachable IRC Proxy 602 | tfido 60177/tcp # fidonet EMSI over telnet 603 | fido 60179/tcp # fidonet EMSI over TCP 604 | 605 | # Local services 606 | -------------------------------------------------------------------------------- /static/client.js: -------------------------------------------------------------------------------- 1 | var socket = io.connect('/'); 2 | 3 | function formatNumber(num) { 4 | // formats 12345003 as "12,345,003" 5 | var ords = []; 6 | var s = ""; 7 | var i; 8 | while(num > 0) { 9 | s = (num % 1000).toString(); 10 | 11 | // makes sure all digit groups except the first are 12 | // 0-prefixed. 13 | if (num > 999) { 14 | for (i=s.length; i<3; i++) { 15 | s = "0" + s; 16 | } 17 | } 18 | ords.unshift(s); 19 | num = (num / 1000).toFixed(0); 20 | if (ords.length > 4) break; 21 | } 22 | // type casting to string ok 23 | return ords.join(','); 24 | } 25 | 26 | /* 27 | * receive messages from server. We can get one of three messages: 28 | * - memory sample (periodic memoryUsage() results) 29 | * - partial GC stats 30 | * - full GC stats 31 | */ 32 | 33 | 34 | socket.on('temporal-sample', function(data) { 35 | $('.RSS .data').text(formatNumber(data.rss)); 36 | $('.heapTotal .data').text(formatNumber(data.heapTotal)); 37 | $('.heapUsed .data').text(formatNumber(data.heapUsed)); 38 | Graph.addTimeSample(data); 39 | }); 40 | 41 | function updateGCDataList(stats) { 42 | $('.usageTrend .data').text(stats.usage_trend.toFixed(2)); 43 | $('.fullGCCount .data').text(formatNumber(stats.num_full_gc)); 44 | $('.incrGCCount .data').text(formatNumber(stats.num_inc_gc)); 45 | $('.heapCompactions .data').text(stats.heap_compactions); 46 | } 47 | socket.on('post-full-gc-sample', function(data) { 48 | $('.currentBase .data').text(formatNumber(data.current_base)); 49 | $('.estimatedBase .data').text(formatNumber(data.estimated_base)); 50 | updateGCDataList(data); 51 | Graph.addGcData('full', data); 52 | }); 53 | 54 | socket.on('post-incremental-gc-sample', function(data) { 55 | $('.currentBase .data').text(formatNumber(data.current_base)); 56 | $('.estimatedBase .data').text(formatNumber(data.estimated_base)); 57 | updateGCDataList(data); 58 | Graph.addGcData('incremental', data); 59 | }); 60 | 61 | socket.on('heap-allocations', function(data) { 62 | // fill the first six things in the heap allocations list 63 | var items = $(".allocations").find("ul").children(); 64 | for (var i=0; i<6; i++) { 65 | var alloc = data[i]; 66 | if (!alloc) break; 67 | var item = $(items[i]); 68 | item.find(".name").text(alloc[1][0]); 69 | item.find(".data").text(alloc[0]); 70 | } 71 | }); 72 | 73 | socket.on('pause', function(data) { 74 | if (data.paused) { 75 | $('.pause-button').addClass('paused').text('GO'); 76 | $('#add_load').addClass('disabled'); 77 | } else { 78 | $('.pause-button').removeClass('paused').text('STOP'); 79 | $('#add_load').removeClass('disabled'); 80 | } 81 | }); 82 | 83 | socket.on('configure', function(data) { 84 | if (data.show) { 85 | // csl of things to show 86 | data.show.split(',').forEach(function(thing) { 87 | $("." + thing.trim()).fadeIn(); 88 | }); 89 | } 90 | if (data.title) { 91 | $(".title").text(data.title); 92 | } 93 | }); 94 | 95 | /* 96 | * Interface - the operator can: 97 | * - choose "Force Compaction", which calls gc() on the gcstats obj 98 | * - choose "Make It Busy", which adds load to the server for a second or two 99 | */ 100 | $('#do_gc').on('click', function() { 101 | socket.send("do_gc"); 102 | }); 103 | 104 | $('#add_load').on('click', function() { 105 | socket.send("add_load"); 106 | }); 107 | 108 | $('#pause').on('click', function() { 109 | socket.send("pause"); 110 | }); -------------------------------------------------------------------------------- /static/graph.js: -------------------------------------------------------------------------------- 1 | window.Graph = {}; 2 | 3 | (function() { 4 | var MB = 1000 * 1000; // actual 1024*1024 makes the resulting text confusing to compare 5 | var w = 600, 6 | h = 300, 7 | margin = 100; 8 | 9 | var vis = d3.select( document.getElementById('graph') ) 10 | .append("svg:svg") 11 | .attr("width", w) 12 | .attr("height", h); 13 | 14 | var base = vis.append("svg:g").attr("transform", "translate(0, 300)"); 15 | var g = vis.append("svg:g").attr("transform", "translate(45, 300)"); 16 | 17 | // data sets we're collecting 18 | var timeSamples = [0]; 19 | var gcFullSamples = [0]; 20 | var nextFullSample = null; 21 | // var gcIncrementalSamples = [0]; 22 | var heapSize = 0; 23 | var heapLeast = Infinity; 24 | var currentBase = 0; 25 | var estimatedBase = 0; 26 | 27 | var MAX_HISTORY = 350; 28 | 29 | function updateData(arr, data) { 30 | arr.push(data); 31 | if (arr.length > MAX_HISTORY) arr.shift(); 32 | } 33 | 34 | function drawLine(data) { 35 | var y = d3.scale.linear().domain([0, heapSize]).range([0, h]), 36 | x = d3.scale.linear().domain([0, MAX_HISTORY]).range([0, w - margin]); 37 | 38 | var line = d3.svg.line() 39 | .x(function(d,i) { return x(i); }) 40 | .y(function(d) { return -1 * y(d); }); 41 | 42 | g.append("svg:path").attr("d", line(data)); 43 | 44 | // now for a max label 45 | base.append("svg:text") 46 | .attr("class", "linktext, data") 47 | .attr('x', 550) 48 | .attr('y', 16-h) 49 | .text(heapSize.toFixed(1)); 50 | // show the estimatedBase size, tracking in y with its curve 51 | base.append("svg:text") 52 | .attr("class", "linktext, data") 53 | .attr('x', 550) 54 | .attr('y', (currentBase/heapSize || 0) * (16 - h)) 55 | .text(currentBase.toFixed(1)); 56 | // base.append("svg:text").attr("class", "linktext, data") 57 | // .attr('x', 550) 58 | // .attr('y', (heapLeast/heapSize) * (16-h)) 59 | // .text(heapLeast.toFixed(1)); 60 | } 61 | 62 | Graph.addGcData = function(type, gcData) { 63 | // fields are: 64 | // compacted: bool 65 | // stats: { num_full_gc: int 66 | // num_inc_gc: int 67 | // heap_compactions: int 68 | // usage_trend: float 69 | // estimated_base: bytes 70 | // current_base: bytes 71 | // min: { bytes: bytes, when: Date } 72 | // max: { bytes: bytes, when: Date } } 73 | // 74 | // convert all units to MB 75 | currentBase = gcData.current_base / MB; 76 | estimatedBase = gcData.estimated_base / MB; 77 | var usage_trend = gcData.usageTrend; 78 | 79 | heapLeast = Math.min(heapLeast, gcData.current_base / MB); 80 | if (type === 'full') { 81 | nextFullSample = currentBase; 82 | } 83 | }; 84 | 85 | Graph.addFullGcData = function(gcData) { 86 | Graph.addGcData('full', gcData); 87 | }; 88 | 89 | Graph.addIncrementalGcData = function(gcData) { 90 | Graph.addGcData('incremental', gcData); 91 | }; 92 | 93 | Graph.addTimeSample = function(timeData) { 94 | // fields are: 95 | // rss: bytes 96 | // heapTotal: bytes 97 | // heapUsed: bytes 98 | // 99 | // Convert all units to MB 100 | var heapUsed = timeData.heapUsed / MB; 101 | heapSize = Math.max(heapUsed, heapSize); 102 | 103 | Graph.replot({timeSample: heapUsed}); 104 | }; 105 | 106 | Graph.replot = function(sample) { 107 | var numSamples = timeSamples.length; 108 | if (sample.timeSample) { 109 | updateData(timeSamples, sample.timeSample); 110 | if (nextFullSample !== null) { 111 | updateData(gcFullSamples, nextFullSample); 112 | nextFullSample = null; 113 | } else { 114 | updateData(gcFullSamples, gcFullSamples[numSamples-1]); 115 | } 116 | } 117 | 118 | d3.selectAll('svg path').remove(); 119 | d3.selectAll('svg text').remove(); 120 | 121 | drawLine(timeSamples, "MB"); 122 | // drawLine(gcIncrementalSamples, "MB"); 123 | drawLine(gcFullSamples, "MB"); 124 | }; 125 | })(); 126 | -------------------------------------------------------------------------------- /static/head.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | Head JS The only script in your
3 | Copyright Tero Piirainen (tipiirai) 4 | License MIT / http://bit.ly/mit-license 5 | Version 0.96 6 | 7 | http://headjs.com 8 | */(function(a){function l(){var a=window.outerWidth||b.clientWidth;b.className=b.className.replace(/ (w|lt)-\d+/g,""),f("w-"+Math.round(a/100)*100),h(c.screens,function(b){a<=b&&f("lt-"+b)}),i.feature()}function h(a,b){for(var c=0,d=a.length;ct |