commit 5eb60db6551e75248d61f67acebd56336abebc42 Author: Brooke Vibber Date: Sat Dec 13 10:37:19 2025 -0800 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..212a211 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +js-range experiments + +run benchmark.js or index in tests + +comparing for loops against iterators diff --git a/bench.js b/bench.js new file mode 100644 index 0000000..5bf1909 --- /dev/null +++ b/bench.js @@ -0,0 +1,60 @@ +import { + rangeGenerator, + rangeObjectProperty, + rangeClosure +} from './range.js'; + +const thousand = 1000; +const million = 1000000; + +function benchmark(func) { + const iters = 100 * thousand; + // pre-heat jit + for (let i = 0; i < iters; i++) { + func(); + } + + let start = performance.now(); + for (let i = 0; i < iters; i++) { + func(); + } + let delta = (performance.now() - start) / iters; + console.log(`${delta * thousand} us per loop`); +} + +function testFor() { + benchmark(() => { + let acc = 0; + for (let i = 0; i < thousand; i++) { + acc += i; + } + return acc; + }); +} + +function testOne(func) { + benchmark(() => { + let acc = 0; + for (let i of func(thousand)) { + acc += i; + } + return acc; + }); +} + + +console.log('raw for loop'); +testFor(); +console.log('\n'); + +console.log('rangeGenerator'); +testOne(rangeGenerator); +console.log('\n'); + +console.log('rangeObjectProperty'); +testOne(rangeObjectProperty); +console.log('\n'); + +console.log('rangeClosure'); +testOne(rangeClosure); +console.log('\n'); diff --git a/index.html b/index.html new file mode 100644 index 0000000..7d91c85 --- /dev/null +++ b/index.html @@ -0,0 +1,3 @@ + + +

look in console for the benchmark results

\ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..4fdad3b --- /dev/null +++ b/package.json @@ -0,0 +1,4 @@ +{ + "name": "js-rnage", + "type": "module" +} diff --git a/range.js b/range.js new file mode 100644 index 0000000..abad96f --- /dev/null +++ b/range.js @@ -0,0 +1,51 @@ +export function *rangeGenerator(max) { + for (let i = 0; i < max; i++) { + yield i; + } +} + +function rangeObjectPropertyNext() { + if (this.value < this.max) { + return { + value: this.value++ + } + } + return { + done: true + } +} + +function rangeObjectPropertyIterator() { + return { + value: 0, + max: this.max, + next: rangeObjectPropertyNext + }; +} + +export function rangeObjectProperty(max) { + return { + max, + [Symbol.iterator]: rangeObjectPropertyIterator + }; +} + +export function rangeClosure(max) { + let value = 0; + return { + [Symbol.iterator]() { + return { + next() { + if (value < max) { + return { + value: value++ + }; + } + return { + done: true + }; + } + }; + } + }; +} diff --git a/results.txt b/results.txt new file mode 100644 index 0000000..865608d --- /dev/null +++ b/results.txt @@ -0,0 +1,25 @@ +macbook air m1 chrome + +raw for loop +- node: 0.64 us +- chrome: 0.64 us +- firefox: 0.63 us +- safari: 3.89 us + +rangeGenerator +- node: 17.08 us +- chrome: 17.08 us +- firefox: 35.06 us +- safari: 28.89 us + +rangeObjectProperty +- node: 6.55 us +- chrome: 5.55 us +- firefox: 5.91 us +- safari: 23.91 us + +rangeClosure +- node: 6.76 us +- chrome: 5.76 us +- firefox: 6.41 us +- safari: 24.79 us diff --git a/test.js b/test.js new file mode 100644 index 0000000..e2a55d9 --- /dev/null +++ b/test.js @@ -0,0 +1,23 @@ +import { + rangeGenerator, + rangeObjectProperty, + rangeClosure +} from './range.js'; + +function testOne(func) { + for (let i of func(10)) { + console.log(i); + } +} + +console.log('rangeGenerator'); +testOne(rangeGenerator); +console.log('\n'); + +console.log('rangeObjectProperty'); +testOne(rangeObjectProperty); +console.log('\n'); + +console.log('rangeClosure'); +testOne(rangeClosure); +console.log('\n');