首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我在使用range时看到某些大小的贴图速度变慢了?

为什么我在使用range时看到某些大小的贴图速度变慢了?
EN

Stack Overflow用户
提问于 2013-07-28 23:30:02
回答 1查看 66关注 0票数 0

在我的电脑上,当我点击特定大小的地图时,每秒的读取量会下降,但它不会以线性方式下降。事实上,性能会立即下降,然后随着大小的增加而缓慢恢复:

代码语言:javascript
复制
$ 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

我预计写入偶尔会变慢(因为底层数据结构调整了大小),但读取对大小敏感(而且是一个数量级),这让我感到惊讶。

下面是我用来测试的代码:

代码语言:javascript
复制
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),
    )
}
EN

回答 1

Stack Overflow用户

发布于 2013-07-28 23:53:49

您的代码本身并不衡量map的性能。您的代码衡量了执行随机数生成(不能保证是恒定时间操作)、映射范围(不能保证是恒定时间操作,也不能保证以任何可预测的方式与普通映射访问性能相关)的奇怪组合,甚至可能还衡量了干扰“停止世界”的垃圾收集。

  • 不要编写自己的工作台功能,使用package "testing"提供的功能,它会更好。例如,perform runtime.GC().
  • Now从不依赖样本大小== 1(就像您的代码错误地那样)。
  • 还会在测量时间之外生成所有测试键。然后,为了最小化GC影响,
  • 最终使用B.StartTimer并执行测量的代码路径。

无论如何,你要正确测量的东西也不会有太多用处。map代码是Go运行时的实现细节,可以随时更改。AFAIK,当前的实现与Go 1中的完全不同。

最后:是的,调优好的map实现可能对许多事情很敏感,包括其中项的数量和/或大小和/或类型-甚至体系结构、CPU步进和缓存大小也会在其中发挥作用。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17909822

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档