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に記載されているように、スケジューラは決して完璧ではありません。 深刻な改善が将来計画されています。 個人的には、ゴルーチンを優先する可能性を主に期待しています。

Source: https://habr.com/ru/post/J141853/


All Articles