Skip to content

Instantly share code, notes, and snippets.

@dhermes
Last active July 9, 2020 03:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dhermes/fee7792dd695940483b3c0cdbfd8a78f to your computer and use it in GitHub Desktop.
Save dhermes/fee7792dd695940483b3c0cdbfd8a78f to your computer and use it in GitHub Desktop.
Benchmarking Dynamic Dispatch vs. Polymorphic Input
node_modules/

Benchmarking Dynamic Dispatch vs. Polymorphic Input

This is an attempt to see if JIT-ed codepaths throw off a microbenchmark.

Running the microbenchmark produces

$ npm run benchmark

> @ benchmark .../fee7792dd695940483b3c0cdbfd8a78f
> node index.js

withDynamicDispath x 99,765,425 ops/sec ±2.36% (79 runs sampled)
withPolymorphic x 45,310,089 ops/sec ±1.61% (84 runs sampled)

The comparison is between invoking a function that accepts a polymorphic input (polymorphic since it can be a 2D or 3D point)

function polymorphicSum(point) {
  return point.x + point.y + (point.z || 0);
}

and using dynamic dispatch to invoke two different specialized functions

function sum2D(point) {
  return point.x + point.y;
}

function sum3D(point) {
  return point.x + point.y + point.z;
}

These are invoked by "randomly" deciding at call time to use a 2D or 3D point so each of them will get invoked in the "same" way.

const Benchmark = require("benchmark");
function polymorphicSum(point) {
return point.x + point.y + (point.z || 0);
}
function sum2D(point) {
return point.x + point.y;
}
function sum3D(point) {
return point.x + point.y + point.z;
}
function withPolymorphic() {
if (Math.random() > 0.5) {
return polymorphicSum({ x: 10.5, y: -11.75 });
}
return polymorphicSum({ x: 171.25, y: -3.0, z: -6.75 });
}
function withDynamicDispath() {
if (Math.random() > 0.5) {
return sum2D({ x: 10.5, y: -11.75 });
}
return sum3D({ x: 171.25, y: -3.0, z: -6.75 });
}
function main() {
const suite = new Benchmark.Suite();
suite
.add("withDynamicDispath", withDynamicDispath)
.add("withPolymorphic", withPolymorphic)
.on("cycle", function (event) {
console.log(String(event.target));
})
.run({ async: true });
}
if (require.main === module) {
main();
}
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"benchmark": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz",
"integrity": "sha1-CfPeMckWQl1JjMLuVloOvzwqVik=",
"requires": {
"lodash": "^4.17.4",
"platform": "^1.3.3"
},
"dependencies": {
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
}
}
},
"platform": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz",
"integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q=="
},
"prettier": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz",
"integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg=="
}
}
}
{
"scripts": {
"benchmark": "node index.js",
"prettier": "prettier index.js --write"
},
"prettier": {
"printWidth": 120,
"quoteProps": "consistent",
"semi": true,
"singleQuote": false,
"trailingComma": "all"
},
"dependencies": {
"benchmark": "2.1.4",
"prettier": "2.0.5"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment