'Why is Math.random being outperformed by crypto.getRandomValues?

I've re-implemented Math.random() using crypto.getRandomValues with a "entropy pool" scheme to reduce the overhead of calls to crypto.getRandomValues. On my computer (x86_64 Windows Chrome) this seems to be about 260% faster than Math.random(). I find this surprising because I was under the impression that Chrome implements the latter using the blazingly fast xorshift128+ PRNG, which should be orders of magnitude faster than whatever CSPRNG is being used under the hood for the former.

class EntropyPool {
    #entropy; #index
    constructor(poolSize = 1024) {
        this.#entropy = new Uint32Array(poolSize)
        this.#index = 0
        crypto.getRandomValues(this.#entropy)
    }
    next() {
        const value = this.#entropy[this.#index++]
        if (this.#index === this.#entropy.length) {
            crypto.getRandomValues(this.#entropy)
            this.#index = 0
        }
        return value
    }
}

const pool = new EntropyPool()

function random() {
    return pool.next() / 4294967296
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source