├── .npmignore ├── shot.png ├── package.json ├── .gitignore ├── index.js └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | shot.png 2 | -------------------------------------------------------------------------------- /shot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jondot/react-native-slowlog/HEAD/shot.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-slowlog", 3 | "version": "1.0.2", 4 | "description": "A tiny in-process profiler for React Native", 5 | "main": "index.js", 6 | "scripts": { 7 | }, 8 | "author": "Dotan Nahum", 9 | "license": "MIT", 10 | "devDependencies": { 11 | "babel-core": "^6.7.6", 12 | "babel-loader": "^6.2.4", 13 | "babel-preset-es2015": "^6.6.0", 14 | "babel-preset-stage-0": "^6.5.0", 15 | "webpack": "^1.12.15", 16 | "webpack-init": "0.0.4" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .AppleDouble 3 | .LSOverride 4 | 5 | # Icon must end with two \r 6 | Icon 7 | 8 | 9 | # Thumbnails 10 | ._* 11 | 12 | # Files that might appear in the root of a volume 13 | .DocumentRevisions-V100 14 | .fseventsd 15 | .Spotlight-V100 16 | .TemporaryItems 17 | .Trashes 18 | .VolumeIcon.icns 19 | 20 | # Directories potentially created on remote AFP share 21 | .AppleDB 22 | .AppleDesktop 23 | Network Trash Folder 24 | Temporary Items 25 | .apdisk 26 | # Logs 27 | logs 28 | *.log 29 | npm-debug.log* 30 | 31 | # Runtime data 32 | pids 33 | *.pid 34 | *.seed 35 | 36 | # Directory for instrumented libs generated by jscoverage/JSCover 37 | lib-cov 38 | 39 | # Coverage directory used by tools like istanbul 40 | coverage 41 | 42 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 43 | .grunt 44 | 45 | # node-waf configuration 46 | .lock-wscript 47 | 48 | # Compiled binary addons (http://nodejs.org/api/addons.html) 49 | build/Release 50 | 51 | # Dependency directories 52 | node_modules 53 | jspm_packages 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional REPL history 59 | .node_repl_history 60 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import fbjsPerformanceNow from 'fbjs/lib/performanceNow' 2 | const performanceNow = global.nativePerformanceNow || fbjsPerformanceNow 3 | 4 | const bencherExcludes = { 5 | 'constructor':true, 6 | } 7 | 8 | const defaultOpts={excludes: bencherExcludes, log: console, verbose: false, threshold: 16} 9 | 10 | function slowlog(that, exp=/.*/, opts={}){ 11 | if(!__DEV__){ 12 | return [] 13 | } 14 | 15 | let bound = [] 16 | let componentName = that.constructor.displayName || that.constructor.name || 'Class' 17 | const { threshold, log:c, verbose, excludes } = {...defaultOpts, ...opts} 18 | 19 | c.log(`slowlog: DEV MODE SLOWLOG ENABLED FOR <${componentName}>`) 20 | 21 | for (let name of Object.getOwnPropertyNames(Object.getPrototypeOf(that))) { 22 | let f = that[name] 23 | const benchkey = `${componentName}.${name}` 24 | if(typeof f === 'function' && !excludes[name] && exp.test(name)){ 25 | that[name] = function(){ 26 | const start = performanceNow() 27 | const res = f.apply(that, arguments) 28 | const timing = performanceNow() - start 29 | 30 | if(timing > threshold){ 31 | c.warn(`slowlog: ${benchkey} was slow at: ${timing.toFixed(3)}ms`) 32 | }else if(verbose){ 33 | c.log(benchkey, timing.toFixed(6)) 34 | } 35 | return res 36 | } 37 | bound.push(name) 38 | } 39 | } 40 | return bound 41 | } 42 | 43 | export default slowlog 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Slowlog 2 | 3 | A high-performance timer for React Native that helps you track big performance problems. 4 | Use it as a first line of defense, before tools like system trace and perftools. 5 | 6 | ![](shot.png) 7 | 8 | ## Quickstart 9 | 10 | In your React Native project run: 11 | 12 | `$ npm i -S react-native-slowlog` 13 | 14 | This is added as a runtime dependency, and `slowlog` will only run in developer mode (using the `__DEV__` flag). 15 | 16 | To use `slowlog` apply it to your component this way: 17 | 18 | ```javascript 19 | class Master extends Component { 20 | constructor(props){ 21 | super(props) 22 | slowlog(this, /.*/) 23 | 24 | this.state = this.getDataSource(props) 25 | this.shouldComponentUpdate = shouldComponentUpdate.bind(this) 26 | } 27 | ... 28 | } 29 | ``` 30 | 31 | ## Options 32 | 33 | You can apply `slowlog` differently based on your needs: 34 | 35 | ```javascript 36 | slowlog([this], [regex matching methods], { verbose: false, threshold: 16, log: console, excludes: [dict of excluded methods] }) 37 | ``` 38 | 39 | * `verbose` - will output all timing information to console, and just slow operations to yellowbox 40 | * `threshold` - in milliseconds. Anything above that goes to yellowbox 41 | * `log` - a `console`-like object. Anything that responds to `.log([msg])` and `.warn([msg])` 42 | * `excludes` - a dict containing an exclusion list, like so {foobar:true, constructor:true} and so on. If you change this, remember to always 43 | include `constructor` 44 | 45 | 46 | # Contributing 47 | 48 | Fork, implement, add tests, pull request, get my everlasting thanks and a respectable place here :). 49 | 50 | # Copyright 51 | 52 | Copyright (c) 2016 [Dotan Nahum](http://gplus.to/dotan) [@jondot](http://twitter.com/jondot). See [LICENSE](LICENSE.txt) for further details. 53 | 54 | 55 | --------------------------------------------------------------------------------