# benchmarking JS random number generation

What’s the fastest way to fill a Float32Array with random numbers?

The problem is as follows - I have a Float32Array and I want to fill it up with random numbers. This array might be large! What’s the fastest way to do this?

There’s a few things to note - the actual values don’t have to satisfy any real properties for my usecase. It just has to be seemingly random, and the range of numbers generated doesn’t really matter.

## Benchmarking

For benchmarking we’ll use the following function:

```
function benchmark(f, x) {
const start = performance.now();
f(x);
const end = performance.now();
return end - start;
}
```

I’ll be including the results on my laptop, but will also provide a button for you to run the benchmark yourself!

## Using Math.random

This is the naive approach. We can do the following:

```
function usingMathRandom(len) {
const arr = new Float32Array(len);
for (let i = 0; i < len; i++) {
arr[i] = Math.random();
}
return arr;
}
```

## Using Crypto.getRandomValues

`Crypto.getRandomValues`

takes in a buffer of length up to 65536 and populates
the whole buffer with random values. It only operates on `Uint32Array`

s, but we
can share the underlying buffer between a `Float32Array`

and a `Uint32Array`

.

```
function usingCryptoRandom(x) {
const arr = new Float32Array(x);
for (let i = 0; i < x * 4; i += 65536) {
const arr_u = new Uint32Array(arr.buffer.slice(i, i + 65536));
crypto.getRandomValues(arr_u);
}
return arr;
}
```

## Results (time in ms)

### Firefox

Array size | Math.random | crypto.getRandomValues |
---|---|---|

10^1 | 1 | 0 |

10^2 | 0 | 0 |

10^3 | 0 | 0 |

10^4 | 1 | 0 |

10^5 | 0 | 2 |

10^6 | 2 | 66 |

10^7 | 31 | 103 |

10^8 | 303 | 1098 |

### Chromium

Array size | Math.random | crypto.getRandomValues |
---|---|---|

10^1 | 0 | 0 |

10^2 | 0 | 0 |

10^3 | 0 | 0 |

10^4 | 0 | 0 |

10^5 | 3 | 0 |

10^6 | 12 | 8 |

10^7 | 113 | 100 |

10^8 | 1139 | 917 |

## Conclusion

I was mildly suprised to see that `Math.random`

on ff is so fast. I suppose that makes
sense as it does not need to satisfy any cryptographically secure properties,
but the fact that `crypto.getRandomValues`

took a buffer made me wonder if it was
more optimized for this usecase. It’s interesting that on chromium,
`Crypto.getRandomValues`

is faster than `Math.random`

, so maybe the right choice
here depends on the browser. Either way, I’ll be sticking to `Math.random`

since
it’s simpler.