Go言語で並列処理
Go言語でサーバのパフォーマンスを向上させる!というタスクがあったとします。その場合、シングルスレッドで直列的に処理をしていてはパフォーマンスは大きく下がってしまうと思います。そこで並列処理の登場です!
並列処理とは
マルチスレッドで複数の処理を同時に処理することです。例えば、あるスレッドではループ処理をして、もう一方のスレッドではデータベースアクセスをする等同時に処理することで処理のスピードは大幅に変わります。
実験
実際に実装してみて処理時間に差が出るが見てみましょう。なお処理時間の差がわかりやすくなるように1千万回ループしています。
直列処理
まずはシングルスレッドでの直列的な処理です。
package main
import (
"fmt"
"time"
)
func loop(id int) {
for i := 0; i < 10000000; i++ {
}
}
func main() {
start := time.Now()
loop(1)
loop(2)
loop(3)
end := time.Now()
fmt.Printf("%f秒\n", (end.Sub(start)).Seconds())
}
結果は以下のようになりました。
$ go run main.go
0.017746秒
これだけみてもよくわからないので次に並列処理です。
並列処理
go言語にはGoroutineというものがあり、関数名の前にgo
をつけるだけで並列処理になります。また、channelというものもありデータの送受信などが出来るみたいですが今回は返り値がないので適当にbooleanを返しておきます。実装は以下のようになります。
package main
import (
"fmt"
"time"
)
func loopByParallel(id int, ch chan bool) {
for i := 0; i < 10000000; i++ {
}
ch <- true
}
func main() {
start := time.Now()
ch1 := make(chan bool)
ch2 := make(chan bool)
ch3 := make(chan bool)
go loopByParallel(1, ch1)
go loopByParallel(2, ch2)
go loopByParallel(3, ch3)
<-ch1
<-ch2
<-ch3
end := time.Now()
fmt.Printf("%f秒\n", (end.Sub(start)).Seconds())
}
これで3つのループ処理が並列に処理されるはずです。結果を見てみましょう。
$ go run main.go
0.007073秒
見事に実行時間が2/5程度になりました!
まとめ
いかがだったでしょうか?今度はchannelの正しい使い方やWebサーバへの応用なども見ていきたいところです!それでは