高速なSSDに大きな仮想メモリを設定したら、意外と実用的な速度が出て、物理メモリの代わりになりました。
その時のお話です。
仮想メモリとは、『ページファイル』とか『ページングファイル』とか呼ばれている、あのメモリです。
自作のプログラムを動かすために、巨大なメモリが必要になったので、試しに使ってみました。
結論から言いますと、『物理メモリ48GB』と『仮想メモリ112GB(SSD)』で確保した『合計160GBのメモリ』は、実用的に使えました。
もし、たくさんのメモリが必要で、『物理メモリの代わりにSSDの仮想メモリが使えないか?』と思ったなら、試す価値はあると思いました。
たしかに、仮想メモリが支配的になるほど遅くなりました。ですが、HDDの仮想メモリよりはずっとマシでした。
実用的に使える範囲には限界もありましたが、手持ちのSSDに仮想メモリを割り当てるだけなので、コスパは最強でした。
以下、仮想メモリをフルパワーで使ってみた時の開発経験談です。
自作プログラムでたくさんのメモリが必要になった
さて、自分は2020年から、個人的に検索エンジンを作っていました。
(最終的に作った画面は以下のような感じ…)
(上場企業の有価証券報告書をどんどん見ていくために作りました)
その過程で試行錯誤していたときの話なのですが、『検索エンジンには大量のメモリが必要だ』ということが分かりました。
キーワードを入力して『サクッと結果を返す』ためには、事前に『転置インデックス』というものを作っておけばいいのですが、それを作るときに凄い量のメモリを消費したんですね(転置インデックスという仕組みを単純にそのまま実装してみたときの話です)。
『物理メモリが5000兆テラバイトほしい!!』
最初のメモリ構成は、『物理メモリ48GB』と、Cドライブに作った『仮想メモリ20GB(システム管理サイズ)』でした。
Cドライブは m.2 NVMe タイプのSSDです。
自分は、N-Gram 方式で愚直にインデックスを作ろうとしたのですが、48ギガバイトもあった物理メモリを軽々とオーバーして、Python プログラムが止まりました。
『転置インデックス、ぜんぜん作れないじゃないか。』
絶望です。
開発中は、一時的に検索対象を減らしていたから良かったけれど、本番モードにしたら全然メモリが足りませんでした。
けれども一応、仮想メモリの部分も使ってくれていたようで、『物理と仮想の合計』を超えそうになったところで止まっていました。
『ふむふむ、だったら仮想メモリ増やしたら行けそうじゃない?』
希望です。
そういうわけで、SSDの仮想メモリを 20GB ⇒ 112GB に増やしました。
全体で160ギガバイトのメモリです。凄い。
実際に使えたのは、少し減って157GBくらいのようでした。
上の画像は、物理メモリを使い切って、仮想メモリを使い始めた時のスクリーンショットです。
※ 『仮想メモリ』の情報を含んでいる『コミット済み』の説明は、日本マイクロソフトのサポート情報ブログにありました。
(jpwinsup.github.io) タスク マネージャーの見方 (Memory) 仮想メモリ Microsoft Japan Windows Technology Support Blog
転置インデックスの作成って凄いメモリ使うんですね。
形態素解析で単語単位で扱えばもっと節約できたんでしょうけれど、自分は N-Gram を使いましたので、サイズがやばかったです。
※ Windows の MeCab で形態素解析するコード例を書きました。
⇒ MeCab で形態素解析する Python コード例
⇒ MeCab で『分かち書き』する Python コード例
⇒ MeCab で NEologd の辞書を作ってインストールする方法
仮想メモリ用のSSDは、2台用意しました。
NVMe タイプ1台と SATA タイプ1台です。
『アクセスが混雑しないように』という期待を込めて、データ用のドライブは別に用意しました。
そして、使用メモリが 150GB 近くになるたびに、インデックスを分割するようにしました。
本当はあまり分割したくないんですけれどもね。分割すればするほど、色々な無駄が増えました。
でもまあ、しかたがないです。
最終的に、120個に分割されたインデックスファイルができました。
かかった時間は14時間でした。
確かに、物理メモリを使い切って仮想メモリを使いだすと、速度は落ちました。
『高速なSSDといえども、さすがに物理メモリには及ばないか。』
ざっくりですが、3倍から5倍の時間がかかってる感じでしたね。
物理メモリだけだと1時間で終わっていた処理が、3時間とか5時間になる感じです。
でもまあ、そのくらいならぜんぜんOKです。
自分の自作プログラムの用途としては、十分実用的な範囲でした。
HDDに作った仮想メモリと比べたら、SSDはめちゃめちゃ高速でした。
HDD の仮想メモリは遅かった
2006年ごろの話ですが、とある数値計算プログラムで、HDDの仮想メモリを試したことがありました。
たしか、『物理メモリ2GB』と『HDDの仮想メモリ6GB』で、合計8GBくらい確保しました。
一応プログラムは動きましたが、速度はめちゃめちゃ遅かったです。
かかっていた時間は、物理メモリだけの時と比べて、10倍や20倍をはるかに超えていました。
ハードディスクがカリカリカリカリ言っていました。
もはや完了する見込みがなくて中断しました。
『やっぱり仮想メモリは物理メモリの代わりにはならないのか』と、当時は思いました。
ですが、時代は変わりました。
SSDなら、意外と実用的な速さが出て、物理メモリの代わりになりました。
もちろん、実行するプログラムの内容にもよると思いますが、自分が巨大な転置インデックスの作成にチャレンジしてみた範囲では、仮想メモリが実用的に使えました。
仮想メモリに使用したSSDの型番
m.2 NVMe SSD
仮想メモリに使用した m.2 NVMe SSD です。
Western Digital の『WD_BLACK SN750 NVMe SSD WDS500G3X0C-00SJG0』で、容量が 500GB のものです。
自分が購入したときの価格は、1万2000円でした。
仮想メモリとして本格的にアクセスし始めた時(と思われる場面)のスクリーンショットです。
間欠的にメモリのデータを書き込んでいるような感じでした。
システムドライブなので、色々なアクセスが混じってると思います。
SATA SSD
仮想メモリに使用した SATA 接続のSSDです。
San Disk の『ウルトラ 3D SDSSDH3-250G-J25』で、容量は 250GB でした。
購入価格は忘れてしまいましたが、たしか6000円くらいだったと思います。
仮想メモリとして本格的にアクセスし始めた(と思われる場面)のスクリーンショットです。
こちらも、間欠的にメモリのデータを書き込んでいるような感じでした。
こちらは仮想メモリだけしか置いていないので、ほぼそのアクセスだけだと思います。
CドライブとFドライブの仮想メモリを両方使って、うまくプログラムが動いていました。
仮想メモリとしての速度は同じくらいだった
速度の面ですが、m.2 NVMe と SATA 接続で、速度の差は感じませんでした。
物理メモリを使い切って、仮想メモリを使いだしたときのアクセス速度は、どちらも 100 MB/s から 180 MB/s くらいでした。
タスクマネージャーのグラフをながめていたら、完全にバラバラのランダムアクセスという感じではなくて、ある程度まとまった大きさになったところでSSDに書き込んでいる感じでした。
もちろん、Windows の仮想メモリがどういう仕組みになっているのかは分かりませんので、想像ですけれども。
あとは、自分の自作プログラムが、たまたまそういったアクセスパターンになっていただけかもしれません。
また、物理メモリを使い切って仮想メモリが支配的になってくると、間欠的な感じはなくなって、どちらのSSDも常時 180 MB /s くらいで読み書きするようになっていました(2台のSSDの合計としては常時 350 MB/s くらいで読み書きしていました)。
SSD の仮想メモリは実用的だった
SSDは、m.2 NVMe 接続でも SATA 接続でも、仮想メモリとしては十分実用的に使えました。
書き込みが極端に遅いタイプ(シーケンシャル書き込みが 100 MB/s 未満とか)でなければ、仮想メモリ用としては十分だと思います。
初めはCドライブの仮想メモリを 20GB ⇒ 50GB にして様子を見たのですが、思いのほかちゃんと使えたので、さらに別のSSDにも仮想メモリを追加してみた感じですね。
そうして、『物理メモリ48GBと仮想メモリ112GB(SSD)』の『合計160GBのメモリ』を実現しました。
SSDさえあれば試すのは簡単なので、迷ったらやってみるのがいいと思います。
自作プログラムで広大なメモリ空間が必要といったケースでは、対応できる場合があるかもしれません。
自分の場合では、転置インデックスの作成で、仮想メモリが有効に使えました(ちょっと遅かったですが許容範囲でした)。
ところで、もしかしたら、『SSDへの書き込み量』が気になるかもしれません。
確認したのは SATA 接続のSSDだけですが、CrystarlDiskInfo で総書込量を見たら、14時間で1000GBほど増えていました。
これをどう見るかですね。
ただ、個人的にはSSDが書き込みすぎて壊れたという経験は、10年間で一度も無かったです。
(不良品で新品交換したことはありました)
A-DATA の 120GB SSD で不具合に遭遇した時の経験談
それに、大容量のSSDが数千円で買えることを考えると、あまり書き込み量とか寿命は気にしなくていいのかなって思います。
自分は SATA 接続で仮想メモリ専用のSSDを追加しました(余っていたSSDが役に立ちました)。
ゲームとかリアルタイム性が重要そうな用途だと、仮想メモリは厳しいのかもしれませんが、ものは試しだと思います。
Chrome ブラウザについては、仮想メモリが有用でした。自作プログラムで物理メモリを使い切って、仮想メモリが支配的になってきた状態でも、Chrome ブラウザでサイトを見ていくことができました。まあ、Chrome のタブを切り替えるたびに、ワンテンポ(1秒くらい)遅れる(ひっかかる)感じはありましたが、高負荷時の動作としては許容範囲でした。何よりも Chrome が落ちずに動作を継続してくれたところに感心しました(Chrome のバージョンにもよると思いますが)。もちろん、自作プログラムが終わって物理メモリが空けば、もとのサクサク動作に戻りました。
『仮想メモリは無駄』とか『仮想メモリは無意味』といった意見は見かけていましたが、とりあえずやってみたら意外と使えました。
本当は物理メモリを増設したいところですが、自分のマザーボードは64GBまでしか対応していなかったんですよね。
ASRock のサイトで自分のマザーボードを見たら、『システムメモリの最大容量:64GB』って書かれていました。
なので、SSDの仮想メモリが実用的に使えたのはありがたかったです。
ものは試しですね
SSD でも限界はあった
調子に乗って、さらに仮想メモリを増やしてみました。
あと、仮想メモリを3台のSSDに分散してみました。
なんとなくですが、2台よりも3台のほうが速そうじゃないですか?
で、物理48GB+仮想168GBを確保してみました。
合計216GBです。
そして、メモリをたくさん使う設定にしてプログラムを動かしたら、遅すぎて実用になりませんでした。
14時間で完了していた処理が、20日間くらいで完了しそうな速度でした。
これはさすがに待てませんでしたね。
ちょっと期待していたのですが、ざんねんです。
昔のHDDの時とちがって、一応現実的な時間で完了する程度には、処理が進んでいたんですけれどもね。
全体のメモリの使用量が160GBを超えたあたりから、急激にプログラムの進みが遅くなりました。
SSDのほうは頑張って読み書きしてくれていたのですが、プログラムの処理がとてもゆっくりになりました。
タスクマネージャを見ると、仮想メモリを置いた3台のSSDは、それぞれ常時 130 MB/s くらいの速度で読み書きしていました。リソースモニタを見ると、3台の合計で 400 MB/s くらいでした。
なんとか高速化できないかと思って、SSDを4台に増やしたら、それぞれの読み書き速度が 100 MB/s くらいに落ちて、全体の速度は変わらず 400 MB/s くらいでした。
『速度が頭打ちしてる…?』
ためしに、SSDを2台に減らして168GBの仮想メモリを設定したら、全体で常時 350 MB /s くらいで読み書きしていました。
SSDの台数を増やしても、仮想メモリの速度はあまり向上していなかった、という印象を受けました。少し速くなったくらいで、あまり分散の効果はなかったです。
プログラムの処理内容にもよると思いますが、自分の場合だと、仮想メモリ用のSSDは2台で十分そうでした。
あとは、仮想メモリの限界ですね。
SSDといえども、仮想メモリとして実用的に使える量には、限界がありました。
今回の自作プログラムの場合については、自分が最初に設定した『物理メモリ48GBと仮想メモリ112GB(SSD)』の『合計160GBのメモリ』は、ちょうど実用的に使える限界だったみたいです。
もちろん、アプリの用途(ブラウザとかゲームとか動画像の編集とか数値計算とか)によって、『仮想メモリが何GBまで実用的に使えるのか?』は変わってくると思います。
それでも、物理メモリを超えてメモリが使えたのは助かりました。
SSDなら『多少物理メモリを超えても実用的に使える場合があった』ということで、試す価値はあると思いました。
出典は調べていませんが、仮想メモリには『物理メモリの1.5倍から2倍くらいのサイズ』を割り当てれば良い、という言い伝えは、物理メモリ48GBというオーダーにおいても、SSDなら、わりと妥当なんじゃないかな?って思いました。
自作プログラムの問題は SQLite の全文検索機能で解決した
さて、自作の検索エンジンですが、最終的に SQLite データベースの全文検索 (FTS, full-text search) 機能を使用することで完成しました。
【Python】SQLite で日本語を全文検索するコード例【N-Gram, FTS4/FTS5】
SQLite は、48GB程度の物理メモリでも、余裕をもって、検索用のインデックスを作ってくれました。
タスクマネージャーでメモリの使用量を見ていた感じでは、システム全体で、25GBくらいの物理メモリ使用量でおさまっていました。
検索も速くて、とても良かったです。
SSDに大量に設定した仮想メモリについては、引き続き、100GB以上設定して使用しています。
Python で、大きな辞書 (dict) とか集合 (set) とかリスト (list) を、安心して扱えるところが気に入りました。
Windows の仮想メモリは、たくさん設定していても、特に不都合はないみたいでした。
いいですね。
別件ですが、以前に、瞬間的なメモリ不足が原因と思われる Python のクラッシュに困っていた時期がありました。
『Python は動作を停止しました』を解決するためにメモリを増設した話 (16GB ⇒ 48GB)
やっぱり、安定して動くっていうのはありがたいです。
しかしそれにしても、大容量のSSDの価格が下がってきたとはいえ、2TBとかのSSDを気軽に買い足すのって、まだまだ難しいですね。
それで自分は、SSDのほかに、『2台のHDDをRAID0で束ねたディスク』を用意しました。
RAID機能付きの外付けHDDケースです。
2台のHDDで『RAID0』にしたディスクがめちゃめちゃ便利だった話
お安いグレードのHDDでも、安定して 200MB/s を超える速度で読み書きできるようになりました。
快適です。
以前は、『HDDのRAID0なんて、早々に故障するんじゃないか?』と心配して、試していなかったんですよね。
ですが、実際に使ってみたら、別にそんなことはなくて、実用的に使うことができました。
HDDのRAID0は、安くて高速で大容量で、心配していたほど頻繁に壊れるといったこともなくて、良かったです。
SSDのデータを退避したりバックアップしたりするのが、とても快適になりました。