読者です 読者をやめる 読者になる 読者になる

初老のボケ防止日記

おっさんのひとりごとだから気にしないようにな。

スポンサーリンク

Go言語のGoルーチンとは



稲垣goroutine


Go言語の目玉である「goroutine(Goルーチン)」。

一言で言えば

A goroutine is a lightweight thread managed by the Go runtime.

A Tour of Go

ということらしいのだが、

Go言語ランタイムで管理された軽量スレッドってどういう意味だ?

ということで実験してみる。

環境

今回はLinux環境で試したいのでAWSにした。

インスタンスタイプ t.2micro
AMI Ubuntu14.04(ami-a21529cc)
Go go1.6.2 linux/amd64

サンプルコード

こんな感じ。

  • ayame.go
package main

import (
        "fmt"
        "github.com/c9s/goprocinfo/linux"
        "github.com/shirou/gopsutil/cpu"
        "os"
        "runtime"
        "time"
)

func baki(i int) {
        for {
                i++
                time.Sleep(time.Millisecond * 5)
        }
}

func main() {
        pid := os.Getpid()
        for {

                g := runtime.NumGoroutine()
                t := getThreadCount(pid)
                u := getCpuUsage()
                fmt.Printf("%v,%v,%.2f\n", g, t, u)
                time.Sleep(time.Second * 1)
                for i := 1; i <= 100; i++ {
                        go baki(i)
                }
                if g > 10000 {
                        break
                }
        }
}

処理としては以下になっている。

  • 毎秒100ずつgoroutine「baki」を実行
  • 「baki」は5ミリ秒で無限ループ
  • 実行中のgoroutine数が1万超えたら終了

で、毎秒以下をモニタリングして出力する。

  1. 現在起動しているgoroutineの数
  2. プロセス内のスレッド数
  3. EC2インスタンスのCPU使用率

「GOMAXPROCS」については、今回試したインスタンスタイプはt2.microなのでNumCPUが1となるのでそのままにした。

スレッド数と、CPU使用率は標準パッケージで取得できない(わからなかった)ので、以下の外部パッケージで出力するようにした*1

github.com
github.com

これらのパッケージの取得した値は以下のPSコマンドやhtopの出力結果と大体あっているので問題なさそう。

ps huH p <PID_OF_U_PROCESS> | wc -l

htop - an interactive process viewer for Unix

なお、現在起動しているgoroutineの数にはmainやシステム的なものが含まれるので今回の環境ではbakiを起動する前から2となる。

実行結果

実行結果をグラフにしたのがコチラ。プログラムを実行したインスタンスは今回の実験用に生成したものでOSインストール状態以外に特別なプロセスを起動していない。

f:id:osa030:20160716113200p:plain

グラフ化してないけど何度か試してみた感じでは傾向は同じ。
つまり、goroutineの数や処理負荷に応じてスレッド数が無尽蔵にガンガン増加する訳ではないようだ*2。つまり、

goroutineイコールThreadではない。

Go言語ランタイムが生成管理を行うスレッド上であたかもスレッドのように実行されるのがgoroutineという感じか。runtimeパッケージでスレッド数を取得できなかったり、logでスレッドIDを出力できなさそうなことから、もしかしたらGo言語は他の言語と違ってプログラム内でスレッドを意識させないようにしているのではないかという憶測をたてていたのだが、どうもそんな感じらしい。要は

ユー達はスレッドは意識しないでいいから並行処理書いちゃいなよ!

ということなんだろう。確かに並行処理されることだけ意識していればスレッドかプロセスかなんてどうでもいい話ですよ。マスコットキャラはブサイクなのに男前な言語である。

今回こんな実験をした理由は、何でもかんでもGoルーチンにするのは楽だけど、いわゆるC10K問題に対してGo言語はどうすればいいのだろうかという疑問があったのだが、ちゃんとそこら辺も考慮はされているようだ。

postd.cc

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

*1:計算すればgoprocinfoでCPU使用率も出せると思うが面倒くさいので楽をした

*2:当然「GOMAXPROCS」の設定値によって、生成されるスレッド数の上限数は変化すると思う

スポンサーリンク