Go言語で並列処理を実装してみた!圧倒的なシンプルさと性能

Go言語は、Googleによって設計された「シンプルで高速なプログラミング言語」として広く知られています。特にGoの並列処理の簡潔さと高性能は、多くの開発者にとって魅力的です。

今回は、Go言語で並列処理を実装し、他の言語(C言語、Python、Java、Ruby)と比較した結果を共有します。Goが「なぜ選ばれるのか」を、実際のコードとともに掘り下げていきます。

テスト仕様

テスト環境の仕様

  • CPU: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
  • RAM: 32.0 GB
  • OS: Windows 11 Pro 64ビット

使用言語とバージョン

  • Go 1.23.4
  • Java 21.0.5
  • Python 3.11.7(GIL有効。並列処理)
  • Python 3.13.1t (GIL無効。並列処理)
  • Ruby 3.3.6
  • C言語:GCC 14.2.0

準備した各ソースコード

Go言語での並列処理プログラム

以下は、Goで10万回のトランザクションを並列処理するプログラムの例です。

プログラムコード

package main

import (
	"fmt"
	"sync"
	"time"
)

func processTransaction(id int) {
	// 模擬トランザクション処理
	_ = id * 2
}

func main() {
	var wg sync.WaitGroup
	start := time.Now()

	transactionCount := 100000
	wg.Add(transactionCount)

	for i := 0; i < transactionCount; i++ {
		go func(id int) {
			defer wg.Done()
			processTransaction(id)
		}(i)
	}

	wg.Wait()
	fmt.Printf("Completed %d transactions in %v\n", transactionCount, time.Since(start))
}

コードの解説

  1. goroutineを利用した並列処理
    • goキーワードを使うだけで、並列タスクを簡単に作成可能。
    • goroutineは軽量で、数百万単位でも効率的に動作します。
  2. sync.WaitGroupによるタスクの同期
    • sync.WaitGroupを使い、すべてのgoroutineが完了するまでメインスレッドを待機。
    • 並列処理の終了を簡単に管理できます。
  3. 時間計測
    • time.Now()で開始時刻を記録し、time.Since(start)で実行時間を算出。
  4. シンプルな構文
    • スレッドやメモリ管理を意識する必要がなく、短いコードで実装可能。

Go言語の強み

  1. 軽量な並列処理
    • goroutineはOSスレッドよりも軽量で、高速かつ低メモリで動作。
    • Goランタイムがスレッドのスケジューリングを自動で管理。
  2. 簡潔なコード
    • 並列処理を記述するのに必要なのはgoキーワードと同期用のWaitGroup
    • 他の言語に比べ、圧倒的にシンプル。
  3. 高いパフォーマンス
    • Goはコンパイル型言語で、バイナリファイルを直接実行。
    • goroutineとGoランタイムによる最適化がパフォーマンスを向上させます。
言語実行時間特徴
Go1.23.433.4msgoroutineによる軽量かつ高速な並列処理
Java 20.0.560.7ms固定スレッド数で効率的な並列処理を実現。
Python 3.11.71.1秒GILの恩恵を受けている。
Python 3.13.11.4秒GIL無効化した場合、期待が外れてオーバーヘッドが大きくなった可能性が大きい。
C 言語14.2.04.4秒C言語は思ったより遅い結果に。
Ruby3.3.657.8秒スレッドのオーバーヘッドが大きい。

なぜGo言語が選ばれるのか?

  1. 開発効率
    • goroutineとWaitGroupを使った並列処理は、他言語に比べて非常に簡潔で直感的。
    • コードの可読性が高く、保守が容易。
  2. パフォーマンス
    • Goのランタイムがgoroutineを効率的にスケジュール。
    • 高速なコンパイルと軽量な実行バイナリにより、性能を最大限に引き出します。
  3. 適用分野
    • Webサーバー、マイクロサービス、リアルタイムシステムなど、大量の並列処理が必要な場面で特に強い。

他言語の課題

Java

  • スレッドプールは強力だが、スレッドのオーバーヘッドがGoに比べて大きい。

C言語

  • 最速だが、コードが複雑で開発・保守の負担が大きい。
  • メモリ管理やスレッド制御を手動で行う必要がある。

Python

  • GIL(Global Interpreter Lock)の影響で、CPUバウンド処理は遅い。
  • I/Oバウンド処理では効果的。
  • GILが処理性能の足かせになる場面を想定し、Python 3.13.1でGILを無効化して並列処理を試しました。しかし、今回の処理内容(比較的単純なトランザクション計算)では、GIL有効時の方が効率的に動作しました。期待通りの結果にはなりませんでしたが、GILが必ずしも性能を妨げるわけではない点が確認できました。

Ruby

  • スレッドのオーバーヘッドが大きく、GILにより並列性能が制限される。

まとめ

Go言語は、簡潔さ、高速性、スケーラビリティを兼ね備えたプログラミング言語です。特に並列処理においては、goroutineとランタイムの最適化により、非常に効率的な実装が可能です。

Goを選ぶべき場面

  • 並列処理が大量に発生するシステム(Webサーバー、リアルタイム処理など)。
  • 高いパフォーマンスが求められる場面。
  • 短い開発期間で保守性の高いコードが求められる場合。

Go言語は「並列処理のエース」として活躍すること間違いなし!ぜひ実際にコードを書いて体感してみてください!

Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です