@stack-fintech/benchmark

0.4.0 • Public • Published

benchmark

A simple framework for benchmarking your functions.

Install

npm i --save @stack-fintech/benchmark

Usage

This example should give you everything you need to setup your own benchmarks!

// The benchmark tools are comprised of these three classes:
const { Suite, Step, Test } = require("@stack-fintech/benchmark");

const crypto = require("crypto"); // Not always required, just for this example.
const Widget = require("./lib/widget"); // Some example thing you're testing.

// Suites take a collection of Tests and run them in the order they're added to the Suite.
const suite = new Suite("YourSuite");

/*
  Tests run a collection of Steps, for a given number of iterations, and produce
  statistics for each Step.

  Each iteration runs all of the Steps once, in the order they're added to the Test.
*/
const test = new Test({
  name: "widget-flow",
  iterations: 10000,
});

// Steps require a name for tracking statistics.
const makeWidget = new Step("makeWidget");

// The setup and teardown functions let you prep and cleanup before a Step runs,
// without that overhead contaminating your benchmark data.
let widgetName;
let createdWidget;

makeWidget.setup(() => {
  // Generate a random name for the widget.
  widgetName = crypto.randomBytes(16).toString("hex");
});

makeWidget.teardown(() => {
  // If you need to clean something up, you'd do it here.
});

// You can give the function handler sync or async functions.
makeWidget.fn(async () => {
  createdWidget = await Widget.create(widgetName);
});

// You can use event handlers instead if your code is event-driven.
// Note that you must:
// - make sure the event is being emitted, otherwise your Test will
// hang.
// - accept a callback as the last parameter of your handler function
// and call it when finished.
makeWidget.event(Widget, "ordered", (cb) => {
  Widget.create(widgetName)
    .then(() => {
      return cb();
    })
    .catch((err) => {
      return cb(err);
    });
});

// Steps can also be created with object definitions.

// Note: You still need to use the Step constructor, as the Test class
// expects certain properties for validation.
const shipWidget = new Step({
  name: "shipWidget",
  fn: () => {
    Widget.ship(createdWidget);
  },
});

// Assemble your test
test.add(makeWidget);
test.add(shipWidget);

// And then assemble your suite.
suite.add(test);

/*
  Suites and Tests are EventEmitters, and you can hook into them!
  
  Tests:
    start:    When Test.start is called. Provides the callback with the Test's
              options object as a parameter.
    cycle:    At the top of each iteration, before any of the steps run. Provides
              the callback with a context object that has an index (the current
              iteration), and the maximum number of iterations:
              (ex. { index: 4, iterations: 10000 })
    step:     Before each step in a cycle. Provides the callback with a context
              object that has an index (the current iteration), the maximum
              number of iterations, and the Step object.
              (ex. { index: 4, iterations: 10000, step: { ... } })
    complete: At the end of the test run. Provides the callback with a copy of
              the Test itself.
  Suites:
    start:    When Suite.start is called.
    cycle:    Identical to the "cycle" event for Tests. Useful for applying the
              same function calls to multiple test runs.
    step:     Identical to the "step" event for Tests. Again, useful if you
              want to run the same function on every Step of multiple Tests.
    complete: At the end of Suite.start, when all Tests have finished.
 */

test.on("cycle", (context) => {
  // These event emitters are *very* useful for adding your own progress tracking,
  // like progress bars, spinners, etc.
  console.log(`Run ${context.index} of ${context.iterations}`);
});

test.on("complete", () => {
  for (let step of test.steps) {
    // Test provides a printStats function you can use to print the results to stdout.
    test.printStats(step.name, test.stats[step.name]);
    // Alternatively, you can access the test.stats object and roll your own!
  }
});

(async () => {
  await suite.start(); // And that's how you do it!
})();

Dependents (0)

Package Sidebar

Install

npm i @stack-fintech/benchmark

Weekly Downloads

3

Version

0.4.0

License

ISC

Unpacked Size

21.1 kB

Total Files

8

Last publish

Collaborators

  • ohassan-cs
  • azhuk
  • rjayapalan
  • lcaicreditsesame.com
  • stackdev
  • vishwakt
  • sharaf_stack
  • manjunathgk
  • aarteagacs
  • jmejia.sesame
  • cs-lbarton
  • psymoon
  • vpham