FizzBu​​zz程序似乎很慢:为什么?

Jos*_*eph 6 performance fizzbuzz go

[ANSWER] Go不缓冲标准输出.切换到缓冲版本并手动刷新使其更接近您的预期.避免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)
  }
}
Run Code Online (Sandbox Code Playgroud)

当我为1到100万的数字运行时,只需不到一秒钟即可完成.当我用C,Rust,Haskell或Python编写等效程序时,它需要从半秒(Python)到零秒(Rust和Haskell).

这是预期的,还是我错过了一些Go-fu?为什么go似乎比其他语言慢?

[编辑]

按照Robert Harvey的建议运行探查器.

看起来100%的时间花在了fmt.(*fmt).fmt_complex上,我猜这与Println(?)有关.还尝试使用strconv.Itoa而不是fmt.Sprint的程序,我获得了轻微的性能提升(~0.2s),但基本结果相同.

印刷是否缓慢,如果是这样,为什么?

[编辑]

对于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
Run Code Online (Sandbox Code Playgroud)

小智 6

标准输出在Python和C中缓冲,但不是Go.缓冲输出以进行苹果对苹果的比较.这几乎减少了我笔记本电脑上的时间.

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    w := bufio.NewWriter(os.Stdout)
    for i := 1; i <= 1000000; i++ {
         fmt.Fprintln(w, fizzbuzz(i))
    }
    w.Flush()
}
Run Code Online (Sandbox Code Playgroud)

消除使用fmt软件包进行另一项改进:

package main

import (
    "bufio"
    "os"
    "strconv"
)

func main() {
    w := bufio.NewWriter(os.Stdout)
    for i := 1; i <= 1000000; i++ {
        w.WriteString(fizzbuzz(i))
        w.WriteString("\n")
    }
    w.Flush()
}

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 strconv.Itoa(n)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 有趣的是,Go决定不默认缓冲stdout:理由是什么? (2认同)