草庐IT

windows - 性能随机下降

coder 2023-06-27 原文

我是 Go 的新手,最近有一些事情让我很困惑。

我有一段代码(下面发布的简化版本),我试图测量它的性能。我用两种方式做到了这一点:1) 带有测试包的基准 2) 手动记录时间

运行基准测试输出结果

30000 55603 ns/op

这很好,但是...当我对同一函数执行 30k 次运行并记录每次迭代的时间时,我得到如下输出:

测试耗时 0 ns 测试耗时 0 ns ... ~10 条记录都一样 测试耗时 1000100 ns 测试耗时 0 ns 测试耗时 0 ns ...又是很多零 测试耗时 0 ns 测试耗时 1000000 ns 测试耗时 0 ns ...

计算表明平均值确实是 55603 ns/op,正如基准所声称的那样。

好吧,我说过,我在优化性能方面不是那么擅长,在所有硬核编译器的东西中也不擅长,但我猜这可能是随机垃圾收集?所以我打开 gc 日志,确保它显示一些输出,然后关闭 gc 以保持良好的 aaand...没有垃圾收集,但我看到了相同的图片 - 有些迭代需要一百万倍的时间(?)。

我对所有这一切的理解有 99% 是错误的,也许有人能给我指明正确的方向,或者也许有人确切地知道到底发生了什么? :)

附言此外,对我来说,不到一纳秒 (0 ns) 有点令人惊讶,这似乎太快了,但程序确实提供了计算结果,所以我不知道该想些什么了。 T_T

编辑 1:回答 Kenny Grant 的问题:我使用 goroutines 来实现某种值生成器以具有惰性,现在我删除了它们并简化了代码。这个问题现在不那么频繁了,但它仍然可以重现。 Playground 链接:https://play.golang.org/p/UQMgtT4Jrf 有趣的是,这不会发生在 Playground 上,但仍然会发生在我的机器上。

编辑 2:我在 win7 x64 上运行 Go 1.9

编辑 3:感谢回复,我现在知道这段代码不可能在 Playground 上正常工作。我将在此处重新发布代码片段,以免我们丢失它。 :)

type PrefType string
var types []PrefType = []PrefType{
    "TYPE1", "TYPE2", "TYPE3", "TYPE4", "TYPE5", "TYPE6",
}

func GetKeys(key string) []string {
    var result []string
    for _, t := range types {
        rr := doCalculations(t)
        for _, k := range rr {
            result = append(result, key + "." + k)
        }
    }
    return result
}

func doCalculations(prefType PrefType) []string {
    return []string{ string(prefType) + "something", string(prefType) + "else" }
}

func test() {
    start := time.Now()
    keysPrioritized := GetKeys("spec_key")
    for _, k := range keysPrioritized {
        _ = fmt.Sprint(k)
    }
    fmt.Printf("test took %v ns\n", time.Since(start).Nanoseconds())
}

func main() {
    for i := 0; i < 30000; i++  {
        test()
    }
}

这是我机器上的输出:

编辑 4:我在装有 Ubuntu 17.04 的笔记本电脑上进行了同样的尝试,输出是合理的,没有零和数百万。似乎是编译器/运行时库中特定于 Windows 的问题。如果有人可以在他们的机器上验证这一点(Win 7/8/10),那就太好了。

最佳答案

在 Windows 上,对于如此短的持续时间,您没有足够精确的时间戳。 Linux 有更精确的时间戳。根据设计,Go 基准测试至少运行一秒钟。 Go1.9+使用单调(m)值来计算持续时间。

在 Windows 上:

timedur.go:

package main

import (
    "fmt"
    "os"
    "time"
)

type PrefType string

var types []PrefType = []PrefType{
    "TYPE1", "TYPE2", "TYPE3", "TYPE4", "TYPE5", "TYPE6",
}

func GetKeys(key string) []string {
    var result []string
    for _, t := range types {
        rr := doCalculations(t)
        for _, k := range rr {
            result = append(result, key+"."+k)
        }
    }
    return result
}

func doCalculations(prefType PrefType) []string {
    return []string{string(prefType) + "something", string(prefType) + "else"}
}

