Nano ID について調べてみた

2024-05-29

はじめに

Nano ID というライブラリを見つけて、どのようなものなのか気になったので調べてみた。

https://github.com/ai/nanoid

UUID とほぼ同じランダム性

UUID v4 と比べ、Nano ID は 4bit 分ランダムな値が多い。
それでいて、UUID v4 の36文字に比べ、Nano ID は21文字と少ない文字数で表現できる。

Comparison with UUID

Nano ID is quite comparable to UUID v4 (random-based). It has a similar number of random bits in the ID (126 in Nano ID and 122 in UUID), so it has a similar collision probability:

https://github.com/ai/nanoid/blob/36b05dd67bad457638958acff10fba04f747840f/README.md#comparison-with-uuid

Note: UUID はバージョン情報に 6bit 使用するため、128bit - 6bit で 122bit しかない。また、決まった位置に - が含まれる。

文字種

A-Za-z0-9_- で構成されている。URL Safe になっているので使いやすそう。

文字種を指定して使用することも可能。

// https://github.com/ai/nanoid/blob/36b05dd67bad457638958acff10fba04f747840f/README.md#custom-alphabet-or-size
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid() //=> "4f90d13a42"

実行速度

そこまで時間がかかる処理ではないと思うが、crypto.randomUUID に比べると 1/4 ぐらいなので、必要がなければ無理に使わなくて良さそう。

crypto.randomUUID         28,398,328 ops/sec
uuid v4                   10,254,199 ops/sec
...
nanoid                     7,484,029 ops/sec
customAlphabet             4,867,017 ops/sec
nanoid for browser           609,426 ops/sec
...

https://github.com/ai/nanoid/blob/36b05dd67bad457638958acff10fba04f747840f/README.md#benchmark

検証

以下の簡単なコードを作って検証してみました。
https://gist.github.com/mryhryki/bf2c7b2e0e0998cea728ba879e5cf255

結果は nanoid() が一番速かったです。

$ npm start >/dev/null
[Generate 1000000 IDs, Node.js version: v20.14.0]
#crypto.generateRandomUUID(): 1408.667041ms
#crypto.getRandomValues()   : 2624.5462079999998ms
#nanoid()                   : 1425.9569999999994ms

README を見ると、crypto.generateRandomUUID() が一番速いと書いてあるのですが、nanoid() とほぼ差がなかったです。
標準出力に全て出しているので、文字数の多さが影響したのかもしれません。
そこまでの厳密性は求めないので、一旦これ以上は検証しないことにします。

まとめ

UUID v4 とほぼ同じランダム性を持ちつつ、文字数が少なく、URL Safe な文字列で扱える便利なID生成ライブラリのようです。
生成速度も早く、ある程度カスタマイズもできるので、使えそうな機会には検討しても良さそうだな、と思いました。