Gorutins:あなたが知りたいが、尋ねることを恐れていたすべて

この記事では、ゴルーチンの概要、使用するタイミング、システムスレッドとの関係、スケジューラの動作方法について簡単に簡潔に説明します。



どんなゴルーチン?


ゴルーチンは、同じアドレス空間にある他のゴルーチンと競争的に実行する機能です。



goroutineの実行は非常に簡単です。

go normalFunc(args...)







normalFunc(args...)



関数は、それを呼び出したコードと非同期に開始します。



ゴルーチンは非常に軽量であることに注意してください。 ほぼすべての費用はスタックの作成であり、必要に応じて拡大できますが、非常に小さいです。



グラム単位でいくらですか?


ナビゲートしやすくするために、 経験的に得られた数値を考慮してください。



平均して、 ゴルーチンごとに約4.5kbを期待できます。 つまり、たとえば、4GbのRAMがある場合、約80万個の作業用ゴルーチンを含めることができます。 たぶん、これはErlangファンを感動させるのに十分ではありませんが、私にはその数字は非常にまともなようです:)



それでも、可能な限りgoroutineに機能を無意識に割り当てるべきではありません。 これは、次の場合に利点をもたらします。





「十分な」-いくらですか? これは難しい質問です。 ほとんどの場合、特定の状況に応じて決定する必要があります。 私のハードウェア(atom d525 64bit)での経験から、それは〜50μsであるとしか言えません。 一般的に、フレアをテストして開発します;)



システムスレッド


ソースコード( src / pkg / runtime / proc.c )では次の用語が受け入れられます

G(ゴルーチン)-ゴロティナ

M(マシン)-マシン



各マシンは別々のスレッドで動作し、一度に1つのGorutinのみを実行できます。 プログラムが実行されるオペレーティングシステムのスケジューラは、マシンを切り替えます。 実行中のマシンの数は、 GOMAXPROCS



環境GOMAXPROCS



またはruntime.GOMAXPROCS(n int)



関数によって制限されます。 デフォルトでは1です。通常、コアの数と等しくするのが理にかなっています。



Go Scheduler


スケジューラの目標は、すぐに実行できるゴルーチン(G)を空きマシン(M)に配布することです。







スケジューラの図と説明は、 Google Goの Sindre Myren RT Capabillitesの研究から引用したものです。



すぐに使用できるゴルーチンは、優先順位の順に実行されます。つまり、FIFO(先入れ先出し)です。 ゴルーチンの実行は、 システムコールまたは同期オブジェクト (チャネル、ミューテックスなどの操作)の使用が原因で実行できなくなった場合にのみ中断されます 。 goroutineの作業にはタイムスライスがありません。その後、再びキューに戻されます。 スケジューラーがこれを行えるようにするには、 runtime. Gosched ()



自分で呼び出す必要がありますruntime. Gosched ()



runtime. Gosched ()







関数の実行準備が整うとすぐに、再びキューに入ります。



結論


私はすぐに、現状が私を驚かせたと言います。 なんらかの理由で、無意識のうちに、「並列性」の向上を期待していました。おそらく、ゴルーチンを軽量のシステムフローとして認識しているからでしょう。 ご覧のとおり、これは完全に真実ではありません。



実際には、これは主に、 runtime. Gosched ()



を使用する価値があることを意味しruntime. Gosched ()



runtime. Gosched ()



。これにより、いくつかの長命のゴルーチンが、他のすべてのゴルーチンの作業を大幅に停止しないようにします。 一方、そのような状況は実際には非常にまれです。



また、現時点では、ドキュメントと公式FAQに記載されているように、スケジューラは決して完璧ではありません。 深刻な改善が将来計画されています。 個人的には、ゴルーチンを優先する可能性を主に期待しています。



All Articles