キャッシュを効率的に管理する方法?--LoopBuffer

我々はバッファ構造を必要とする効率的なメモリ管理の場合は、データのサイズを予測することはできません。既存のデータ・メモリの動的な拡張は、任意の転換操作を持っていない場合でも、すべてのデータは、有効な書き込みを保証しています。データは、ときにのみ読み出しシーケンスを読み取ることができ、また読み出しデータが移動されていないでしょう。

バッファCppNetデータストリームCBufferの実際のデータストレージに、実装クラスCLoopBuffer名として実装ループバッファに一定量のメモリ上のポインタを移動させることによって、一連の操作を読み書きすること、を示唆しています。

各ループ・バッファは、固定サイズのメモリ・プールからメモリのピースを所持しています。その後、4つのポインタが厳しく、これは厳密に識別されることに注意して、位置データを識別するために、私たちはメモリに適用する必要はありませんのmemsetの各読み、ポインタの移動を介してデータの流れを制御するために書き、初期化、次のようにポインタがいくつか言ったの動きに焦点を当てて:

開始:割り当てられたメモリの先頭アドレスにポイントを。
終了:割り当てられたメモリへのエンド・アドレス・ポインタ。
読み:現在のカーソルをお読みください。
書き込み:現在のカーソルを記述します。
ループバッファが最初に作成されたときに、ポインタの位置は、図1に示します。

図1

読み取ることができ、このデータを書き込む=ときに読み出し、メモリ内の開始位置に3針位置を読み取り、書き込み、起動すると、ヌルです。次に、データは、図2に示すように、書き込み:

図2

ポインタは右、次の書き込みの記録位置に移動を開始する書き込み。読んで、残りのメモリサイズが書き込み可能なエンドです - - 読み書きできるデータ量は、書き込みになりました。

次はかつて、図3に示したデータを、読んで:

図3

ポインタが右に移動し始める読み取り、読み取ったデータ量が読み取られる - 開始、残りのデータのサイズが読み書きされる - 読み取り、残りのメモリサイズは、書き込み可能なエンドである - ( - 開始リード)+書き込み。

次は、図4に示した全てのデータを読み出します。

図4

リードポインタは、追加メンバー変数、読み取りおよび書き込みポインタは、2つのケースが存在する場合、同一である、いずれかのメモリがいっぱいになるか、またはメモリブロックが空の場合、読み書き、現在==、書き込みを抜いまで右に移動同定しました。書き込みに追いつくために読んで、メモリブロックが空である、あなたはデータサイズが0で読むことができる今、書き込み可能なメモリサイズは、コールwritevを容易にするために、より完全な書き込みキャッシュを行うために、ブロック全体のサイズであり、READV毎回読んで追いつくために、ポインタのポインタを書き込み、我々はすべてのポインタの状態がリセットされ、図の状態に戻ります。

次に、図5に示す到着する新しいデータは、あります。

図5

私たちは、ときにエンドへのポインタが、あなたが開始するポイントを再調整する必要があります読んで、適切な時期に移動されているので書くために、左の書き込みを見てきました、これはループの起源はあるが、今回は、読み取りと開始の間にたくさんありますその後、スタートからの距離と、私たちが書く、データを書き始めるには、再び右に移動を開始します。今読み取り可能なデータサイズ終了 - (書き込み - スタート)+読んで、書き込みデータのサイズを読み取ることができます - 書き込みます。

または、次のデータが書き込まれた場合、その後、それが右に移動します書き込み、読み取りを追いついてきました。そして、==書き込みを読んで、しかし、メモリが充填されました。

コールREADVに沿って、インターフェースの必要性は開始位置に戻ることができ、現在の書き込み可能なメモリのサイズは、我々は上記のいくつかのプロセスによって、2例があることを観察することができます。

1>図1(図4は、図1の状態にリセットされる。)図2、図5、のみ書き込みバッファ、書き込み開始アドレスポインタとリードの長さ-書き込みまたはエンド-書き込みます。
読み書き- -開始2>図3が、2つの書き込み可能領域、書き込み開始アドレスであり、それぞれ、起動すると、書き込み可能な長さの端部です。writevデータ領域を返す必要があり、上記と同様のポインタ操作が、正反対の場合、すべて、詳細には説明しません。

いくつかの処理ループバッファ以上のすべての状況が読み書きされ、あなたは、データのみ必要な読み書きするたびに参照データレプリケーション、およびその他のデータをコピーする操作を移動していなかったことができ、各データ流れるとき、それはメモリ領域の上限を超えることはありません。

しかし、唯一の固定サイズループバッファメモリだけでなく、新しいデータの書き込み要求の後に行う方法で満たされている場合?これは、バッファのパフォーマンスの時間です。

実際にCBuffer CLoopBufferもある同一それが、メモリブロックポインタCLoopBuffer内の特定の場所、及びCBufferを達成するだけでなく、読み出しを制御し、4つのポインタを介してデータを書き込むために、各ポインタ動作に非常に類似していますメモリブロックCLoopBufferへのポインタ。データが満杯でない場合、その中に全てのメモリブロックの一方向リンクリストを介して、ループバッファと同じいくつかのポインタおよびポインタ移動操作を管理ノード。
唯一の違いは、それらが満たされたメモリ・ブロックのすべてが、読んだとき==書き込み、時間CBufferは、メモリブロックから新しいメモリプールを適用し、リストに追加する必要があり、ということです。

問題を達成するための複数の方法がありますが、ないシーケンシャルアプリケーションCLoopBufferポインタが読み取りおよび書き込みポインタアドレスのシーケンスを比較することによって決定することができない、それ自体がインデックスキューを運ぶその実現に各CLoopBuffer、各valgrindの性能分析はここで見つける周波数がCBufferの実装を再最適化することを非常に高いので呼び出したときに、関係の呼び出しの順序を決定するためにオペレータ<または>をオーバーライドするすべての時間の必要性を見つけます。

どのようにデータが書き込まれるループバッファを管理するために、単独で、リンクされたリストで再建後CBufferは、新しいノードがリストに再度追加されたメモリプールの要求から十分なスペースではありません、書き込みポインタが後方に移動します。データ読み出し、電流ループバッファデータを読み出した後は、すべてのノードを完了すると、現在のブロックがメモリプールに返され、読み取りポインタが後方に移動します。以上のファミコンゲームマリオポンツーンのように実装するには、新しいレンガの遊歩道を構成する生成しますフロントをオフデストラクタする各煉瓦を踏ん。全体のプロセスは、移動シーケンス中に左から右に読まれます。

これらは、コアCppNetキャッシュ管理の実装です。

githubのは、突くしてくださいここに

おすすめ

転載: juejin.im/post/5d92e8b451882532ce31369c