Giter Site home page Giter Site logo

jamiemason / karma-benchmark Goto Github PK

View Code? Open in Web Editor NEW
90.0 8.0 16.0 1.9 MB

A Karma plugin to run Benchmark.js over multiple browsers with CI compatible output.

License: MIT License

JavaScript 7.69% TypeScript 92.31%
karma benchmarking performance javascript nodejs benchmark karma-plugin profiling

karma-benchmark's Introduction

karma-benchmark

A Karma plugin to run Benchmark.js over multiple browsers with CI compatible output.

NPM version NPM downloads Build Status Maintainability

Table of Contents

๐ŸŒฉ Installation

npm install --save-dev benchmark karma-benchmark

๐Ÿ•ต๐Ÿพโ€โ™€๏ธ Reporters

โš–๏ธ Configuration

In karma.conf.js, add 'benchmark' to the list of frameworks:

module.exports = config => {
  config.set({
    autoWatch: false,
    browsers: ["Chrome"],
    concurrency: 1,
    files: ["bench/**/*.bench.js"],
    frameworks: ["benchmark"],
    singleRun: true
  });
};

Terminal Reporting

Now let's add karma-benchmarkjs-reporter by @FormidableLabs to report results to the Terminal:

npm install --save-dev karma-benchmarkjs-reporter

In karma.conf.js, add 'benchmark' to the list of reporters:

module.exports = (config) => {
  config.set({
    autoWatch: false,
    browsers: ['Chrome'],
    concurrency: 1,
    files: ['bench/**/*.bench.js'],
    frameworks: ['benchmark'],
+   reporters: ['benchmark'],
    singleRun: true
  });
};

JUnit Reporting

To feed our data into Continuous Integration, we can use the karma-junit-reporter.

npm install --save-dev karma-junit-reporter

In karma.conf.js, add junit to the list of reporters and configure the reporter accordingly:

module.exports = (config) => {
  config.set({
    autoWatch: false,
    browsers: ['Chrome'],
    concurrency: 1,
    files: ['bench/**/*.bench.js'],
    frameworks: ['benchmark'],
+   junitReporter: {
+     outputDir: 'reports',
+     outputFile: 'benchmark.xml'
+   },
-   reporters: ['benchmark'],
+   reporters: ['benchmark', 'junit'],
    singleRun: true
  });
};

Data Visualisation Reporting

With a free plot.ly account, we can generate visualisations using the karma-benchmark-plotly-reporter by @etpinard.

npm install --save-dev karma-benchmark-plotly-reporter

In karma.conf.js, add benchmark-plotly to the list of reporters and configure the reporter accordingly:

module.exports = (config) => {
  config.set({
    autoWatch: false,
+   benchmarkPlotlyReporter: {
+     username: '<your username>',
+     apiKey: '<your api key>',
+     cloudFilename: 'plotly-example',
+     imageFilename: 'plotly-example.png'
+   },
    browsers: ['Chrome'],
    concurrency: 1,
    files: ['bench/**/*.bench.js'],
    frameworks: ['benchmark'],
    junitReporter: {
      outputDir: 'reports',
      outputFile: 'benchmark.xml'
    },
-   reporters: ['benchmark', 'junit'],
+   reporters: ['benchmark', 'benchmark-plotly', 'junit'],
    singleRun: true
  });
};

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ”ฌ Writing Benchmarks

Benchmarks can be written by using the original Benchmark.js API, but a wrapper API is also provided by karma-benchmark in the form of the suite and benchmark globals. The karma-benchmark API aims to make the process of writing Benchmarks feel familiar to users of Jasmine or Jest.

In this example, a suite is defined that pits _.each against the native Array.forEach method:

suite("Array iteration", () => {
  benchmark("_.each", () => {
    _.each([1, 2, 3], el => {
      return el;
    });
  });

  benchmark("native forEach", () => {
    [1, 2, 3].forEach(el => {
      return el;
    });
  });
});

Suite options

Suite options are the same as in Benchmark.js with one exception: onStart and onComplete can be set at the suite level.

See the Benchmark.js Suite constructor API docs for a full list of options.

suite(
  "Array iteration",
  () => {
    benchmark("_.each", () => {
      _.each(this.list, number => {
        return number;
      });
    });

    benchmark("native forEach", () => {
      this.list.forEach(number => {
        return number;
      });
    });
  },
  {
    onCycle(event) {
      var suite = this;
      var benchmark = event.target;
      console.log("Cycle completed for " + suite.name + ": " + benchmark.name);
    },
    onStart() {
      this.list = [5, 4, 3];
    },
    onComplete() {
      this.list = null;
    }
  }
);

