🔩 ねじき教室 Go と Web の教室

待ちは積み上がる

読了目安 約2分

競プロにない「待ち時間」を逐次コードで体感し、Web の速さが計算ではなく待ちの重ね方で決まることを確かめます。

この章の目次

競プロのプログラムは、入力を読み、計算し、出力して終わります。 時間はほぼ計算量で決まり、CPU はずっと働きっぱなしです。

Web は違います。 処理時間の大半は「データベースの応答待ち」で、その間 CPU は何もせず待っています。

逐次だと待ちが直列に積み上がる

Go
package main

import (
	"fmt"
	"time"
)

func query(id int) {
	time.Sleep(100 * time.Millisecond) // データベースへの問い合わせのつもり
	fmt.Printf("問い合わせ %d 完了\n", id)
}

func main() {
	start := time.Now()
	for i := 1; i <= 5; i++ {
		query(i)
	}
	fmt.Println("所要時間:", time.Since(start).Round(time.Millisecond))
}

1 件 100 ミリ秒の待ちが 5 件で、所要時間はおよそ 500 ミリ秒です。 CPU は 500 ミリ秒のうちほとんど遊んでいるのに、待ちを 1 件ずつ順番に消化しているからです。

競プロでは、そもそも非同期の処理を書く場面がほとんどありません。 入力は最初から全部手元にあり、応答を待つ相手がいないからです。 だから上から順に計算する逐次の書き方で何も困りません。

Web では待ちを重ねたい

5 件の待ちを重ねられれば、所要時間は 100 ミリ秒で済みます。 待っている間に次を始める、という動きです。 これは、上から順に実行する逐次のコードでは書けません。

待ちを重ねる道具が goroutine です。

試してみよう

  1. 件数を 5 から 50 に増やして、所要時間がおよそ 10 倍になることを確かめてください。待ちが積み上がっている証拠です。