16

背景の 1 行: 私はNoSQL データベースである Redisの開発者です。私が実装している新機能の 1 つは仮想メモリです。これは、Redis がメモリ内のすべてのデータを取得するためです。VM のおかげで、Redis はめったに使用されないオブジェクトをメモリからディスクに転送できます。OS にスワッピングの作業を任せるよりも、これがうまく機能する理由はいくつかあります (redis オブジェクトは、不連続に割り当てられた多くの小さなオブジェクトで構築されています)。 Redis によってディスクにシリアル化されると、それらが存在するメモリ ページと比較して 10 分の 1 のスペースしか必要としません)。

現在、Linux では完全に動作するアルファ版の実装がありますが、Mac OS X Snow Leopard ではうまく動作しません。Redis がメモリからディスクにページを移動しようとしている間、redis プロセスは数分間、中断できない待機状態になることがあります。これをデバッグできませんでしたが、これはfseeko()またはの呼び出しで発生しますfwrite()。数分後、呼び出しは最終的に戻り、redis はまったく問題なく動作し続けます: クラッシュはありません。

転送されるデータ量は非常に少なく、256 バイト程度です。したがって、非常に大量の I/O が実行される問題ではありません。

しかし、書き込み操作のターゲットであるスワップ ファイルに関する興味深い詳細があります。fopen()でファイルを開き、 で拡大して作成した大きなファイル (26 ギガバイト) ですftruncate()。最後に、unlink()Redis が参照を取得し続けるようにファイルが編集されますが、Redis プロセスが終了するときに、OS が実際にスワップ ファイルを解放することは確実です。

これですべてですが、詳細についてはここにいます。ところで、Redis git で実際のコードを見つけることもできますが、かなり複雑なシステムであることを考えると、5 分で理解するのは簡単なことではありません。

助けてくれてありがとう。

4

5 に答える 5

11

私が理解しているように、HFS+ はスパース ファイルのサポートが非常に貧弱です。そのため、ファイルの大部分を初期化/実体化するファイル拡張を書き込みがトリガーしている可能性があります。

たとえば、新しい大きな空のファイルを mmap し、いくつかのランダムな場所に書き込むと、HFS+ でディスク上に非常に大きなファイルが生成されることを私は知っています。mmap とスパース ファイルはデータを操作するのに非常に便利な方法であり、事実上他のすべてのプラットフォーム/ファイル システムがこれを適切に処理するため、非常に面倒です。

スワップ ファイルは線形に書き込まれますか? つまり、既存のブロックを置き換えるか、最後に新しいブロックを書き込んで空き領域ポインタをインクリメントしますか? その場合、ファイルを展開するためのより小さな ftruncate 呼び出しをより頻繁に実行すると、一時停止が短くなる可能性があります。

余談ですが、redis VM が mmap を使用せず、ブロックを移動してホット ブロックをホット ページに集中させようとする理由が気になります。

于 2010-01-07T00:34:06.950 に答える
1

antirez さん、私の Apple 経験は に限られているので、あまり役に立たないかもしれませんが、やってApple ][みます。

まず質問です。仮想メモリの場合、動作速度はディスク容量よりも重要な尺度になると思いました(特に、速度が重要なNoSQL DBの場合、そうでなければSQLを使用することになりますよね?)。ただし、スワップ ファイルが 26G の場合、そうではない可能性があります :-)

試してみるいくつかのこと(可能であれば)。

  1. 実際に問題をシークまたは書き込みに切り分けてみてください。シークにそれほど時間がかかるとは信じがたいです。最悪の場合、シークはバッファ ポインタの変更になるはずです。それでも、私はOSXを書いていないので、確信が持てません。
  2. スワップ ファイルのサイズを調整して、それが問題の原因であるかどうかを確認してください。
  3. (事前割り当てではなく) スワップ ファイルを動的に拡張することはありますか? その場合、それが問題の原因である可能性があります。
  4. 常にファイルのできるだけ低い位置に書き込みますか? 26G ファイルを作成しても実際にはデータが入力されない可能性がありますが、作成してから最後のバイトに書き込むと、OS はその前にバイトをゼロにする必要がある場合があります (初期化がある場合は延期します)。
  5. ファイル全体を事前に割り当て (すべてのバイトに書き込む)、リンクを解除しないとどうなりますか? 言い換えれば、プログラムの実行の間にファイルをそこに残してください (もちろん、まだ存在しない場合は作成します)。次に、Redis のスタートアップ コードで、ファイル (ポインターなど) を初期化します。これにより、上記のポイント 4 のような問題を取り除くことができます。
  6. さまざまな BSD サイトでも質問してください。Apple が内部でどれだけ変更を加えたかはわかりませんが、OSX は最低レベルの BSD にすぎません (カバーの Pax のアヒル)。
  7. また、Apple のサイトで質問することも検討してください (まだ行っていない場合)。

それは私のささやかな貢献です。あなたのプロジェクトで頑張ってください。

于 2010-01-07T00:46:28.300 に答える
0

ファイルのファイル キャッシュをオフにしましたか? すなわち fcntl(fd, F_GLOBAL_NOCACHE, 1)

于 2010-01-07T00:24:43.687 に答える
0

DTrace や Instruments (Apple の実験的な dtrace フロントエンド) を使用してデバッグを試みましたか?

DTrace で Leopard を探索する

OS X での Chrome のデバッグ

于 2010-01-07T00:33:54.093 に答える
-1

Linus が Git メーリング リストでかつて言ったように:

「OS X の人々がそれを受け入れるのに苦労していることはわかっていますが、OS X のファイルシステムは一般的に完全でまったくがらくたです - Windows よりもさらにそうです。」

于 2010-01-07T00:26:21.180 に答える