7

[回答] Go は stdout をバッファリングしません。バッファリングされたバージョンに切り替えて手動でフラッシュすると、期待するものにはるかに近づきます。fmt を回避すると、好きなだけ速く実行できます。

Go で FizzBu​​zz プログラムを作成しようとしています。

func main() {
  for i := 1; i <= 1000000; i++ {
    fmt.Println(fizzbuzz(i))
  }
}

func fizzbuzz(n int) string {
  fizzy := n%3 == 0
  buzzy := n%5 == 0

  switch {
  case fizzy && buzzy:
    return "FizzBuzz"
  case fizzy:
    return "Fizz"
  case buzzy:
    return "Buzz"
  default:
    return fmt.Sprint(n)
  }
}

1 から 100 万までの数値に対して実行すると、完了するまでに 1 秒もかかりません。C、Rust、Haskell、または Python で同等のプログラムを作成すると、0.5 秒 (Python) から 0 秒 (Rust と Haskell) までかかります。

これは当然のことでしょうか、それとも Go-fu が不足しているのでしょうか? go が他の言語よりも遅いように見えるのはなぜですか?

[編集]

Robert Harvey によって提案されたプロファイラーで実行します。

時間の 100% が fmt.(*fmt).fmt_complex に費やされているように見えますが、これは Println(?) に関連していると推測しています。また、fmt.Sprint の代わりに strconv.Itoa を使用してプログラムを試してみたところ、パフォーマンスがわずかに向上しましたが (~0.2 秒)、基本的な結果は同じでした。

遅いのは印刷ですか? もしそうなら、それはなぜですか?

[編集]

jgritty の場合、同等の Python プログラムとタイミング。印刷が遅い理由に興味がありますか? 私が気付いていない舞台裏で何かをしているのですか?

$ cat fizzbuzz.py
def fizzbuzz(n):
    fizzy = n%3 == 0
    buzzy = n%5 == 0

    if fizzy and buzzy:
        return "FizzBuzz"
    elif fizzy:
        return "Fizz"
    elif buzzy:
        return "Buzz"
    else:
        return ("%u" % n)

def main():
    for i in range(1, 10**6):
        print(fizzbuzz(i))

main()
$ time pypy3 fizzbuzz.py >/dev/null

real    0m0.579s
user    0m0.545s
sys     0m0.030s
4

1 に答える 1