Benchmark options

Benchmark options are the same as in Benchmark.js. If setup and teardown are passed to benchmark(), they will override setup and teardown from the suite. Pass null or undefined to remove them.

See the Benchmark.js Benchmark constructor API docs for a full list of options.

suite("Iteration", () => {
  benchmark(
    "_.each with array",
    () => {
      _.each(this.list, number => {
        return number;
      });
    },
    {
      setup() {
        this.list = ["a", "b", "c"];
      },
      teardown() {
        delete this.list;
      }
    }
  );

  benchmark(
    "_.each with object",
    () => {
      _.each(this.list, number => {
        return number;
      });
    },
    {
      setup() {
        this.list = { 0: "a", 1: "b", 2: "c" };
      },
      teardown() {
        delete this.list;
      }
    }
  );
});

Running only a specific benchmark or suite

To run only a specific benchmark, use benchmark.only() or bbenchmark() instead of benchmark():

benchmark.only(() => {
  // Only this benchmark will run
  // bbenchmark() does the same thing
});

benchmark(() => {
  // This benchmark won't run
});

The same applies to suites with suite.only() and ssuite().

Skipping benchmarks & suites

To skip a benchmark, use benchmark.skip() or xbenchmark() instead of benchmark():

benchmark.skip(() => {
  // This benchmark won't run
  // xbenchmark() does the same thing
});

benchmark(() => {
  // This and all other benchmarks will run
});

The same applies to suites with suite.skip() and xsuite().

๐Ÿ™‹๐Ÿพโ€โ™‚๏ธ Getting Help

Get help with issues by creating a Bug Report or discuss ideas by opening a Feature Request.

๐Ÿ‘€ Other Projects

If you find my Open Source projects useful, please share them โค๏ธ

๐Ÿค“ Author

I'm Jamie Mason from Leeds in England, I began Web Design and Development in 1999 and have been Contracting and offering Consultancy as Fold Left Ltd since 2012. Who I've worked with includes Sky Sports, Sky Bet, Sky Poker, The Premier League, William Hill, Shell, Betfair, and Football Clubs including Leeds United, Spurs, West Ham, Arsenal, and more.

Follow JamieMason on GitHubย ย ย ย ย ย Follow fold_left on Twitter

karma-benchmark's People

Contributors

jacobrask avatar jamiemason avatar jared-sprague avatar lazd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

karma-benchmark's Issues

Triggering failed benchmarks

I was wondering if there would be a way to use this in the form of

  • compare foo with bar, and if foo is 10% slower then bar fail the suite.

anothe useful way would be to fail a suite if performed less then x operations per second.

Add setup and teardown methods

Standard

benchmark('_.each', function () {
  when('iterating over an array', function () {
    _.each([1, 2, 3], function(el){
      return el;
    });
  });
});

With setup and teardown

when('iterating over an array', {
  before: function () {
    // body...
  },
  run: function () {
    _.each([1, 2, 3], function(el){
      return el;
    });
  },
  after: function () {
    // body...
  }
});

Error "TypeError: Cannot read property 'suite' of undefined" when using multiple frameworks

Hi there. Just want to first thank you for putting the time in to write this.

I am getting this error when I include ['jasmine', 'benchmark'] as frameworks for Karma:

