Nonchalant Programming Master

    js-profiler

    2.5.3 • Public • Published

    JS-Profiler

    https://js-profiler.com

    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.

    NPM

    CircleCI

    Table of contents

    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.tests is renamed to profile.functions
    • function.description (formerly test.description) now contains a nice human readable description.
    • function.codeSample now contains a short pseudo-code sample of the function under test.
    • use function.code to access the full source code of the function under test.
    • function.keywords contains keywords associated with the function under test.
    • profile.keywords contains 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:

    Intro

    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

    Documentation

    Changelog

    License

    Install

    npm i js-profiler

    DownloadsWeekly Downloads

    55

    Version

    2.5.3

    License

    MIT

    Unpacked Size

    85.2 kB

    Total Files

    31

    Last publish

    Collaborators

    • haensl