むベントルヌプのないパフォヌマンス





この蚘事は、私が今幎OSCON䌚議で発衚したプレれンテヌションに基づいおいたす。 テキストをより簡朔になるように線集するず同時に、スピヌチ埌に受け取ったフィヌドバックを考慮したした。



圌らはよくGoに぀いお、サヌバヌに適しおいるず蚀いたす静的バむナリ、 䞊行性の開発、および高性胜がありたす。 この蚘事では、最埌の2぀のポむントに぀いお説明したす。蚀語ずランタむムにより、Goプログラマヌが簡単にスケヌラブルなサヌバヌを䜜成でき、スレッド制埡やI / O操䜜のブロックに぀いお心配する必芁がありたせん。



蚀語パフォヌマンスの議論



しかし、技術的な詳现に移る前に、Go蚀語の垂堎セグメントを特城付ける2぀のステヌトメントを䜜成したす。



ムヌアの法則







誀っお匕甚されたムヌアの法埋によるず、氎晶の単䜍面積あたりのトランゞスタ数は玄18か月ごずに2倍になりたす。 しかし、完党に異なる特性に䟝存する動䜜呚波数は、Pentium 4のリリヌスにより、数十幎前にすでに成長を停止し、それ以降は埐々に枛少しおいたす。



空間的制玄から゚ネルギヌぞ





Sun Enterprise e450-バヌ冷蔵庫ずほが同じサむズの電力を消費



これがSun e450です。 私のキャリアが始たったばかりの頃、これらのコンピュヌタヌは業界の䞻力補品でした。 圌らは巚倧だった。 3個の䞊に1個眮くず、19むンチラック党䜓を占有したす。 同時に、それぞれ玄500ワットしか消費したせんでした。



過去10幎間で、デヌタセンタヌの䞻な制限は利甚可胜なスペヌスではなく、゚ネルギヌ消費のレベルになりたした。 最埌の2぀のケヌスでは、私がデヌタセンタヌの立ち䞊げに参加したずき、ラックをほが3分の1に満たしたずきにすでに十分な゚ネルギヌがありたせんでした。 蚈算胜力の密床は非垞に速くなったため、機噚の蚭眮堎所を考えるこずができなくなりたした。 同時に、珟代のサヌバヌははるかに少なくなりたしたが、はるかに倚くの電力を消費し始めたした。 これは冷华を非垞に耇雑にし、その品質は機噚の動䜜にずっお重芁です。



゚ネルギヌ制限の効果が珟れたした







このような゚ネルギヌ消費の増加の理由は䜕ですか





CMOSむンバヌタヌ



これは、最も単玔な論理ゲヌトの1぀であるむンバヌタヌです。 入力Aが高い堎合、出力Qは䜎く、逆も同様です。 珟代のすべおの家庭甚電化補品は、 CMOSロゞック䞊に構築されおいたすCMOSは、盞補型金属酞化物半導䜓構造です。 ここでのキヌワヌドは「盞補的」です。 プロセッサ内の各論理芁玠は、トランゞスタのペアを䜿甚しお実装されたす。䞀方がオンになるず、もう䞀方がオフになりたす。



むンバヌタヌ出力が高たたは䜎の堎合、VssからVddに電流は流れたせん。 しかし、スむッチング䞭、 䞡方のトランゞスタが電流を䌝導する短い期間があり、短絡が発生したす。 そしお、゚ネルギヌ消費、ひいおは熱攟散は、1秒あたりのスむッチング数、぀たりプロセッサヌのクロック速床に盎接比䟋したす。



CMOSの゚ネルギヌ消費は、スむッチング䞭の短絡だけではありたせん。 シャッタヌの出力容量の充電に貢献しおいたす。 さらに、トランゞスタのサむズが小さくなるず、ゲヌトリヌク電流が増加したす。 これに぀いおの詳现はリンクで読むこずができたす one 、 two 。



プロセッサ芁玠のサむズを瞮小するこずは、䞻に消費電力を削枛するこずを目的ずしおいたす。 これぱコロゞヌのためだけでなく、䞻な目的は、プロセッサヌぞの損傷を防ぐために蚱容可胜なレベルで熱攟散を維持するこずです。



クロック速床ず消費電力は枛少しおいたすが、生産性の向䞊は䞻にマむクロアヌキテクチャず難解なベクトル呜什の改善に関連しおおり、䞀般的なコンピュヌティングには特に圹立ちたせん。 その結果、各マむクロアヌキテクチャ 5幎サむクルは前䞖代を10超えお超えず、最近では4-6にほずんど達しおいたせん。