func test() {
    start := time.Now()
    keysPrioritized := GetKeys("spec_key")
    for _, k := range keysPrioritized {
        _ = fmt.Sprint(k)
    }
    end := time.Now()
    fmt.Printf("test took %v ns\n", time.Since(start).Nanoseconds())
    fmt.Println(start)
    fmt.Println(end)
    if end.Sub(start) < time.Microsecond {
        os.Exit(1)
    }
}

func main() {
    for i := 0; i < 30000; i++ {
        test()
    }
}

输出:

>go run timedur.go
test took 1026000 ns
2017-09-02 14:21:58.1488675 -0700 PDT m=+0.010003700
2017-09-02 14:21:58.1498935 -0700 PDT m=+0.011029700
test took 0 ns
2017-09-02 14:21:58.1538658 -0700 PDT m=+0.015002000
2017-09-02 14:21:58.1538658 -0700 PDT m=+0.015002000
exit status 1
>

在 Linux 上:

输出:

$ go run timedur.go
test took 113641 ns
2017-09-02 14:52:02.917175333 +0000 UTC m=+0.001041249
2017-09-02 14:52:02.917287569 +0000 UTC m=+0.001153717
test took 23614 ns
2017-09-02 14:52:02.917600301 +0000 UTC m=+0.001466208
2017-09-02 14:52:02.917623585 +0000 UTC m=+0.001489354
test took 22814 ns
2017-09-02 14:52:02.917726364 +0000 UTC m=+0.001592236
2017-09-02 14:52:02.917748805 +0000 UTC m=+0.001614575
test took 21139 ns
2017-09-02 14:52:02.917818409 +0000 UTC m=+0.001684292
2017-09-02 14:52:02.917839184 +0000 UTC m=+0.001704954
test took 21478 ns
2017-09-02 14:52:02.917911899 +0000 UTC m=+0.001777712
2017-09-02 14:52:02.917932944 +0000 UTC m=+0.001798712
test took 31032 ns
<SNIP>

结果具有可比性。它们在同一台机器上运行,Windows 10 和 Ubuntu 16.04 双启动。

关于windows - 性能随机下降,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46012094/

有关windows - 性能随机下降的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  3. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  4. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  5. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  6. Ruby 的数字方法性能 - 2

    我正在使用Ruby解决一些ProjectEuler问题,特别是这里我要讨论的问题25(Fibonacci数列中包含1000位数字的第一项的索引是多少?)。起初,我使用的是Ruby2.2.3,我将问题编码为:number=3a=1b=2whileb.to_s.length但后来我发现2.4.2版本有一个名为digits的方法,这正是我需要的。我转换为代码:whileb.digits.length当我比较这两种方法时,digits慢得多。时间./025/problem025.rb0.13s用户0.02s系统80%cpu0.190总计./025/problem025.rb2.19s用户0.0

  7. ruby - Ruby 性能中的计时器 - 2

    我正在寻找一个用ruby​​演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent

  8. ruby - 如何在 Ruby 中执行 Windows CLI 命令? - 2

    我在目录“C:\DocumentsandSettings\test.exe”中有一个文件,但是当我用单引号编写命令时`C:\DocumentsandSettings\test.exe(我无法在此框中显示),用于在Ruby中执行命令,我无法这样做,我收到的错误是找不到文件或目录。我尝试用“//”和“\”替换“\”,但似乎没有任何效果。我也使用过系统、IO.popen和exec命令,但所有的努力都是徒劳的。exec命令还使程序退出,这是我不想发生的。提前致谢。 最佳答案 反引号环境就像双引号,所以反斜杠用于转义。此外,Ruby会将空格解

  9. ruby-on-rails - 如果条件与 &&,是否有任何性能提升 - 2

    如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:

  10. ruby - 如何在 Ruby 中生成一个非常大的随机整数? - 2

    我想在ruby​​中生成一个64位整数。我知道在Java中你有很多渴望,但我不确定你会如何在Ruby中做到这一点。另外,64位数字中有多少个字符?这是我正在谈论的示例......123456789999。@num=Random.rand(9000)+Random.rand(9000)+Random.rand(9000)但我认为这是非常低效的,必须有一种更简单、更简洁的方法来做到这一点。谢谢! 最佳答案 rand可以将范围作为参数:pa=rand(2**32..2**64-1)#=>11093913376345012184putsa.

随机推荐