Created
May 29, 2025 02:55
-
-
Save easrng/5ab2f2d49309d40462054a4beca1de5c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
$ deno bench iter.js | |
CPU | 13th Gen Intel(R) Core(TM) i7-1365U | |
Runtime | Deno 2.2.8 (x86_64-unknown-linux-gnu) | |
file:///tmp/iter.js | |
benchmark time/iter (avg) iter/s (min … max) p75 p99 p995 | |
------------------- ----------------------------- --------------------- -------------------------- | |
for 4.4 µs 225,600 ( 4.4 µs … 4.5 µs) 4.4 µs 4.5 µs 4.5 µs | |
default iterator 6.7 µs 149,700 ( 6.6 µs … 27.0 µs) 6.7 µs 6.8 µs 8.3 µs | |
SafeArrayIterator 53.3 µs 18,750 ( 48.2 µs … 186.0 µs) 49.9 µs 91.6 µs 93.5 µs | |
CustomIterator1 36.6 µs 27,300 ( 25.3 µs … 676.6 µs) 33.4 µs 72.9 µs 75.1 µs | |
CustomIterator2 587.6 µs 1,702 (531.5 µs … 700.9 µs) 614.8 µs 648.5 µs 657.3 µs | |
CustomIterator3 36.7 µs 27,250 ( 25.1 µs … 250.6 µs) 33.5 µs 73.2 µs 75.9 µs | |
CustomIterator4 34.1 µs 29,300 ( 27.9 µs … 172.1 µs) 31.0 µs 71.5 µs 73.7 µs | |
CustomIterator5 30.9 µs 32,310 ( 24.7 µs … 212.9 µs) 27.7 µs 68.3 µs 70.8 µs | |
CustomIterator6 13.5 µs 74,240 ( 13.2 µs … 161.2 µs) 13.6 µs 15.2 µs 15.7 µs | |
CustomIterator7 16.0 µs 62,520 ( 15.9 µs … 145.6 µs) 15.9 µs 17.7 µs 18.3 µs | |
CustomGenerator 12.5 µs 80,220 ( 11.9 µs … 179.4 µs) 12.4 µs 22.4 µs 22.4 µs | |
generator 98.7 µs 10,130 ( 85.8 µs … 220.5 µs) 103.3 µs 139.1 µs 141.1 µs | |
for (no array) 3.5 µs 283,100 ( 3.5 µs … 3.5 µs) 3.5 µs 3.5 µs 3.5 µs | |
*/ | |
import assert from "node:assert"; | |
const SafeArrayIterator = (() => { | |
var { bind, call } = Function.prototype; | |
var uncurryThis = bind.bind(call); | |
var SymbolIterator = Symbol.iterator; | |
var ReflectGetPrototypeOf = Reflect.getPrototypeOf; | |
var ArrayPrototype = Array.prototype; | |
var ArrayPrototypeSymbolIterator = uncurryThis( | |
ArrayPrototype[SymbolIterator], | |
); | |
var ObjectSetPrototypeOf = Object.setPrototypeOf; | |
var ObjectFreeze = Object.freeze; | |
var createSafeIterator = (factory, next) => { | |
class SafeIterator { | |
#iterator; | |
constructor(iterable) { | |
this.#iterator = factory(iterable); | |
} | |
next() { | |
return next(this.#iterator); | |
} | |
[SymbolIterator]() { | |
return this; | |
} | |
} | |
ObjectSetPrototypeOf(SafeIterator.prototype, null); | |
ObjectFreeze(SafeIterator.prototype); | |
ObjectFreeze(SafeIterator); | |
return SafeIterator; | |
}; | |
var ArrayIteratorPrototype = ReflectGetPrototypeOf( | |
ArrayPrototype[SymbolIterator](), | |
); | |
var ArrayIteratorPrototypeNext = uncurryThis(ArrayIteratorPrototype.next); | |
var SafeArrayIterator = createSafeIterator( | |
ArrayPrototypeSymbolIterator, | |
ArrayIteratorPrototypeNext, | |
); | |
return SafeArrayIterator; | |
})(); | |
class CustomIterator1 { | |
constructor(array) { | |
this.index = 0; | |
this.array = array; | |
} | |
next() { | |
if (this.index >= this.array.length) { | |
return { done: true, value: undefined }; | |
} | |
return { done: false, value: this.array[this.index++] }; | |
} | |
[Symbol.iterator]() { | |
return this; | |
} | |
} | |
class CustomIterator2 { | |
constructor(array) { | |
this.index = 0; | |
this.array = array; | |
} | |
next() { | |
if (this.index >= this.array.length) { | |
return { __proto__: null, done: true, value: undefined }; | |
} | |
return { __proto__: null, done: false, value: this.array[this.index++] }; | |
} | |
[Symbol.iterator]() { | |
return this; | |
} | |
} | |
Object.setPrototypeOf(CustomIterator2.prototype, null); | |
class CustomIterator3 { | |
constructor(array) { | |
this.index = 0; | |
this.array = array; | |
} | |
next() { | |
if (this.index >= this.array.length) { | |
return { done: true, value: undefined }; | |
} | |
return { done: false, value: this.array[this.index++] }; | |
} | |
[Symbol.iterator]() { | |
return this; | |
} | |
} | |
Object.setPrototypeOf(CustomIterator3.prototype, null); | |
class CustomIterator4Result { | |
constructor(done, value) { | |
this.done = done; | |
this.value = value; | |
} | |
} | |
Object.setPrototypeOf(CustomIterator4Result.prototype, null); | |
class CustomIterator4 { | |
constructor(array) { | |
this.index = 0; | |
this.array = array; | |
} | |
next() { | |
if (this.index >= this.array.length) { | |
return new CustomIterator4Result(true, undefined); | |
} | |
return new CustomIterator4Result(false, this.array[this.index++]); | |
} | |
[Symbol.iterator]() { | |
return this; | |
} | |
} | |
Object.setPrototypeOf(CustomIterator4.prototype, null); | |
class CustomIterator5 { | |
#index; | |
#array; | |
constructor(array) { | |
this.#index = 0; | |
this.#array = array; | |
} | |
next() { | |
if (this.#index >= this.#array.length) { | |
return new CustomIterator4Result(true, undefined); | |
} | |
return new CustomIterator4Result(false, this.#array[this.#index++]); | |
} | |
[Symbol.iterator]() { | |
return this; | |
} | |
} | |
Object.setPrototypeOf(CustomIterator5.prototype, null); | |
class CustomIterator6 { | |
constructor(array) { | |
this.index = 0; | |
this.array = array; | |
this.result = new CustomIterator4Result(false, undefined); | |
} | |
next() { | |
if (this.index >= this.array.length) { | |
this.result.done = true; | |
this.result.value = undefined; | |
} else { | |
this.result.done = false; | |
this.result.value = this.array[this.index++]; | |
} | |
return this.result; | |
} | |
[Symbol.iterator]() { | |
return this; | |
} | |
} | |
Object.setPrototypeOf(CustomIterator6.prototype, null); | |
class CustomIterator7 { | |
constructor(array) { | |
this.index = 0; | |
this.array = array; | |
this.done = false; | |
this.value = undefined; | |
} | |
next() { | |
if (this.index >= this.array.length) { | |
this.done = true; | |
this.value = undefined; | |
} else { | |
this.done = false; | |
this.value = this.array[this.index++]; | |
} | |
return this; | |
} | |
[Symbol.iterator]() { | |
return this; | |
} | |
} | |
Object.setPrototypeOf(CustomIterator7.prototype, null); | |
class CustomGenerator { | |
constructor(length) { | |
this.index = 0; | |
this.length = length; | |
this.result = new CustomIterator4Result(false, undefined); | |
} | |
next() { | |
if (this.index >= this.length) { | |
this.result.done = true; | |
this.result.value = undefined; | |
} else { | |
this.result.done = false; | |
this.result.value = this.index++; | |
} | |
return this.result; | |
} | |
[Symbol.iterator]() { | |
return this; | |
} | |
} | |
Object.setPrototypeOf(CustomGenerator.prototype, null); | |
var data = Array.from({ length: 10000 }, (_, i) => i); | |
Deno.bench("for", function fn() { | |
let sum = 0; | |
for (let i = 0; i < data.length; i++) sum += data[i]; | |
assert.strictEqual(sum, 49995000); | |
}); | |
Deno.bench("default iterator", function fn() { | |
let sum = 0; | |
for (let num of data) sum += num; | |
assert.strictEqual(sum, 49995000); | |
}); | |
Deno.bench("SafeArrayIterator", function fn() { | |
let sum = 0; | |
for (let num of new SafeArrayIterator(data)) sum += num; | |
assert.strictEqual(sum, 49995000); | |
}); | |
Deno.bench("CustomIterator1", function fn() { | |
let sum = 0; | |
for (let num of new CustomIterator1(data)) sum += num; | |
assert.strictEqual(sum, 49995000); | |
}); | |
Deno.bench("CustomIterator2", function fn() { | |
let sum = 0; | |
for (let num of new CustomIterator2(data)) sum += num; | |
assert.strictEqual(sum, 49995000); | |
}); | |
Deno.bench("CustomIterator3", function fn() { | |
let sum = 0; | |
for (let num of new CustomIterator3(data)) sum += num; | |
assert.strictEqual(sum, 49995000); | |
}); | |
Deno.bench("CustomIterator4", function fn() { | |
let sum = 0; | |
for (let num of new CustomIterator4(data)) sum += num; | |
assert.strictEqual(sum, 49995000); | |
}); | |
Deno.bench("CustomIterator5", function fn() { | |
let sum = 0; | |
for (let num of new CustomIterator5(data)) sum += num; | |
assert.strictEqual(sum, 49995000); | |
}); | |
Deno.bench("CustomIterator6", function fn() { | |
let sum = 0; | |
for (let num of new CustomIterator6(data)) sum += num; | |
assert.strictEqual(sum, 49995000); | |
}); | |
Deno.bench("CustomIterator7", function fn() { | |
let sum = 0; | |
for (let num of new CustomIterator7(data)) sum += num; | |
assert.strictEqual(sum, 49995000); | |
}); | |
Deno.bench("CustomGenerator", function fn() { | |
let sum = 0; | |
for (let num of new CustomGenerator(10000)) sum += num; | |
assert.strictEqual(sum, 49995000); | |
}); | |
function* gen() { | |
for (let i = 0; i < 10000; i++) yield i; | |
} | |
Deno.bench("generator", function fn() { | |
let sum = 0; | |
for (let num of gen()) sum += num; | |
assert.strictEqual(sum, 49995000); | |
}); | |
Deno.bench("for (no array)", function fn() { | |
let sum = 0; | |
for (let i = 0; i < 10000; i++) sum += i; | |
assert.strictEqual(sum, 49995000); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment