概要
Goで実際に利用されているOSのスレッド数を知りたいときはなかなか無いと思いますが、知識としてしっておくといいかもしれないですね。
以下のサンプルでは、変化をわかりやすくするために、一つのゴルーチン毎に runtime.LockOSThread() を呼び出して、そのゴルーチンが動くスレッドを束縛するようにしています。
/* Goが内部で利用しているスレッド数を表示するサンプルです。 結果は例えば以下のようになります。(結果は環境によって異なります。) $ go install github.com/go-task/task/v3/cmd/task@latest $ go install honnef.co/go/tools/cmd/staticcheck@latest $ task task: [run] go fmt task: [run] go vet ./... task: [run] staticcheck ./... task: [run] go run main.go [BEFORE] lock-thread=false thread count=5 [AFTER ] lock-thread=false thread count=5 [BEFORE] lock-thread=true thread count=5 [AFTER ] lock-thread=true thread count=15 REFERENCES: - https://blog.rahuldev.in/how-to-implement-concurrency-and-parallelism-in-go */ package main import ( "fmt" "runtime" "runtime/pprof" "sync" "time" ) func fn(lockThread bool, wg *sync.WaitGroup) { defer wg.Done() if lockThread { runtime.LockOSThread() defer runtime.UnlockOSThread() } time.Sleep(1 * time.Second) } func main() { const ( NUM_GOROUTINE = 10 ) var ( threadProfile = pprof.Lookup("threadcreate") ) for _, lockThread := range []bool{false, true} { var ( wg sync.WaitGroup ) fmt.Printf("[BEFORE] lock-thread=%v\tthread count=%d\n", lockThread, threadProfile.Count()) wg.Add(NUM_GOROUTINE) for i := 0; i < NUM_GOROUTINE; i++ { go fn(lockThread, &wg) } wg.Wait() fmt.Printf("[AFTER ] lock-thread=%v\tthread count=%d\n", lockThread, threadProfile.Count()) } }
go-taskのタスクファイルは以下。
version: '3' tasks: default: cmds: - task: run run: cmds: - go fmt - go vet ./... - staticcheck ./... - go run main.go
実行すると以下のようになります。
gitpod /workspace/try-golang (master) $ task -d examples/singleapp/pprof_thread_count/ task: [run] go fmt task: [run] go vet ./... task: [run] staticcheck ./... task: [run] go run main.go [BEFORE] lock-thread=false thread count=5 [AFTER ] lock-thread=false thread count=5 [BEFORE] lock-thread=true thread count=5 [AFTER ] lock-thread=true thread count=15
参考情報
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。