├── .gitignore ├── .travis.yml ├── example.js ├── package.json ├── LICENSE ├── index.js ├── browser.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | coverage/ 3 | tmp/ 4 | dist/ 5 | npm-debug.log* 6 | .DS_Store 7 | .nyc_output 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | node_js: 2 | - "7" 3 | - "8" 4 | - "9" 5 | sudo: false 6 | language: node_js 7 | script: "npm run test" 8 | # after_success: "npm i -g codecov && npm run coverage && codecov" 9 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | var nanotiming = require('./') 2 | 3 | try { 4 | var hooks = require('perf_hooks') 5 | var nanot = nanotiming('my-loop') // Start profiling 6 | } catch (e) { 7 | console.log('perf_hooks not available, exiting') 8 | process.exit(1) 9 | } 10 | var performance = hooks.performance 11 | 12 | var i = 10 13 | while (--i) console.log(i) 14 | 15 | // Stop profiling 16 | nanot() 17 | 18 | var timings = performance.getEntries() 19 | var timing = timings[timings.length - 1] 20 | console.log(timing.name, timing.duration) // log the last entry 21 | performance.clearMeasures(timing.name) // be a good citizen and free after use 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nanotiming", 3 | "description": "Small timing library", 4 | "repository": "choojs/nanotiming", 5 | "version": "7.3.1", 6 | "main": "index.js", 7 | "browser": { 8 | "./index.js": "./browser.js", 9 | "assert": "nanoassert" 10 | }, 11 | "scripts": { 12 | "start": "node .", 13 | "test": "standard", 14 | "coverage": "nyc report --reporter=text-lcov > coverage.lcov" 15 | }, 16 | "dependencies": { 17 | "nanoassert": "^1.1.0", 18 | "nanoscheduler": "^1.0.2" 19 | }, 20 | "devDependencies": { 21 | "dependency-check": "^2.8.0", 22 | "nyc": "^10.2.0", 23 | "standard": "^10.0.1", 24 | "tape": "^4.6.3" 25 | }, 26 | "keywords": [ 27 | "browser", 28 | "timing", 29 | "mark", 30 | "measure", 31 | "performance" 32 | ], 33 | "license": "MIT" 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Yoshua Wuyts 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert') 2 | 3 | var perf 4 | nanotiming.disabled = true 5 | try { 6 | perf = require('perf_hooks').performance 7 | nanotiming.disabled = process.env.DISABLE_NANOTIMING || !perf.mark 8 | } catch (e) { } 9 | 10 | module.exports = nanotiming 11 | 12 | function nanotiming (name) { 13 | if (typeof window !== 'undefined') return require('./browser.js')(name) // electron suport 14 | 15 | assert.equal(typeof name, 'string', 'nanotiming: name should be type string') 16 | 17 | if (nanotiming.disabled) return noop 18 | 19 | var uuid = (perf.now() * 10000).toFixed() % Number.MAX_SAFE_INTEGER 20 | var startName = 'start-' + uuid + '-' + name 21 | perf.mark(startName) 22 | 23 | function end (cb) { 24 | var endName = 'end-' + uuid + '-' + name 25 | perf.mark(endName) 26 | 27 | var err = null 28 | try { 29 | var measureName = name + ' [' + uuid + ']' 30 | perf.measure(measureName, startName, endName) 31 | perf.clearMarks(startName) 32 | perf.clearMarks(endName) 33 | } catch (e) { err = e } 34 | if (cb) cb(err, name) 35 | } 36 | 37 | end.uuid = uuid 38 | return end 39 | } 40 | 41 | function noop (cb) { 42 | if (cb) { 43 | cb(new Error('nanotiming: performance API unavailable')) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /browser.js: -------------------------------------------------------------------------------- 1 | var scheduler = require('nanoscheduler')() 2 | var assert = require('assert') 3 | 4 | var perf 5 | nanotiming.disabled = true 6 | try { 7 | perf = window.performance 8 | nanotiming.disabled = window.localStorage.DISABLE_NANOTIMING === 'true' || !perf.mark 9 | } catch (e) { } 10 | 11 | module.exports = nanotiming 12 | 13 | function nanotiming (name) { 14 | assert.equal(typeof name, 'string', 'nanotiming: name should be type string') 15 | 16 | if (nanotiming.disabled) return noop 17 | 18 | var uuid = (perf.now() * 10000).toFixed() % Number.MAX_SAFE_INTEGER 19 | var startName = 'start-' + uuid + '-' + name 20 | perf.mark(startName) 21 | 22 | function end (cb) { 23 | var endName = 'end-' + uuid + '-' + name 24 | perf.mark(endName) 25 | 26 | scheduler.push(function () { 27 | var err = null 28 | try { 29 | var measureName = name + ' [' + uuid + ']' 30 | perf.measure(measureName, startName, endName) 31 | perf.clearMarks(startName) 32 | perf.clearMarks(endName) 33 | } catch (e) { err = e } 34 | if (cb) cb(err, name) 35 | }) 36 | } 37 | 38 | end.uuid = uuid 39 | return end 40 | } 41 | 42 | function noop (cb) { 43 | if (cb) { 44 | scheduler.push(function () { 45 | cb(new Error('nanotiming: performance API unavailable')) 46 | }) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nanotiming [![stability][0]][1] 2 | [![npm version][2]][3] [![build status][4]][5] 3 | [![downloads][8]][9] [![js-standard-style][10]][11] 4 | 5 | Small timing library. Useful to integrate into libraries that have multiple 6 | methods. Works both in the browser and Node. To use this in Node, make sure you 7 | are using v8.5.0 or greater. 8 | 9 | ## Usage 10 | ```js 11 | var nanotiming = require('nanotiming') 12 | // require 'perf_hooks' for Node environment 13 | // var performance = require('perf_hooks').performance 14 | 15 | var timing = nanotiming('my-loop') // Start profiling 16 | 17 | var i = 1000 18 | while (--i) console.log(i) 19 | 20 | // Stop profiling 21 | timing() 22 | 23 | // in the browser 24 | var timings = window.performance.getEntries() 25 | var timing = timings[timings.length - 1] 26 | console.log(timing.name, timing.duration) // log the last entry 27 | window.performance.clearMeasures(timing.name) // be a good citizen and free after use 28 | 29 | // in Node 30 | var timings = performance.getEntries() 31 | var timing = timings[timings.length - 1] 32 | console.log(timing.name, timing.duration) // log the last entry 33 | performance.clearMeasures(timing.name) // be a good citizen and free after use 34 | ``` 35 | 36 | ## Timing names 37 | Timings inside the view are appended with a unique UUID so they can be cleared 38 | individually. While there's no strict format for timing formats, we recommend 39 | using a format along these lines: 40 | ```txt 41 | choo.render [12356778] 42 | choo.route('/') [13355671] 43 | choo.emit('log:debug') [13355675] 44 | ``` 45 | 46 | ## Disabling timings 47 | Performance timers are still a somewhat experimental technology. While they're 48 | a great idea conceptually, there might be bugs. To disable timings complete, in 49 | the browser set: 50 | ```js 51 | window.localStorage.DISABLE_NANOTIMING = true 52 | ``` 53 | Alternatively, in Node set: 54 | ```js 55 | process.env.DISABLE_NANOTIMING = true 56 | ``` 57 | 58 | ## API 59 | ### `endTiming = nanotiming(name)` 60 | Start a new timing. 61 | 62 | ### `endTiming.uuid` 63 | The unique ID created for the timing. 64 | 65 | ### `endTiming([cb(err, name)])` 66 | Close the timing. Measuring the timing is done inside a `requestIdleCallback()` 67 | (browser) or `setTimeout` (node) tick, so it might not be available 68 | immediately. If a callback is passed it will be called with an error (if 69 | measuring wasn't successful) and the timing's name. 70 | 71 | ## License 72 | [MIT](https://tldrlegal.com/license/mit-license) 73 | 74 | [0]: https://img.shields.io/badge/stability-experimental-orange.svg?style=flat-square 75 | [1]: https://nodejs.org/api/documentation.html#documentation_stability_index 76 | [2]: https://img.shields.io/npm/v/nanotiming.svg?style=flat-square 77 | [3]: https://npmjs.org/package/nanotiming 78 | [4]: https://img.shields.io/travis/choojs/nanotiming/master.svg?style=flat-square 79 | [5]: https://travis-ci.org/choojs/nanotiming 80 | [6]: https://img.shields.io/codecov/c/github/choojs/nanotiming/master.svg?style=flat-square 81 | [7]: https://codecov.io/github/choojs/nanotiming 82 | [8]: http://img.shields.io/npm/dm/nanotiming.svg?style=flat-square 83 | [9]: https://npmjs.org/package/nanotiming 84 | [10]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square 85 | [11]: https://github.com/feross/standard 86 | --------------------------------------------------------------------------------