CodeBlanks Logo Icon CodeBlanks

Meydan okuma 3 - Performance

  • Go kursu
  • İleri seviye
  • Ders 67/68
  • 8 dk

Benchmark ve pprof ile darboğaz bulan bir analiz yazarsın.

Meydan okuma: ayırmayı azalt

Elinde sayıları virgülle birleştiren yavaş bir fonksiyon var:

func yavas(n []int) string {
    s := ""
    for i, x := range n {
        if i > 0 { s += "," }
        s += strconv.Itoa(x)
    }
    return s
}

Her += yeni bir string ayırır. Görevin: aynı çıktıyı strings.Builder ve strconv.AppendInt ile çok daha az ayırmayla üretmek ve farkı testing.AllocsPerRun ile ölçmek.

Plan

Önce kapasite ayır: her sayı için en fazla ~20 bayt yeter, buf := make([]byte, 0, len(n)*21). Döngüde virgül ve strconv.AppendInt(buf, int64(x), 10) ekle; sonunda string(buf) döndür. Ölçüm için iki fonksiyonu da testing.AllocsPerRun(100, ...) içinde çalıştır ve sonuçları karşılaştır. Çıktıların eşit olduğunu da kontrol et.

Uygulama Hızlı sürüm

yavas ve hizli fonksiyonlarını yaz. n := []int{1, 22, 333, 4444} için iki çıktının eşit olduğunu ve hizli'nin ayırma sayısının yavas'tan az olduğunu tek satırda yazdır.

Başlangıç kodu

main.go
package main

import (
    "fmt"
    "strconv"
    "testing"
)

func main() {
    // buraya yaz
}

Örnek çözüm

main.go
package main

import (
    "fmt"
    "strconv"
    "testing"
)

func yavas(n []int) string {
    s := ""
    for i, x := range n {
        if i > 0 {
            s += ","
        }
        s += strconv.Itoa(x)
    }
    return s
}

func hizli(n []int) string {
    buf := make([]byte, 0, len(n)*21)
    for i, x := range n {
        if i > 0 {
            buf = append(buf, ',')
        }
        buf = strconv.AppendInt(buf, int64(x), 10)
    }
    return string(buf)
}

var sink string

func main() {
    n := []int{1, 22, 333, 4444}
    a := testing.AllocsPerRun(100, func() { sink = yavas(n) })
    b := testing.AllocsPerRun(100, func() { sink = hizli(n) })
    fmt.Println(yavas(n) == hizli(n), b < a)
}

Beklenen çıktı

true true

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 <code>strconv.AppendInt</code>'i <code>Itoa</code>'dan avantajlı yapan nedir?

  • Eşzamanlı çalışır
  • Sayıyı var olan bir bayt dilimine yazar, ara string oluşturmaz Doğru cevap
  • Daha kısa yazılır
  • Ondalık sayıları da destekler

Açıklama: Itoa her sayı için yeni bir string ayırır; AppendInt verilen tampona ekler ve tampon yeterince büyükse ayırma yapmaz.

2 Tampona ekle

Soru
buf = strconv.____(buf, int64(x), 10)
Cevap
buf = strconv.AppendInt(buf, int64(x), 10)

Açıklama: AppendInt sayının ondalık gösterimini mevcut bayt dilimine ekler.

3 Yöntem ve maliyet

Kavram Anlamı
s += ... Her adımda yeni string
strconv.Itoa Sayı başına bir string
AppendInt Tampona yazar
make(..., 0, cap) Önceden kapasite

İleri seviye bölümündeki tüm dersler