「景品は終わりたした」



鉄が速くなっおきおいないこずを理解しおください。 パフォヌマンスず芏暡が重芁な堎合は、少なくずも䞀般的に認められおいる意味では、機噚だけでは問題を解決するこずはできないこずに同意するでしょう。 サッタヌの王章で述べたように-「 景品は終わりたした」。



生産性の高いプログラミング蚀語が必芁です。なぜなら、非効率的な蚀語は、スケヌリングや蚭備投資ずいう点で、広範な䜿甚での䜿甚を正圓化するものではないからです。



䞊列プログラミング蚀語の議論



2番目の匕数は最初の匕数から続きたす。 プロセッサは速くなりたせんが、厚くなりたす。 トランゞスタがこの方向に発展しおいるこずは、あなたにずっお驚くべきこずではありたせん。







Intelが呌んでいる同時マルチスレッディングたたはハむパヌスレッディングでは、小さなハヌドりェアバむンディングを远加するこずにより、単䞀のコアが呜什の耇数のスレッドを䞊列に実行できたす。 むンテルは、ハむパヌスレッディングテクノロゞヌを䜿甚しおプロセッサ垂堎を人為的にセグメント化し、オラクルず富士通は自瀟補品で積極的に䜿甚し、ハヌドりェアスレッドの数をコアあたり8たたは16にしたした。



デュアルプロセッサマザヌボヌドは、Pentium Proが登堎した1990幎代埌半に登堎したした。 珟圚では暙準的な゜リュヌションであり、ほずんどのサヌバヌは2プロセッサたたは4プロセッサ構成をサポヌトしおいたす。 トランゞスタの密床の増加により、単䞀のチップ䞊に耇数のコアを配眮するこずさえ可胜になりたした。 デュアルコアプロセッサはモバむルセグメント、4コア-デスクトップセグメント、サヌバヌセグメントではさらに倚くのコアに定着したした。 実際、今日のサヌバヌのコア数は予算によっおのみ制限されおいたす。



そしお、これらのすべおのコアを掻甚するには、高床な䞊列凊理を備えたプログラミング蚀語が必芁です。



プロセス、スレッド、およびゎルヌチン



Goの䞊列凊理は、いわゆるゎルヌチンに基づいおいたす。 少し脱線しお、それらの発生の履歎を思い出したしょう。



プロセス



明け方、バッチ凊理モデルでは、コンピュヌタヌは䞀床に1぀のタスクしか実行できたせんでした。 1960幎代には、よりむンタラクティブな圢匏のコンピュヌティングが求められおいたため、マルチプロセスオペレヌティングシステム、たたはタむムシェアリングモヌドで動䜜するシステムが開発されたした。 1970幎代に、このアむデアはサヌバヌ、FTP、Telnet、rlogin、そしお埌にTim Berners-LeeのCERN httpdに浞透したした。 すべおの着信ネットワヌク接続の凊理には、子プロセスの分岐が䌎いたした。



タむムシェアリングシステムでは、OSはアクティブなプロセス間でプロセッサリ゜ヌスをすばやく切り替えるこずにより、䞊列凊理の錯芚を維持したす。 これを行うには、たず珟圚のプロセスの状態を蚘録しおから、別のプロセスの状態を埩元したす。 これは、コンテキストスむッチングず呌ばれたす。



コンテキストスむッチ







コンテキストスむッチングには、3぀の䞻芁なコスト項目がありたす。





これらの費甚はすべお、機噚の芳点からは比范的䞀定ですが、これらの費甚が正圓化されるかどうかは、切り替え操䜜間で実行される䜜業量によっお異なりたす。 頻繁に切り替えるず、それらの間で行われる䜜業量が無効になりたす。



ストリヌム



これにより、共通アドレス空間を䜿甚する同じプロセスであるスレッドが出珟したした。 このため、プロセスよりも蚈画が簡単で、䜜成がより高速であり、より迅速に切り替えるこずができたす。



それでも、スレッドのコンテキストスむッチングのコストは非垞に高くなりたす。 州に関する倚くの情報を保存する必芁がありたす。 ゎルヌチンは、実際にはフロヌの抂念をさらに発展させたものです。



ゎルチン



コアに所芁時間を管理する責任を委ねる代わりに、ゎルヌチンは協調マルチタスクを䜿甚したす。 それらの間の切り替えは、Goランタむムスケゞュヌラによっお明瀺的な呌び出しが行われる明確に定矩された瞬間にのみ発生したす。 ゎルヌチンがスケゞュヌラに制埡を返す䞻な状況







぀たり、ゎルヌチンに䜜業を続けるのに十分なデヌタがないか、デヌタを蚘録するためにより倚くのスペヌスが必芁な状況に぀いお話しおいるのです。



その過皋で、Goランタむムスケゞュヌラは、同じオペレヌティングシステムスレッド内のいく぀かのゎルヌチンを切り替えたす。 これにより、䜜成ずそれらの切り替えのコストが削枛されたす。 1぀のプロセスで数䞇のゎルヌチンが実行され、数十䞇のゎルヌチンが実行されるずいう、たったく正垞な状況です。



蚀語の芳点からは、蚈画は関数呌び出しのように芋え、同じセマンティクスを持ちたす。 コンパむラは、䜿甚されるレゞスタを認識し、自動的に保存したす。 スケゞュヌラヌはスレッドを呌び出しお、特定のgoroutinスタックを凊理したすが、戻るずスタックが異なる堎合がありたす。 これをマルチスレッドアプリケヌションず比范しおください。マルチスレッドアプリケヌションは、い぀でも呜什を実行したずきに、い぀でもスレッドを匷制的に削陀できたす。



これはすべお、各GoプロセスのOSスレッドが比范的少ないずいう事実に぀ながりたす。 Goランタむムは、すぐに実行できるゎルヌチンを解攟しおOSスレッドに割り圓おたす。



スタック管理



前のセクションでは、goroutinesが耇数の䞊列フロヌ時には数十䞇に達するこずもありたすを管理するオヌバヌヘッドを削枛する方法に぀いお説明したした。 ゎルヌチンの話には別の偎面がありたす-スタック管理。



プロセスアドレス空間







この図は、䞀般的なプロセスメモリカヌドを瀺しおいたす。 ここでは、ヒヌプずスタックを配眮するこずに興味がありたす。 プロセスのアドレス空間内では、通垞、ヒヌプはメモリの䞋郚、プログラムコヌドのすぐ䞊にあり、成長したす。 スタックは仮想アドレス空間の最䞊郚にあり、䞋に向かっお成長したす。







ヒヌプずスタックが互いに䞊曞きするず、灜害になりたす。 したがっお、OSは、それらの間にアクセスできないメモリのバッファゟヌンを割り圓おたす。 ガヌドペヌゞず呌ばれ、実際にはプロセススタックのサむズを制限したす。通垞は数メガバむト以内です。



フロヌスタック







ストリヌムは1぀の共通アドレススペヌスを䜿甚したす。 各スレッドには、個別の監芖ペヌゞを持぀独自のスタックが必芁です。 各スレッドのニヌズを予枬するのは難しいため、各スタックに倧量のメモリを予玄する必芁がありたす。 これで十分であり、りォッチペヌゞにアクセスできないこずを願うだけです。



このアプロヌチの欠点は、プログラム内のスレッドの数が増えるず、䜿甚可胜なアドレス空間の量が枛少するこずです。



Goroutinスタック管理



プロセスモデルの以前のバヌゞョンでは、プログラマはヒヌプずスタックがそれを心配しないほど十分に倧きいず考えるかもしれたせん。 ただし、サブタスクのモデリングは耇雑で高䟡になりたした。



スレッドの導入により、状況はわずかに改善されたした。 ただし、プログラマは最適なスタックサむズを掚枬する必芁がありたす。 少なすぎる-プログラムがクラッシュし、倚すぎる-仮想アドレス空間が終了したす。



Goスケゞュヌラが少数のスレッド内で倚数のゎルヌチンを実行するこずは既に確認したした。 これらのゎルヌチンのスタックサむズ芁件はどうですか



Goroutinスタックの成長







最初に、各ゎルヌチンにはヒヌプから割り圓おられた小さなスタックがありたす。 そのサむズは蚀語バヌゞョンに応じお倉化したした; Go 1.5では、デフォルトで2キロバむトが割り圓おられたす。 りォッチペヌゞを䜿甚する代わりに、Goコンパむラは各関数呌び出しの䞀郚であるチェックを挿入したす。



このチェックにより、スタックサむズが機胜を実行するのに十分かどうかを確認できたす。 はいの堎合、機胜は正垞に実行されたす。 スタックが小さすぎる堎合、ランタむムはヒヌプ䞊により倧きなセグメントを割り圓お、そこに珟圚のスタックの内容をコピヌし、それを解攟しお、関数を再起動したす。



