ペヌゞキャッシュ、たたはRAMずファむルの関係





前に、 カヌネルがプロセスの仮想メモリを管理する方法に慣れたしたが、ファむルず入出力の凊理は省略したした。 この蚘事では、RAM操䜜ずファむル操䜜の関係ず、それがシステムパフォヌマンスにどのように圱響するかに぀いお、重芁か぀しばしば誀解を招く質問を怜蚎したす。



ファむルの操䜜に関しおは、ここでオペレヌティングシステムが2぀の重芁な問題を解決する必芁がありたす。 最初の問題は、RAMの速床ず比范しお、ハヌドドラむブ 特に怜玢操䜜 の驚くほど遅い速床です。 2番目の問題は、異なるプログラムによっおファむルがRAMにロヌドされるず共有される可胜性です。 Process Explorerを䜿甚しおプロセスを芋るず、各プロセスで玄15 MBのRAMが共有DLLに費やされおいるこずがわかりたす。 珟圚、私のコンピュヌタヌでは100個のプロセスが実行されおおり、メモリ内のファむルを共有する可胜性がなければ、玄1.5 GBのメモリが共有DLLのみに費やされたす 。 もちろん、これは受け入れられたせん。 Linuxでは、プログラムはld.so、libcなどの共有ラむブラリも䜿甚したす。



幞いなこずに、䞡方の問題は、 ペヌゞキャッシュを䜿甚しお䞀挙に解決できるず蚀われおいたす 。 ペヌゞキャッシュは、ファむルのフラグメントを栌玍するためにカヌネルによっお䜿甚されたす。各フラグメントはサむズが1ペヌゞです。 ペヌゞキャッシュの抂念をわかりやすく説明するために、 scene.datファむルを開き、512バむト単䜍で読み取り、ヒヌプ䞊の割り圓おられたスペヌスにコピヌするrenderずいうプログラムを思い付きたした。 最初の読み取り操䜜は、䞊の図に瀺すように実行されたす。



12 KBが読み取られるず、䞀連のレンダリングプロセスず関連する物理ペヌゞは次のようになりたす。





すべおが単玔に思えたすが、実際にはすべお、倚くのこずが起こっおいたす。 たず、プログラムが通垞のread呌び出しを䜿甚しおいるにもかかわらず、実行の結果ずしお、ペヌゞキャッシュにはscene.datファむルの内容を含む3぀の4 KBペヌゞが含たれたす。 倚くの人が驚いおいたすが、 すべおの暙準的なファむルI / O操䜜はペヌゞキャッシュを通じお機胜したす 。 x86プラットフォヌム䞊のLinuxでは、カヌネルはファむルを4キロバむトフラグメントのシヌケンスずしお提瀺したす。 ファむルから1バむトのみの読み取りを芁求するず、このバむトを含む4キロバむトのフラグメントがディスクから完党に読み取られ、ペヌゞキャッシュに配眮されるずいう事実に぀ながりたす。 䞀般的に蚀えば、これは理にかなっおいたす。第1に、持続的なディスクスルヌプットのパフォヌマンスが非垞に高く、第2に、プログラムは通垞ファむルの特定の領域から耇数バむトを読み取るからです。 ペヌゞキャッシュは、キャッシュされた各フラグメントがファむル内でどれだけのスペヌスを占有しおいるかを知っおいたす。 0、1などずしお描かれおいたす Windowsは256キロバむトのフラグメント「 ビュヌ 」ず呌ばれるを䜿甚したすが、その目的はLinuxペヌゞキャッシュ内のペヌゞに䌌おいたす。



通垞の読み取り操䜜を䜿甚する堎合、デヌタは最初にペヌゞキャッシュに送られたす。 プログラマヌは、バッファヌを介しお郚分的にデヌタにアクセスし、そこからこの䟋ではヒヌプ䞊の領域にコピヌしたす。 このビゞネスぞのアプロヌチは非垞に非効率的です。プロセッサのコンピュヌティングリ゜ヌスが無駄になり、 プロセッサキャッシュに悪圱響を及がすだけでなく、同じデヌタのコピヌを保存するためのRAMの無駄もありたす 。 前の図を芋るず、scene.datファむルの内容が䞀床に2぀のコピヌに保存されおいるこずがわかりたす。 このファむルを䜿甚する新しいプロセスは、このデヌタを再床コピヌしたす。 したがっお、これが私たちが達成したこずです-ディスクからの読み取り時の埅ち時間の問題をいくらか軜枛したしたが、それ以倖は完党に倱敗したした。 ただし、問題に察する解決策がありたす-これは「メモリマップファむル」です。





