2014-10-01 34 views
7

[CEVAP] Git, stdout'u arabelleğe almıyor. Tamponlu bir versiyona geçmek ve manuel olarak yıkamak, beklediğinize çok daha yakındır. Fmt'den kaçınmak, istediğiniz kadar hızlı çalışmasını sağlar.FizzBuzz programı yavaş görünüyor: Neden?

Git'de FizzBuzz programını yazmaya çalışıyorum.

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 ile 1 milyon arasında bir sayı için çalıştırdığımda, tamamlanması bir saniyeden kısa sürüyor. Eşdeğer programı C, Rust, Haskell veya Python'da yazdığımda, yarım saniyeden (Python) sıfır saniyeye (Rust ve Haskell) kadar her yerde bir yer alır.

Bu beklenebilir mi, yoksa bazı Go-fu'ları mı özlüyorum? Git neden diğer dillerden daha yavaş görünüyor? Robert Harvey tarafından önerildiği gibi profilcisine ile Koşu

[DÜZENLE]

.

Zamanın% 100'ünün baskıda harcadığı gibi görünüyor. (* Fmt) .fmt_complex, println (?) Ile ilgili olduğunu tahmin ediyorum. Ayrıca programı fmt.Sprint yerine strconv.Itoa ile denedim ve hafif performans artışı (~ 0.2s) elde ettim ama aynı temel sonuçları elde ettim.

Yavaş mı, neden bu kadar baskı yapıyor? jgritty eşdeğer Python programı ve zamanlamaları için

[DÜZ]

. Baskı neden daha yavaş? Farkında olmadığım sahnelerin ardında bir şey mi var?

$ 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 
+0

http://blog.golang.org/profiling-go-programs Haskell tembel dil olduğunu –

+0

Not; Çıktının gerçekten sorulmasına kadar muhtemelen sonuçlarınızı değerlendirmiyordur. Aynı büyük olasılıkla Rust doğrudur. –

+0

Belki diğer dillerden başlamak için gitmek daha uzun sürer? Program sürecini daha fazla veriyi denemeyi denediyseniz, çalıştırmanız yaklaşık 10 saniye sürer? –

cevap

7

Standart çıktı, Python ve C'de arabelleğe alınır, ancak Gitmez. Elmaların çıkışını elma karşılaştırması için tamponlayın. Bu neredeyse zamanımı dizüstü bilgisayarımda yarıya indirdi.

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

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

başka iyileştirme için fmt package kullanımını ortadan kaldırın:

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) 
    } 
} 
+0

Sanırım, Println yerine fmt.Fprintln demek istediniz. – Joseph

+0

Bu bana büyük bir performans artışı sağladı! Dört kat hızlanır ve saniyenin çeyreğine ineriz. – Joseph

+2

Go'nun, stdout'u varsayılan olarak tampon etmemeye karar vermesi ilginç: mantık nedir? – Joseph

İlgili konular