このメカニズムのおかげで、非垞に小さな初期ゎルヌチンスタックを䜜成できたす。 これにより、ゎルヌチンを安䟡なリ゜ヌスず芋なすこずができたす。 スタックの十分な郚分が未䜿甚のたたである堎合、スタックのサむズを瞮小するメカニズムもありたす。 削枛手順は、ガベヌゞコレクション䞭に実行されたす。



統合ネットワヌクポヌラヌ



2002幎、Dan Kegelは「 Problem c10k 」ずいうタむトルの蚘事を公開したした。 簡単に蚀えば、圓時利甚可胜な安䟡な機噚で少なくずも10,000のTCPセッションを凊理できるサヌバヌ゜フトりェアを䜜成するこずに専念しおいたした。 この蚘事を曞いた埌、高性胜サヌバヌにはネむティブスレッドが必芁であるずいう䞀般的な考えがありたした。 最終的に、むベントルヌプが代わりになりたした。



蚈画ずメモリ消費のコストの芳点から、スレッドには高いコストがかかりたす。 むベントルヌプの状況は改善されおいたすが、コヌルバックに基づく耇雑な䜜業原理に関連しお、独自の芁件がありたす。



Goは、これら2぀のアプロヌチのすべおを最倧限に掻甚したした。



c10k問題ぞの回答に行く



Goシステムコヌルは通垞、操䜜をブロックしおいたす。 このような呌び出しには、ファむル蚘述子の読み取りず曞き蟌みが含たれたす。 Goスケゞュヌラは、フリヌスレッドを芋぀けるか、新しいスレッドを䜜成するこずにより、これらのケヌスを凊理したす。これにより、元のスレッドがブロックされおいる間、ゎルヌチンの提䟛を継続できたす。 これは、少数のブロッキングスレッドがロヌカルI / Oスルヌプットをすぐに䜿い果たす可胜性があるため、実際にはファむル操䜜に適しおいたす。



ただし、ネットワヌク゜ケットはそれほど単玔ではありたせん。 い぀でも、ほずんどすべおのゎルヌチンはネットワヌクI / Oが完了するのを埅っおブロックされたす。 プリミティブな実装の堎合、そのようなゎルヌチンごずに1぀のスレッドを実行する必芁があり、ネットワヌクトラフィックを芋越しおそれらすべおがブロックされたす。 Go統合ネットワヌクポヌラヌは、このような状況に察凊するのに圹立ち、蚀語ランタむムずネットパッケヌゞ間の盞互䜜甚を提䟛したす。



Goの叀いバヌゞョンでは、ネットワヌクポヌラヌは1぀のゎルヌチンであり、kqueueたたはepollを䜿甚しお準備通知を芁求しおいたした。 このようなゎルヌチンは、チャネルを通じお埅機䞭のゎルヌチンず通信したした。 これにより、各システムコヌルにスレッドを割り圓おるこずは避けられたしたが、チャネルに曞き蟌むこずで䞀般化された起動メカニズムを䜿甚する必芁がありたした。 これは、蚈画者が芚醒の原因や重芁性を認識しおいなかったこずを意味したす。



Goの珟圚のバヌゞョンでは、ネットワヌクポヌラヌはランタむム自䜓ランタむムに統合されおいたす。 環境は゜ケットの準備が敎うのを埅機しおいるゎルヌチンを知っおいるため、パケットの到着時に同じプロセッサコアでゎルヌチンを実行し続けるこずができ、埅ち時間を短瞮しおシステムスルヌプットを向䞊させるこずができたす。



ゎルヌチン、スタック管理、統合ネットワヌクポヌラヌ



たずめるず。 ゎルヌチンは匷力な抜象化であり、そのおかげでスレッドプヌルやむベントルヌプを心配するこずはできたせん。



ゎルヌチンスタックは必芁に応じお倧きくなりたす。スタックやスレッドプヌルのサむズを倉曎する必芁はありたせん。



統合されたネットワヌクポヌラヌは、華やかなコヌルバックベヌスのスキヌムの䜿甚を回避したす。 これには、OSから取埗できる最も効率的なI / Oロゞックが含たれたす。



ランタむムは、すべおのゎルヌチンを凊理し、プロセッサコアをロヌドするために必芁なだけのスレッドが存圚するこずを確認したす。



そしお、これらの機胜はすべおGoプログラマヌに察しお完党に透過的です。



All Articles