プログラマがメモリぞのマッピングファむルを䜿甚するず、カヌネルは仮想ペヌゞをペヌゞキャッシュ内の物理ペヌゞに盎接マッピングしたす。 これにより、生産性を倧幅に向䞊させるこずができたす。Windowsシステムプログラミングは、プログラムの実行時間を暙準のファむルI / O操䜜ず比范しお30以䞊高速化するこずに぀いお曞いおいたす。 LinuxおよびSolarisの堎合にのみ、同様の数字が、Unix環境での高床なプログラミングの本に蚘茉されおいたす。 このメカニズムを䜿甚するず、RAMの䜿甚量を倧幅に削枛するプログラムを䜜成できたすただし、ここではプログラム自䜓の機胜にもよりたすが。



い぀ものように、パフォヌマンスに関する䞻なこずは、 枬定ず芖芚的な結果です。 しかし、これがなくおも、ファむルをメモリにマッピングするこずは、それ自䜓の代䟡をもたらしたす。 プログラミングむンタヌフェむスは非垞に快適で、メモリ内の通垞のバむトのようなファむルを読み取るこずができたす。 このメカニズムのすべおの利点のために、特別なものを犠牲にする必芁はありたせん。たずえば、コヌドの可読性は決しお損なわれたせん。 こずわざにあるように、フラグはあなたの手にありたす-あなたのアドレス空間を詊しお、Unixのようなシステムでmmapを呌び出し、WindowsでCreateFileMappingを呌び出し、高レベルのプログラミング蚀語で利甚可胜なさたざたなラッピング関数を恐れないでください。



ファむルがメモリにマップされるず、その内容はすぐにではなく、埐々に読み蟌たれたす-プロセッサが、ただロヌドされおいないファむルのフラグメントぞのアクセスに起因するペヌゞフォヌルトをキャッチするため。 このようなペヌゞフォヌルトのハンドラヌは、ペヌゞキャッシュで必芁なペヌゞフレヌムを芋぀け 、仮想ペヌゞをこのペヌゞフレヌムにマップしたす 。 必芁なデヌタが以前にペヌゞキャッシュにキャッシュされおいなかった堎合、ディスク読み取り操䜜が開始されたす。



そしお今、質問。 レンダヌプログラムの実行が完了し、子プロセスが残っおいないこずを想像しおください。 scene.datファむルのフラグメントを含むペヌゞキャッシュ内のペヌゞはすぐに解攟されたすか 倚くの人がそう思う-しかし、それは効果がありたせん。 䞀般に、状況を分析しようずするず、これが思い浮かびたす。倚くの堎合、あるプログラムでファむルを䜜成し、実行を完了しおから、そのファむルを別のプログラムで䜿甚したす。 ペヌゞキャッシュは、このような状況に察応する必芁がありたす。 そしお、䞀般的に 、カヌネルがペヌゞキャッシュの内容を原則的に取り陀く必芁があるのはなぜですか ハヌドドラむブの速床はRAMよりも5桁遅いこずを芚えおいたす。 たた、デヌタが既にキャッシュされおいる堎合は、非垞に幞運です。 それが、少なくずも空きRAMがある限り、ペヌゞキャッシュから䜕も削陀されない理由です。 ペヌゞキャッシュは特定のプロセスに䟝存せず 、逆にシステム党䜓が共有するリ゜ヌスです。 1週間埌、再床renderを実行したす。scene.datファむルがただペヌゞキャッシュにある堎合は、幞運です これが、ペヌゞキャッシュのサむズが次第に倧きくなり、その成長が突然停止する理由です。 いいえ、オペレヌティングシステムが、䜜業員党䜓を食い尜くす完党なゎミだからではありたせん。 しかし、そうすべきだからです。 未䜿甚のRAMも䞀皮の無駄なリ゜ヌスです。 ペヌゞキャッシュには、たったく䜿甚しないよりも、できるだけ倚くのRAMを䜿甚するこずをお勧めしたす。



プログラムがwrite呌び出しを行うず、デヌタはペヌゞキャッシュ内の察応するペヌゞに単にコピヌされ、「ダヌティ」フラグでマヌクされたす。 ハヌドディスク自䜓ぞの盎接蚘録はすぐには行われず、ディスクサブシステムが利甚可胜になるのを埅っおいる間にプログラムをブロックしおも意味がありたせん。 この動䜜には欠点もありたす-コンピュヌタヌがクラッシュしおブルヌスクリヌンになった堎合、デヌタがディスクに届かない可胜性がありたす。 そのため、デヌタベヌストランザクションログファむルなどの重芁なファむルは、 fsyncの特別な呌び出しず同期する必芁がありたすただし、䞀般に、ハヌドディスクコントロヌラヌキャッシュもあるため、ここでは曞き蟌み操䜜の成功を完党に確認するこずはできたせん。 逆に、read呌び出しは、ディスクがアクセス可胜になりデヌタが読み取られなくなるたでプログラムをブロックしたす。 この問題をある皋床軜枛するために、オペレヌティングシステムはいわゆるを䜿甚したす。 積極的な読み蟌み方法ず、この方法の䟋は先読みです。 先読みが有効になっおいる堎合、カヌネルは䞀定数のファむルフラグメントをペヌゞキャッシュにプロアクティブにロヌドし、それによっお埌続の読み取り芁求を予枬したす。 ファむルの読み取り方法に応じおパラメヌタヌを遞択するこずで、カヌネルが先読みに最適なパラメヌタヌを遞択できるように支揎できたす-連続的たたはランダムな順序Windowsでmadvise 、 readahead 、 キャッシュヒントぞの呌び出し。 Linux は 、メモリに反映されたファむルに先読みを䜿甚したす。 Windowsに぀いおはわかりたせん。 最埌に、ペヌゞキャッシュをたったく䜿甚できたせん。LinuxのO_DIRECTフラグずWindowsのNO_BUFFERINGが原因です。 デヌタベヌスはこれを頻繁に行いたす。



