js-profiler
                                
                                 js-profiler copied to clipboard
                                
                                    js-profiler copied to clipboard
                            
                            
                            
                        JavaScript profiling tool, library and benchmark collection.
JS-Profiler

JavaScript profiling tool and library of profiling modules and benchmarks.
JS-Profiler allows you to compare different techniques, operators and functions regarding execution speed and memory consumption. It reports results either in text or JSON format.
JS-Profiler powers https://js-profiler.com.
Table of contents
- Installation
- Updates
- v2.3.0: New contributor and profile: shallow array copying.
- v2.2.0: Migrate to Node.js Performance Hooks
- New in version 2 & Migration
- Comparison of v1 vs. v2 profile object
- v1 profile object
- v2 profile object
 
 
- Comparison of v1 vs. v2 profile object
 
- Usage
- CLI
- Library
 
- Profiles
- array concatenation
- array copying
- comparison operators
- (de-)composition
- guards
- loops
- map access
- map creation
- object iteration
- recursion
 
- Documentation
- Changelog
- License
Installation
npm i [-gS] js-profiler
Updates
v2.5.0: New profile: (de-)composition.
v2.3.0: A new contributor and a new profile: shallow array copying.
We are happy to welcome Josh Howe as a contributor to JS-Profiler! He added a new profile comparing ways to shallow copy arrays.
Big thank you and shout out to Josh Howe!
Due to updated dependencies, JS-Profiler now requires a minimum Node.js version of 10.12.0.
v2.2.0: Migrate to Node.js Performance Hooks
As of version 2.2.0 js-profiler gathers function timing information via the Performance Hooks API instead of process.hrtime().
New in version 2 & Migration from v1.x.y to v2.x.y
- profile.testsis renamed to- profile.functions
- function.description(formerly- test.description) now contains a nice human readable description.
- function.codeSamplenow contains a short pseudo-code sample of the function under test.
- use function.codeto access the full source code of the function under test.
- function.keywordscontains keywords associated with the function under test.
- profile.keywordscontains keywords associated with this profile.
Comparison of a v1 vs. v2 profile object
Version 1.x.y profile object
// v1
{
  "name" : "recursion",
  "description" : "Recursion variations: Calculating sum of array of integers. Profile contains a simple for-loop for reference.",
  "tests" : [
      {
          "description" : "for loop sum for reference",
          "time" : {
              "average" : "1.4923μs",
              "minimum" : "1.0970μs",
              "maximum" : "38.8230μs"
          }
      }, 
      {
          "description" : "recursive sum",
          "time" : {
              "average" : "1080.3024μs",
              "minimum" : "703.3320μs",
              "maximum" : "10215.1650μs"
          }
      }, 
      {
          "description" : "tail recursive sum",
          "time" : {
              "average" : "1041.0375μs",
              "minimum" : "704.2790μs",
              "maximum" : "16476.7110μs"
          }
      }
  ],
  "fastest" : [
      {
          "description" : "for loop sum for reference",
          "time" : {
              "average" : "1.4923μs",
              "minimum" : "1.0970μs",
              "maximum" : "38.8230μs"
          }
      }
  ]
}
Version 2.x.y profile object
// v2
{
  "name": "recursion",
  "description": "Recursion.",
  "keywords": [
    "for",
    "loop",
    "recursion",
    "sum",
    "tail",
    "tailrecursion"
  ],
  "functions": [
    {
      "description": "for loop sum for reference",
      "keywords": [
        "for",
        "loop",
        "sum"
      ],
      "codeSample": "for (...) { sum += d[i] }",
      "code": "(d) => {\n    let sum = 0;\n    for (let i = 0; i < d.length; i++) {\n      sum += d[i];\n    }\n\n    return sum;\n  }",
      "time": {
        "average": "3.8774µs"
      }
    },
    {
      "description": "recursive sum",
      "keywords": [
        "recursion",
        "sum"
      ],
      "codeSample": "const f = (d) => (d && d.length && (d[0] + f(d.slice(1)))) || 0",
      "code": "(d) => (d && d.length && (d[0] + recursiveSum.f(d.slice(1)))) || 0",
      "time": {
        "average": "733.7537µs"
      }
    },
    {
      "description": "tail recursive sum",
      "keywords": [
        "recursion",
        "sum",
        "tail",
        "tailrecursion"
      ],
      "codeSample": "const f = (d, i = 0) => (!d.length && i) || f(d.slice(1), i + d[0])",
      "code": "(d, i = 0) => (!d.length && i)\n    || tailRecursiveSum.f(d.slice(1), i + d[0])",
      "time": {
        "average": "769.7328µs"
      }
    }
  ],
  "fastest": [
    {
      "description": "for loop sum for reference",
      "keywords": [
        "for",
        "loop",
        "sum"
      ],
      "codeSample": "for (...) { sum += d[i] }",
      "code": "(d) => {\n    let sum = 0;\n    for (let i = 0; i < d.length; i++) {\n      sum += d[i];\n    }\n\n    return sum;\n  }",
      "time": {
        "average": "3.8774µs"
      }
    }
  ]
}
Usage
CLI
If installed with the -g flag you can simply run js-profiler from your command line:

For further information please refer to the CLI documentation and the man page.
Library
// 1. Import the library
const jsProfiler = require('js-profiler');
// 2. Run the profiler
jsProfiler.run()
  .then((report) => {
    console.log(JSON.stringify(report, null, 2));
  });
For configuration options please refer to the Library documentation.
Available performance profiles:
array concatenation
Array concatenation variations: Combining two arrays using different techniques.
Profiled operations:
- a.concat(b)
- for (...) { a.push(b[i])}
- for (...) { b.unshift(a[i])}
- a.push.apply(a, b)
- Array.prototype.unshift.apply(b, a)
- b.reduce((arr, item) => arr.push(item), a)
- a.reduceRight((arr, item) => arr.unshift(item), b)
- [...a, ...b]
array copying
Array copying variations: creating a new array with the same elements as an existing array.
Profiled operations:
- a.slice()
- [...a]
- Array.from(a)
- new Array(...a)
- a.concat([])
- [].concat(a)
- Array.prototype.unshift.apply([], a)
- Array.prototype.unshift.apply(new Arrray(), a)
- [].push(...a)
- (new Array()).push(...a)
- b = []; for(...){ b.push(a[i]) }
- b = new Array(); for(...){ b.push(a[i]) }
- b = new Array(a.length); for(...){ b[i] = a[i] }
(de-)composition
(De-)Composition: composing objects, arrays and variables from each other.
Profiled operations:
- const { a, b } = obj
- const { a = i } = obj
- const [a, b] = arr
- const [a = i, b] = d
- const [a, b, ...tail] = d
- const a = arr[i]
- const a = arr[i] || j
- const a = obj.b
- const a = obj.b || i
- const [a, b] = [b, a]
- const c = b; b = a; a = c
comarison operators
Variable comparison operators.
Profiled operations:
- a > b
- a >= b
- a < b
- a <= b
- ==
- ===
- !=
- !==
- &&
- ||
guards
Variable guards: checking whether a variable is defined or of a certain type.
Profiled operations:
- typeof !== 'undefined'
- typeof != 'undefined'
- typeof === 'function'
- typeof == 'function'
- typeof === 'number'
- typeof == 'number'
- typeof === 'object'
- typeof == 'object'
- typeof === 'string'
- typeof == 'string'
- Array.isArray
- !!var
- !var
- isNaN(var)
- Number.isNaN(var)
- !isNaN(var)
- !Number.IsNaN(var)
- prop in obj
- obj.hasOwnProperty(prop)
- Object.prototype.hasOwnProperty.call(obj, prop)
loops
Loop variations: Converting an array of integers into an array of booleans satisfying a conjunction of two simple relational operations.
Profiled operations:
- [].forEach() => []
- for(i++, i < d.length) => []
- for(i++, i < len) => []
- while(i--) => []
- [].map() => []
- while(i < d.length) => []
- while(i < len) => []
- do { } while (i < d.length)
- do { } while (i < len)
- for (prop of [])
map access
Object literal vs. Map: retrieving values.
Profiled operations:
- Map.get()
- {}.prop
map creation
Object literal vs. Map: creating a map.
Profiled operations:
- Map.set()
- new Map([props])
- {}.prop = val
- Object.defineProperty({}, prop, desc)
- Object.defineProperties({}, props)
- { ...props }
object iteration
Object iteration: different ways of iterating over properties of an object and concatenating property names into a single string.
Profiled operations:
- for (const prop in obj) {}
- Object.keys(obj).forEach()
- Object.entries(obj).forEach()
- for (prop of Map.keys())
- for (prop of Object.keys(obj))
- for (prop of Object.keys(obj) { obj.hasOwnProperty(prop) && ... })
- for (prop of Object.getOwnPropertyNames(obj))
- Object.getOwnPropertyNames(obj).forEach()
recursion
Recurstion variations: Calculating sum of array of integers. Profile contains a simple for-loop for reference.
Profiled operations:
- for loop sum for reference
- recursive sum
- tail recursive sum
