├── .gitignore ├── .jshintignore ├── .jshintrc ├── LICENSE ├── README.md ├── example └── cpu-blocking.js ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | site/public/css/*.css 4 | site/properties.json 5 | CPU-* 6 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { "asi": true 2 | , "boss": true 3 | , "browser": true 4 | , "camelcase": true 5 | , "curly": false 6 | , "devel": false 7 | , "devel": true 8 | , "eqeqeq": true 9 | , "eqnull": true 10 | , "es5": false 11 | , "evil": false 12 | , "immed": false 13 | , "indent": 2 14 | , "jquery": true 15 | , "latedef": false 16 | , "laxbreak": true 17 | , "laxcomma": true 18 | , "maxcomplexity": 6 19 | , "maxdepth": 4 20 | , "maxstatements": 25 21 | , "maxlen": 120 22 | , "newcap": true 23 | , "node": true 24 | , "noempty": false 25 | , "nonew": true 26 | , "predef": 27 | [ "Backbone" 28 | , "describe" 29 | , "it" 30 | , "before" 31 | , "beforeEach" 32 | , "after" 33 | , "afterEach" 34 | ] 35 | , "quotmark": "single" 36 | , "smarttabs": true 37 | , "strict": false 38 | , "trailing": false 39 | , "undef": true 40 | , "unused": true 41 | , "-W079": true 42 | , "-W069": true 43 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Tom Gallacher 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chrome-cpu-profiler 2 | 3 | Visulise your applications performance in chrome using flame-graphs! 4 | 5 | ## Installation 6 | 7 | npm install --save chrome-cpu-profiler 8 | 9 | ## Usage 10 | 11 | var profiler = require('chrome-cpu-profiler') 12 | profiler.startProfiling('cpu-block') 13 | var data = profiler.stopProfiling('cpu-block') 14 | profiler.writeFile(data) 15 | 16 | ## Credits 17 | Built by Tom Gallacher [@tomgco](http://twitter.com/tomgco). 18 | 19 | ## Licence 20 | Licensed under the [New BSD License](http://opensource.org/licenses/bsd-license.php) 21 | -------------------------------------------------------------------------------- /example/cpu-blocking.js: -------------------------------------------------------------------------------- 1 | var profiler = require('../') 2 | profiler.startProfiling('cpu-block') 3 | 4 | function bootstrap() { 5 | function pre(cb) { 6 | var num = 0 7 | for (var i = 1e6 - 1; i >= 0; i--) { 8 | num++ 9 | } 10 | return cb() 11 | } 12 | 13 | function post() { 14 | profiler.writeFile(profiler.stopProfiling('cpu-block')) 15 | } 16 | 17 | function init(cb) { 18 | for (var i = 1e8 - 1; i >= 0; i--) { 19 | var a = 16 + 87 20 | a = a - 10 21 | } 22 | cb() 23 | } 24 | 25 | pre(function preInner() { 26 | init(function initInner() { 27 | for (var i = 1e8 - 1; i >= 0; i--) { 28 | var a = 1 + 1 29 | a = a + 1 30 | } 31 | pre(function preInner() { 32 | init(function initInner() { 33 | for (var i = 1e8 - 1; i >= 0; i--) { 34 | var a = 1 + 1 35 | a = a + 1 36 | } 37 | post() 38 | }) 39 | }) 40 | }) 41 | }) 42 | } 43 | 44 | bootstrap() -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var profiler = require('cpu-profiler') 2 | , clone = require('lodash.clone') 3 | , fs = require('fs') 4 | , timings = {} 5 | 6 | function profile(item) { 7 | var data = clone(item.topRoot) 8 | followChild(item.topRoot, data) 9 | return { head: data 10 | , startTime: formatV8Time(item.startTime) 11 | , endTime: formatV8Time(item.endTime) 12 | , samples: generateSamples(item) 13 | } 14 | } 15 | 16 | function formatV8Time (time) { 17 | return time / 1000000 18 | } 19 | 20 | function generateSamples(profile) { 21 | var samples = [] 22 | , count = profile.samplesCount 23 | 24 | for (var i = 0; i < count; i++) { 25 | samples[i] = profile.getSample(i).id 26 | } 27 | 28 | return samples 29 | } 30 | 31 | function followChild(source, dest) { 32 | // Display url with path 33 | dest.url = dest.scriptName.replace(source.rootPath, '') 34 | // New chrome wants a hit count, this add backwards compatibility 35 | // hopefully these are the same 36 | if (typeof dest.hitCount === 'undefined') 37 | dest.hitCount = dest.selfSamplesCount 38 | 39 | // Mocking as not provided? 40 | // if (typeof dest.sourceId === 'undefined') 41 | // dest.sourceId = 0 42 | 43 | // Sometimes we can have children count of zero so lets add no children 44 | // so flame graph works 45 | if (!dest.children) 46 | dest.children = [] 47 | 48 | // If the node has children then continue 49 | if (source.childrenCount > 0) { 50 | for (var i = 0; i < source.childrenCount; i++) { 51 | var child = source.getChild(i) 52 | , newChild = clone(child) 53 | 54 | followChild(child, newChild) 55 | dest.children.push(newChild) 56 | } 57 | } 58 | } 59 | 60 | // Wrap start profiling to grab current time 61 | profile.startProfiling = function (name) { 62 | // true to record samples 63 | return profiler.startProfiling(name, true) 64 | } 65 | 66 | // Wrap stop profiling to format before returning 67 | profile.stopProfiling = function (name) { 68 | var data = profile(profiler.stopProfiling(name)) 69 | if (timings[name]) { 70 | delete timings[name] 71 | } 72 | return data 73 | } 74 | 75 | profile.writeFile = function (file, data, cb) { 76 | if (!cb) { 77 | cb = function () {} 78 | } 79 | if (typeof file !== 'string') { 80 | data = file 81 | file = false 82 | } 83 | if (typeof data === 'object') { 84 | data = JSON.stringify(data) 85 | } 86 | fs.writeFile(file || 'CPU-' + Date.now() + '.cpuprofile', data, cb) 87 | } 88 | 89 | module.exports = profile 90 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chrome-cpu-profiler", 3 | "version": "1.0.2", 4 | "description": "Convert the output of v8-profiler to work in google chrome", 5 | "main": "index.js", 6 | "scripts": { 7 | "lint": "./node_modules/.bin/jshint . --reporter=./node_modules/jshint-full-path/index.js" 8 | }, 9 | "publishConfig": { 10 | "registry": "http://registry.npmjs.org" 11 | }, 12 | "author": "Tom Gallacher ", 13 | "license": "MIT", 14 | "dependencies": { 15 | "cpu-profiler": "git+ssh://git@github.com:tomgco/strong-cpu-profiler.git#release/2.0.0", 16 | "lodash.clone": "~2.4.1" 17 | }, 18 | "devDependencies": { 19 | "jshint": "~2.1.11", 20 | "jshint-full-path": "~0.1.0" 21 | } 22 | } 23 | --------------------------------------------------------------------------------