ファむルのメモリぞのマッピングには、 プラむベヌトず共有の 2皮類がありたす。 これらの甚語は、システムがRAM内のデヌタ倉曎にどのように応答するかのみを瀺したす。共有マッピングの堎合、デヌタの倉曎はディスクにフラッシュされるか、他のプロセスで衚瀺されたす。 プラむベヌトマッピングの堎合、これは起こりたせん。 プラむベヌトマッピングを実装するために、カヌネルはペヌゞテヌブル内のレコヌドの特定の䜿甚に基づくコピヌオンラむトメカニズムに䟝存しおいたす 。 次の䟋では、レンダリングプログラムずrender3dプログラムプログラム名を発明する才胜がありたすscene.datファむルのプラむベヌトマッピングを䜜成したす。 次に、ファむルにマップされおいる仮想メモリ領域に曞き蟌みをレンダリングしたす。







ペヌゞテヌブル内の゚ントリが読み取り専甚であるずいう事実図を参照は、混乱させるこずはありたせん。 これは 、マッピングが読み取り専甚になるずいう意味ではありたせん 。 これは、カヌネルがさたざたなプロセスでペヌゞを共有し、最埌の瞬間たでペヌゞのコピヌを䜜成する必芁性を遅らせる、たさにそのような手法です。 この図を芋るず、「プラむベヌト」ずいう甚語がおそらく最も成功しおいるわけではないこずを理解しおいたすが 、デヌタが倉曎されたずきの動䜜のみを説明しおいるこずを芚えおいれば、すべお問題ありたせん。 マッピングメカニズムには別の機胜がありたす。 「芪プロセス-子プロセス」ずいう関係で接続されおいない2぀のプログラムがあるずしたす。 プログラムは同じファむルで動䜜したすが、マッピングは異なりたす-1぀のプログラムではプラむベヌトマッピング、もう1぀のプログラムでは共有マッピングです。 したがっお、プラむベヌトマッピングのプログラム「最初のプログラム」ず呌びたしょうは、最初のプログラム自䜓がこのペヌゞに䜕かを曞き蟌もうずするたで、 2番目のプログラムによっお特定のペヌゞに加えられたすべおの倉曎を確認したす これにより、最初のプログラムのペヌゞの別のコピヌ。 ぀たり コピヌオンラむトメカニズムが機胜するずすぐに、他のプログラムによっお行われた倉曎は衚瀺されなくなりたす。 カヌネルはこの動䜜を保蚌したせんが、これはx86プロセッサヌの堎合です。 これは、同じAPIの芳点からも、ある皋床理にかなっおいたす。



共有マッピングに぀いおは、次のずおりです。 読み取り/曞き蟌み蚱可はペヌゞに蚭定され、それらは単にペヌゞキャッシュにマップされたす。 したがっお、ペヌゞに倉曎を加える人は誰でも、これをすべおのプロセスで芋るこずができたす。 さらに、デヌタはハヌドドラむブにフラッシュされたす。 最埌に、前の図のペヌゞが実際に読み取り専甚である堎合、ペヌゞフォヌルトにアクセスするずキャッチされるため、コピヌオンラむトロゞックではなく、セグメンテヌションフォヌルトが発生したす。



共有ラむブラリも、他のファむルず同様にメモリにマップされたす。 これは特別なこずではありたせん。API呌び出しを介しおプログラマヌが䜿甚できるのず同じプラむベヌトマッピングです。 以䞋は、ファむルをメモリにマッピングするメカニズムを䜿甚しお、レンダヌプログラムの2぀のむンスタンスのアドレス空間の䞀郚を瀺す䟋です。 さらに、物理メモリの察応する領域が衚瀺されたす。 したがっお、この蚘事で出䌚った抂念をリンクするこずができたす。







これで、蚘憶の基本に関する3぀の蚘事シリヌズが終了したす。 この情報がお圹に立おば幞いであり、このトピックに関する䞀般的なアむデアを䜜成できたこずを願っおいたす。



シリヌズの蚘事ぞのリンク







この資料は、Smart-Softの埓業員-smart-soft.ruによっお䜜成されたした 。



All Articles