ERROR [karma]: [TypeError: Cannot read property 'suite' of undefined]
TypeError: Cannot read property 'suite' of undefined
  at [object Object].specSuccess (/Users/user/projects/app/node_modules/karma-benchmark-reporter/index.js:35:33)
  at [object Object].onSpecComplete (/Users/user/projects/app/node_modules/karma/lib/reporters/base.js:83:12)
  at [object Object].<anonymous> (/Users/user/projects/app/node_modules/karma/lib/events.js:15:22)
  at [object Object].emit (events.js:98:17)
  at [object Object].onResult (/Users/user/projects/app/node_modules/karma/lib/browser.js:219:13)
  at Socket.<anonymous> (/Users/user/projects/app/node_modules/karma/lib/events.js:15:22)
  at Socket.emit [as $emit] (events.js:117:20)
  at SocketNamespace.handlePacket (/Users/user/projects/app/node_modules/karma/node_modules/socket.io/lib/namespace.js:335:22)
  at Manager.onClientMessage (/Users/user/projects/app/node_modules/karma/node_modules/socket.io/lib/manager.js:488:38)
  at WebSocket.Transport.onMessage (/Users/user/projects/app/node_modules/karma/node_modules/socket.io/lib/transport.js:387:20)
  at Parser.<anonymous> (/Users/user/projects/app/node_modules/karma/node_modules/socket.io/lib/transports/websocket/default.js:36:10)
  at Parser.emit (events.js:95:17)
  at Parser.parse (/Users/user/projects/app/node_modules/karma/node_modules/socket.io/lib/transports/websocket/default.js:343:12)
  at Parser.parse (/Users/user/projects/app/node_modules/karma/node_modules/socket.io/lib/transports/websocket/default.js:346:19)
  at Parser.parse (/Users/user/projects/app/node_modules/karma/node_modules/socket.io/lib/transports/websocket/default.js:346:19)
  at Parser.parse (/Users/user/projects/app/node_modules/karma/node_modules/socket.io/lib/transports/websocket/default.js:346:19)
  at Parser.add (/Users/user/projects/app/node_modules/karma/node_modules/socket.io/lib/transports/websocket/default.js:315:8)
  at Socket.<anonymous> (/Users/user/projects/app/node_modules/karma/node_modules/socket.io/lib/transports/websocket/default.js:169:17)
  at Socket.emit (events.js:117:20)
  at Socket.<anonymous> (_stream_readable.js:765:14)
  at Socket.emit (events.js:92:17)
  at emitReadable_ (_stream_readable.js:427:10)
  at emitReadable (_stream_readable.js:423:5)
  at readableAddChunk (_stream_readable.js:166:9)
  at Socket.Readable.push (_stream_readable.js:128:10)
  at TCP.onread (net.js:529:21)

I logged the result being passed.
code karma-benchmark-reporter/index.js:33-36:

  this.specSuccess = function(browser, result) {
    var browser = browser.name;
    var suite = result.benchmark.suite; // fails here
    var name = result.benchmark.name;

result:

{ description: 'is defined',
  id: 'spec0',
  log: [],
  skipped: false,
  success: true,
  suite: [ 'App' ],
  time: 2 }

It looks like result.benchmark does not exist.
Is this expected behavior?

I have just created a separate karma.conf.js file for BenchmarkJS in leu of this error.

Credit karma-benchmark reporters

Find out more about these reporters and mention them on the README.

Thanks so much @etpinard, @FormidableLabs, @lazd for making them โค๏ธ . This project was left unattended for quite a while, please open issues for anything you would like fixed or improving.

Using existing BenchmarkJS Benchmarks + Suites

If I want to use karma-benchmark to drive an existing set of benchmark tests, do I need to refactor all my existing tests which currently use the BenchmarkJS Benchmark and Suite objects, to use the "global" benchmark() and suite() wrappers which karma-benchmark introduces to register my tests?

It seems like, at some point in the past, karma-benchmark used to allow users to use the BenchmarkJS APIs (https://groups.google.com/d/msg/karma-users/sreRuEnUp6k/D-EYDd8RCzQJ) as opposed to forcing tests to be updated to use the "global" benchmark() and suite().

Just wondering if that support still exists or not?

Broken suite parameters assignement

The suite wrapper function is unable to setup benchmarks with his onStart stuff.

suite(
    'Suite options',
    function () {
        benchmark('_.each', function () {
            _.each(this.list, function (number) {
                return number;
            });
        });

        benchmark('native forEach', function () {
            this.list.forEach(function (number) {
                return number;
            });
        });
    },
    {
        onCycle: function (event) {
            var suite = this;
            var benchmark = event.target;
            console.log('Cycle completed for ' + suite.name + ': ' + benchmark.name);
        },
        onStart: function () {
            this.list = [5, 4, 3];
        },
        onComplete: function () {
            this.list = null;
        }
    }
);

This code come from the Readme and just crash because this.list does not exist in benchmark.
It throw:

PhantomJS 2.1.1 (Windows 8 0.0.0)  Suite options: native forEach FAILED
        TypeError: undefined is not an object (evaluating 'this.list.forEach')
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! karma-benchmark-examples@1.0.0 test: `karma start`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the karma-benchmark-examples@1.0.0 test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

This is the same with karma v3.0.0. You can find a working example here

Broken build on window

The prebuild script "mkdir -p dist" just fail on window platform. It create an -p folder and crash.

Add the ability to skip suites and benchmarks

It would be useful if certain suites or benchmarks could be skipped. One way to do this is to add a .skip() method to the benchmark and suite functions a la inclusive tests in Mocha:

suite.skip('Set value', function() {
  // ...
});

suite('Get value', function() {
  benchmark.skip(function() {
    // ...
  });
});

This is useful when benchmarks are crashing and you need to avoid running them.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.