Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Numbers Everyone Should Know #17

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions NumbersEveryoneShouldKnow.md
Original file line number Diff line number Diff line change
@@ -1 +1,117 @@
# Numbers Everyone Should Know

## 単位

| 時間 | 比率 |
| --- | --- |
| s | $1$ |
| ms | $10^{-3}$ |
| μs | $10^{-6}$ |
| ns | $10^{-9}$ |
| ps | $10^{-12}$ |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この続きは、フェムト、アトです。私は、もともとレーザー屋だったので、フェムト秒、アト秒には馴染があります。

フェムト秒はだいたい可視光の振動周期で、化学反応や振動などが100フェムト秒前後でおきる感覚ですね。


| バイト | 2進数 | 10進数 |
| --- | --- | --- |
| PB | $2^{50}$ | $10^{15}$ |
| TB | $2^{40}$ | $10^{12}$ |
| GB | $2^{30}$ | $10^9$ |
| MB | $2^{20}$ | $10^6$ |
| KB | $2^{10}$ | $10^3$ |
| B | $1$ | $1$ |

## Jeff Dean Numbers

| 操作 | ns | μs | ms | 補足 |
| --- | --- | --- | --- | --- |
| 通常のCPU命令 | 1 ns | | | |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

| L1キャッシュ参照 | 0.5 ns | | | |
| 分岐予測ミス | 5 ns | | | |
| L2キャッシュ参照 | 7 ns | | | L1キャッシュの14倍 |
| Mutex lock/unlock | 25 ns | | | |
| メインメモリ参照 | 100 ns | | | L1キャッシュの200倍、L2キャッシュの20倍 |
| 1KBのデータを[Zippy](https://en.wikipedia.org/wiki/Snappy_(compression))で圧縮 | 3,000 ns | 3 μs | | |
| 1KBのデータを1Gbpsのネットワークで送信 | 10,000 ns | 10 μs | | |
| SSDから4KBをランダムにRead | 150,000 ns | 150 μs | | ~1GB/s SSD |
| メモリから1MBをシーケンシャルにRead | 250,000 ns | 250 μs | | |
| 同じデータセンター内のRTT | 500,000 ns | 500 μs | | |
| SSDから1MBをシーケンシャルにRead | 1,000,000 ns | 1,000 μs | 1ms | ~1GB/s SSD, メモリの4倍 |
| ディスクシーク | 10,000,000 ns | 10,000 μs | 10 ms | データセンター内のラウンドトリップの20倍 |
| ディスクから1MBをシーケンシャルにRead | 20,000,000 ns | 20,000 μs | 20 ms | メモリの80倍、SSDの20倍 |
| カルフォルニア-オランダ間のRTT | 150,000,000 ns | 150,000 μs | 150 ms | |

- 現在ではアメリカ西海岸-東京間のRTTは100msぐらい[^1]らしいので、今はカルフォルニア-オランダ間のRTTは80msぐらいでは?
- デフォルトゲートウェイへの通信速度は無線だと1, 2ms、有線だと1, 2μsぐらい

## 言語

| 言語 | 速度比率 | |
| --- | --- | --- |
| C/C++ | 1 | 1~10億ステップ/s |
| Go, Java, C# | 3 | |
| Python | 50~100 | |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


| 型(C/C++) | バイト |
| --- | --- |
| bool | 1 B |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bool は 1 bit ですが、色々おきます。

| char | 1 B |
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Java の char は UTF-16 で2バイトだったかと思います。

| short | 2 B |
| int | 4 B |
| long | 4, 8 B |
| long long | 8 B |
| float | 4 B |
| double | 8 B |

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C++ の話をしているとすると、サイズは何ビット最低あるか、くらいしか決まっていません。
https://stackoverflow.com/questions/589575/what-does-the-c-standard-say-about-the-size-of-int-long

- デフォルトのコールスタックの深さは、Linuxだと8MB、Pythonだと1000個、Javaだと1万個ぐらい

## コンピュータ

| | サイズ |
| --- | --- |
| L1キャッシュ | 32~128 KB |
| L2キャッシュ | 512 KB ~ 4 MB |
| L3キャッシュ | 16~256 MB |
| メインメモリ | 4~128 GB |
| 補助記憶装置 | 64 GB ~ 4 TB |

| | スループット |
| --- | --- |
| PCIe 4.0 | 5 GB/s |
| PCIe 5.0 | 10 GB/s |

| | 時間 |
| --- | --- |
| CPU周波数 | 1~3 GHz |
| CPUコア数 | 4~64 |
| 関数呼び出し | 1 ns |
| システムコール | 500 ns |
| コンテキストスイッチ | 10 μs |
| DB(MySQL, Redis)クエリ | 500 μs |

- HDDやSSDの平均寿命は約5年、年間故障率(AFR)は0.5~1.5%

## グラフィック

| | 値 |
| --- | --- |
| ピクセルサイズ | 3 B |
| 4K解像度 | 3840x2160 |
| HD解像度 | 1920x1080 |
| リフレッシュレート(フレームレート) | 通常:24, 30, 60 Hz(fps)、ゲーム:120, 144, 240 Hz(fps) |

## システムデザイン

- Webページの表示速度は数msが望ましく、2~3秒が限界

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

表示速度の定義にもよりますが、数msというのは一般的にはかなり実現が難しいと思います。
Webのパフォーマンスチューニングの会社で、表示速度にこだわっているサイトでも、私の環境では静的コンテンツのキャッシュがある状態で0.1〜0.2秒ぐらいかかります。(末尾に表示速度があります)
https://spelldata.co.jp/

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://developer.chrome.com/docs/lighthouse/performance/speed-index/
参考までに Google のおすすめはアクセスから描画が始まるまで1.8秒以内ですね。(ちょっとその限界値は小さそうです。)

- 1台のWebサーバーの最大同時接続数は200~1000ぐらい

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

たとえばnginxのworker_connectionsのデフォルト値は1024で、ざっくりとは整合的だと思います。
https://github.com/nginx/nginx/blob/a4100450c067009158299ad69adb7d6f5e775943/conf/nginx.conf#L13
(ただし、動かしているサーバーのファイルディスクリプタの設定によっては、そちらに足を引っ張られます)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

もともと select の扱えるファイルディスクリプタの数の限界が FD_SETSIZE 1024までだったんですよね。(老人。)

- 1台のDBサーバーで扱えるレコード数は数十万ぐらい、100万レコードを超えてくると厳しくなる

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これの出典・カウント方法はどのようなものでしょうか?
DBサーバーのスペックにもよりますが、1レコードにつき1kBぐらいであれば素で保存するとしても1GBぐらいで、100万レコードぐらいは(すごく頻繁に登録更新があるとかでなければ)特に問題ないと思います。
シンプルなテーブルであれば、普通のPCぐらいの性能でも千万レコードを超えてもあまり不自由なく扱えますが、インデックスを貼ってないカラムで検索やソートしたりすると、めちゃくちゃ時間がかかったり、初期設定だとメモリ不足でエラーになったり、という事はあります。
OLAPとかだと、1台のDBで億を超えるレコードを扱うことも割とあると思います。スペックではない台数で語るのがナンセンスかもですが...

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これを参照しました。読み違えているかもしれません(cc @oda
https://discord.com/channels/1084280443945353267/1084283898617417748/1226569567476912190

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これは、MySQL を何も考えずに使っているときの(ウェブサーバーと同じマシンで同居くらいの)条件で、このあたりから運用方法を考え始める、くらいの話です。

あと、私は、こういうの作っていたの昔なので、感覚小さめの数字をいうと思います。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なるほど、そういうことですね。
私の感覚としては、主要なレコードの量が100万〜1000万の間ぐらいになってくると、素の状態で雑に使っているとだんだんと課題が出てきて、スケールさせることを考えるかなと思うので、そういう意味で「もう1桁2桁」というのは同じような感覚かなと思いました。

「1台のDBサーバーで扱えるレコード数が数十万ぐらい」というよりは、「Web・DB同居の1サーバーぐらいの構成だと100万〜1000万レコードぐらいで課題が出始めるので、必要ならスケールを考えはじめる」「数十万ぐらいまでは深く考えなくていい」みたいな事かもしれません。
(100万を超えたら厳しくなるのだ、と言われれば確かにそうかもしれませんが、元の文脈と微妙にニュアンスが違うような印象を受けました。オーダーの話として記されているか否かの違いですかね。。)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なるほど、そういうことですか。ありがとうございます

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1台で10万の桁までは扱えるが、もう1桁2桁上がってくると厳しいという感覚
そろそろ垂直にスケールさせたい

たしかに、これ日本語の読解として厳しいですね。

これくらいのところから、ORM が吐く SQL 文が気に食わないとか、クエリープランナーが妙なことしているなとか、暖機の時間が長いとか、書き方変えたり、DB を別サーバーにして強化したり、ちょっと考えないといけないようになるようなイメージです。

他の課題があったら挙げてくれるとありがたいです。> @sasanquaneuf

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そうですね、DBそのものについては、更新が多い場合にはPostgresだとVACUUMのパフォーマンスが気になってくるとか、他DBでもRedoログ/トランザクションログが肥大化したり切り捨てを調整したりとか、というような事があります。
MySQL等では、バッファプールに乗り切らなくなる(orスワッピングが発生する)などして、データ量の増加によって同じクエリがある日突然遅くなる場合もあります。

あと、数値と直接は関係ないんですが、このスケールを考慮するタイミングで、負荷をWebサーバーに寄せるかDBサーバーに寄せるか、みたいな設計戦略が変わってくる場合があります。
例えば同居サーバーの場合は同じリソースを分け合って使うので、単純に処理効率が良い方法を選ぶのが最適になります。このとき「データ量はそこそこあるがユーザー数は必ずしも多くない」みたいなケースでは、DBに寄せて処理した方が早くて楽なケースがそこそこあります。一方、WebとDBを分離すると、スケールさせやすいのがどちらかという事になるのですが、セッション管理等をちゃんとやればWebのスケールの方が楽になります。そうすると、なるべくDBの負荷を下げてWebに負荷を寄せる、というような戦略を取った方がよく、それによって実装方針が変わるケースもあります。
典型的な例としては、データの結合をWebサーバーでやるかDBでやるかとか、多少煩雑な集計をWebサーバーでやるかDBでやるかとかです。これはDB側でデータ転送量とCPU使用率のトレードオフがあったりするので、WebとDBのトレードオフだけではないのですが、それもこのぐらいのデータ規模から真剣に考えます。
※この辺は「書き方変えたり」に含まれるかもしれません。もちろん、やはりDBを増やせば十分なのでDBに寄せる、といった判断もあります。


## 参照

[Latency Numbers Every Programmer Should Know](https://gist.github.com/jboner/2841832)
[Latency Numbers Every Programmer Should Know - comment](https://gist.github.com/jboner/2841832?permalink_comment_id=3707733#gistcomment-3707733)
["Numbers Everyone Should Know" from Jeff Dean](https://brenocon.com/dean_perf.html)
[Original "Numbers Everyone Should Know"](http://norvig.com/21-days.html#answers)
[Napkin Math](https://github.com/sirupsen/napkin-math)
[Speed comparision](https://github.com/niklas-heer/speed-comparison)
[The Computer Language Benchmarks Game](https://benchmarksgame-team.pages.debian.net/benchmarksgame/)

[^1]: [Yahoo! JAPAN アメリカデータセンタとネットワーク変遷 - 39ページ](https://www.janog.gr.jp/meeting/janog52/wp-content/uploads/2023/06/janog52-atpo-fukazawa.pdf)