0

私のコンピューターでは、特定のサイズのマップに到達すると 1 秒あたりの読み取りが低下するのが見られますが、直線的に低下するわけではありません。実際、パフォーマンスはすぐに低下し、サイズが大きくなるにつれてゆっくりと戻ります。

$ go run map.go 425984 1 425985
    273578 wps ::   18488800 rps
    227909 wps ::    1790311 rps

$ go run map.go 400000 10000 500000
    271355 wps ::   18060069 rps
    254804 wps ::   18404288 rps
    267067 wps ::   18673778 rps
    216442 wps ::    1984859 rps
    246724 wps ::    2461281 rps
    282316 wps ::    3634125 rps
    216615 wps ::    4989007 rps
    276769 wps ::    6972233 rps
    212019 wps ::    9756720 rps
    286027 wps ::   14488593 rps
    227073 wps ::   17309822 rps

(基礎となるデータ構造のサイズが変更されるため) ときどき書き込みが遅くなることを期待していましたが、読み取りがサイズに (そして桁違いに) 敏感であることに驚きました。

これをテストするために使用しているコードは次のとおりです。

package main

import (
    "bytes"
    "fmt"
    "math/rand"
    "os"
    "strconv"
    "time"
)

func main() {
    start, _ := strconv.ParseInt(os.Args[1], 10, 64)
    step, _ := strconv.ParseInt(os.Args[2], 10, 64)
    end, _ := strconv.ParseInt(os.Args[3], 10, 64)
    for n := start; n <= end; n += step {
        runNTimes(n)
    }
}

func randomString() string {
    var b bytes.Buffer

    for i := 0; i < 16; i++ {
        b.WriteByte(byte(0x61 + rand.Intn(26)))
    }

    return b.String()
}

func perSecond(end time.Time, start time.Time, n int64) float64 {
    return float64(n) / end.Sub(start).Seconds()
}

func runNTimes(n int64) {
    m := make(map[string]int64)

    startAdd := time.Now()
    for i := int64(0); i < n; i++ {
        m[randomString()]++
    }
    endAdd := time.Now()

    totalInMap := int64(0)
    startRead := time.Now()
    for _, v := range m {
        //get around unused variable error,
        //v should always be > 0
        if v != 0 {
            totalInMap++
        } 
    }
    endRead := time.Now()

    fmt.Printf("%10.0f wps :: %10.0f rps\n",
        perSecond(endAdd, startAdd, n),
        perSecond(endRead, startRead, totalInMap),
    )
}
4

1 に答える 1