なぜGoは並行処理に優れているか?

Go言語

Goがなぜ並行処理に長けているのか、Gorutineのどのような部分が良いのかについて解説をしていきます。

スタック、ヒープ

Goroutineの良さを知るためにはまずスタック、ヒープを知っておく必要があります。
スタックは引数や変数、返り値、静的な構造体など静的なデータが格納されていて、OSによって管理がされている。
ヒープは関数スコープにとらわれず、オブジェクト持ち続けていて、ガベージコレクションなどソフトウェア側で管理されている。
データのアクセスはスタックが高速になる。

Goroutineについて

Goroutineは主に2つの特徴があります。

  • メモリ効率が良い
  • スイッチングコストが低い

それぞれについて解説していきます。

メモリ効率が良い

スレッドの場合は、スレッド間でメモリが干渉し合わないようにスタックガードページと呼ばれる1MBの領域を確保している。Goroutineはコンパイラ側で必要に応じてヒープ領域を割り当てるようにしているため、スタック領域2KBしか消費しないで済み、メモリ効率が良い。

スイッチングコストが低い

OSスレッドはコンテキストスイッチによるオーバーヘッドが大きい。
それに比べて、GoランタイムはM個のGoroutineをN個のOSスレッドで実行するM:Nモデルを採用している。Goのランタイムによって多くのGoroutineがOSの1スレッド上で多重化されている。これによりGoroutineは生成するのも切り替えるのも安価になる。GoのプロセスごとのOSのスレッドは比較的数が少なくなっていて、Goのランタイムは使われてないOSスレッドに実行可能なGorutineを割り当てる。
問題としてスケジューリングをするのが複雑になるが、Goの場合はGoランタイムスケジューラーがこの問題を解決してくれている。

Goランタイムスケジューラー

Goランタイムスケジューラーは、Gorutineの数がOSスレッド数を上回ってしまった場合にリソースうまく振り分ける役目をする。
Goランタイムのコンポーネントとして、以下がある。

  • G(Gorutine)
  • M(Machine):OSスレッド
  • P(Processor):Goroutineを実行するのに必要なPCリソース。OSスケジューラにとってCPUのようなもの

Goランタイムスケジューラのイメージ図

Gの実行には3パターンある

  1. グローバルキューに実行可能なGがないかを確認、あればそのGを実行
  2. 1でGがない場合、動いているPのローカルキューに実行可能なGがあるかを確認、あればそのGを実行
  3. キューにGがなかった場合は、他を見つけに行き、忙しいPからGを横取りする

Goroutineを使う上での注意点

  • WaitGroup、channelなどを使用して、終了をブロックをする必要がある。
  • 配列やマップなどはアトミックな操作ができないため、使用する時にはスレッドセーフにする。RWMutexを使用する。
  • 順番通りに実行されないので、順番を気にする場合はGoroutineは使用しない。
  • リソースを無限に使われないために、必要あればGoroutineの同時実行数を制限する必要がある。

理解度チェック

今回の内容がわかっているかの問題を作成しています。
問題をクリックすると、答えが表示されますので、今回の内容を理解できたかチェックをしてみてください。

Q.Goroutineの2つの特徴は?
A.メモリ効率が良い、スイッチングコストが低い

Q.Goroutineを使う上での注意点4つ
A.
・WaitGroup、channelなどを使用して、終了をブロックをする必要がある。
・配列やマップなどはアトミックな操作ができないため、使用する時にはスレッドセーフにする。RWMutexを使用する。
・順番通りに実行されないので、順番を気にする場合はGoroutineは使用しない。
・リソースを無限に使われないために、必要あればGoroutineの同時実行数を制限する必要がある。

まとめ

今回はGoroutineがなぜ良いのか、また使用するときの注意点について紹介をしてきました。
注意点で、Goroutineの同時実行数の制限をかける必要があると書きましたが、その対応について記事を書いていたり、他にも低レイヤーな内容を書いている記事もありますので、興味があればそちらも読んでみてください。

【おすすめ記事のリンク】

参考

【Go言語入門】goroutineとは? 実際に手を動かしながら goroutineの基礎を理解しよう! | 株式会社ARISE analytics(アライズ アナリティクス)
はじめまして。2022年4月に中途入社し、現在Analytics Delivery Divisionでバックエ …

イベントループなしでのハイパフォーマンス – C10K問題へのGoの回答 | POSTD
この投稿は、私が去年OSCONで行ったプレゼンテーションを基に作成しています。プレゼンよりは簡潔に編集し直し、プレゼン後にいただいたいくつかのフィードバックに応える形で記事を書いています。 Go言語…

コメント

タイトルとURLをコピーしました