├── AUTHORS ├── package.json ├── scripts └── preinstall.sh ├── README.md ├── LICENSE └── bin └── nodeprofile /AUTHORS: -------------------------------------------------------------------------------- 1 | # Authors ordered by first contribution. 2 | 3 | Mathias Pettersson 4 | Brian Noguchi 5 | Paul Bergeron 6 | Sam Day 7 | Vadim Semenov 8 | Christian Rishøj 9 | Fredrick Galoso -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "profile", 3 | "description": "A script that makes profiling node.js apps easier.", 4 | "version": "0.0.10", 5 | "author" : "Mathias Pettersson ", 6 | "bin": { "nodeprofile": "./bin/nodeprofile" }, 7 | "engines": { "node": ">= 0.2.0" }, 8 | "scripts" : { "preinstall" : "./scripts/preinstall.sh" } 9 | } 10 | -------------------------------------------------------------------------------- /scripts/preinstall.sh: -------------------------------------------------------------------------------- 1 | PLATFORM=`uname` 2 | if [ "$PLATFORM" = "Darwin" ] 3 | then 4 | if [ -z "$(locate mac-tick-processor)" ] 5 | then 6 | echo "Couldn't find mac-tick-processor" 7 | exit 1 8 | fi 9 | elif [ "$PLATFORM" = "Linux" ] 10 | then 11 | if [ -z "$(locate linux-tick-processor.py)" ] 12 | then 13 | echo "Couldn't find linux-tick-processor.py" 14 | exit 1 15 | fi 16 | else 17 | echo "Unknown platform" 18 | fi 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-profile 2 | 3 | A script that makes profiling node.js apps a little easier. 4 | Compatible with node v0.6.x 5 | 6 | ## Installation 7 | 8 | Via [npm](http://github.com/isaacs/npm): 9 | 10 | $ npm install profile 11 | 12 | ## Usage 13 | ### Output to stdout 14 | `> nodeprofile yourapp.js` 15 | ### Output to file 16 | `> nodeprofile yourapp.js -o=profile.txt` 17 | ### Lazy profiling (profiling disabled on startup) 18 | This is useful if you want to profile certain areas of your code using [bnoordhuis/node-profiler](https://github.com/bnoordhuis/node-profiler): 19 | 20 | `> nodeprofile yourapp.js --prof_lazy` 21 | 22 | ## "Dependencies" 23 | * python 24 | * [SCONS](http://www.scons.org/) (used to build the V8 debugger on first use) 25 | * That the `locate` command can find a copy of `linux-tick-processor` (or `mac-tick-processor` on OS X). This is bundled with node.js. 26 | 27 | ## Pre-configuration 28 | 29 | $ cd /usr/src/node 30 | $ cd deps/v8 31 | $ scons prof=on 32 | $ export PATH="${PATH}:/usr/src/node/deps/v8" 33 | 34 | ## Output 35 | 36 | 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Mathias Pettersson, mape@mape.me 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /bin/nodeprofile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var exec = require('child_process').exec 4 | , fs = require('fs') 5 | , os = require('os') 6 | , path = require('path'); 7 | 8 | process.addListener('SIGINT', function () {}); 9 | 10 | var logName = 'profile-'+Date.now()+Math.floor(Math.random()*10000)+'.log'; 11 | var args = {}; 12 | var profLazy = false; 13 | process.argv.splice(3).join(' ').split('-').forEach(function (arg) { 14 | var argParts = arg.split('='); 15 | 16 | if(argParts[0].trim() == "prof_lazy") { 17 | profLazy = true; 18 | } 19 | if (argParts[0] && argParts[1]) { 20 | args[argParts[0].trim()] = argParts[1].trim(); 21 | } 22 | }); 23 | 24 | if(path.extname(process.argv[2]) === '.coffee') { 25 | var command = 'coffee --nodejs "--prof'+(profLazy ? ' --prof_lazy':'')+' --log-snapshot-positions --logfile='+logName+'" '+process.argv[2]; 26 | } else { 27 | var command = 'node --prof'+(profLazy ? ' --prof_lazy':'')+' --log-snapshot-positions --logfile='+logName+' '+process.argv[2]; 28 | } 29 | 30 | var tick_processor = "linux-tick-processor" 31 | 32 | if(os.type() === 'Darwin') { 33 | tick_processor = "mac-tick-processor" 34 | } 35 | 36 | console.log('Running: '+command); 37 | 38 | exec(command).on('exit', function (code, signal) { 39 | exec('locate '+tick_processor, function (err, stdout, stderr) { 40 | if (err) throw err; 41 | 42 | var tickLocations = stdout.trim().split('\n').filter( 43 | function(location) { 44 | location = location.split('/'); 45 | return (location[location.length - 1] === tick_processor); 46 | }); 47 | if (tickLocations[0]) { 48 | exec(tickLocations[0]+' '+logName, function (err, stdout, stderr) { 49 | if (!err) { 50 | if (args.o) { 51 | fs.writeFile(args.o, stdout, function (err) { 52 | if (err) { 53 | throw err; 54 | } else { 55 | console.log(style(33, '\nSaved output to '+args.o)); 56 | } 57 | }); 58 | } else { 59 | console.log(colorFormat(stdout)); 60 | } 61 | } else { 62 | console.log(style(31, '\nCould not generate profile.\n\n'+err.message)); 63 | } 64 | 65 | fs.unlink(logName, function (err) { 66 | if (err) { 67 | throw err; 68 | } 69 | console.log('Successfully deleted temporary: '+logName); 70 | }); 71 | }); 72 | } else { 73 | throw new Error('Could not find ' + tick_processor); 74 | } 75 | }); 76 | }); 77 | 78 | function colorFormat(profileLog) { 79 | var lines = profileLog.split('\n'); 80 | var newLog = []; 81 | 82 | lines.forEach(function (line) { 83 | if (line.match(/ *\[.*\]/)) { 84 | newLog.push(style(33, line)); 85 | } else if (line.match(/^[^ ]/)) { 86 | newLog.push(style(37, line)); 87 | } else if (line.match(/^ [^ 0-9]/)) { 88 | newLog.push(style(35, line)); 89 | } else { 90 | newLog.push(line.replace(/ *([^ ]+)/, function (match) { 91 | return style(31, match); 92 | }).replace(/([0-9]+\.[0-9]+%)/g, function (match) { 93 | return style(33, match); 94 | })); 95 | } 96 | }); 97 | 98 | return newLog.join('\n'); 99 | } 100 | 101 | function style(colorCode, str) { 102 | return '\x1B[1m\x1B['+colorCode+'m'+str+'\x1B[0m'; 103 | } 104 | --------------------------------------------------------------------------------