代码顺序和性能

Order of the code and performance

我想找出哪个更快:结构与数组。所以我写了一个 GO 代码,其中我将 4 个 int 值(1、2、3 和 4)写入结构的成员,然后写入长度为 4 的数组。我试图找出写入所需的时间。

案例 1:首先,我将值写入结构,然后写入数组。在这里我发现数组比结构更快。

package main

import (
    "fmt"
    "time"
)

type abc struct {
    a, b, c, d int
}

func main() {

    var obj abc

    t1 := time.Now()
    obj.a = 1
    obj.b = 2
    obj.c = 3
    obj.d = 4
    t2 := time.Since(t1)

    fmt.Println("Struct access time: : ", t2)

    a := make([]int, 4)
    t3 := time.Now()
    a[0] = 1
    a[1] = 2
    a[2] = 3
    a[3] = 4
    t4 := time.Since(t3)

    fmt.Println("Array access time: : ", t4)

}

案例2:其次,我将值写入数组,然后写入结构。在这里我发现结构比数组快。

package main

import (
    "fmt"
    "time"
)

type abc struct {
    a, b, c, d int
}

func main() {

    var obj abc

    a := make([]int, 4)
    t3 := time.Now()
    a[0] = 1
    a[1] = 2
    a[2] = 3
    a[3] = 4
    t4 := time.Since(t3)

    fmt.Println("Array access time: : ", t4)

    t1 := time.Now()
    obj.a = 1
    obj.b = 2
    obj.c = 3
    obj.d = 4
    t2 := time.Since(t1)

    fmt.Println("Struct access time: : ", t2)

}

为什么性能取决于我先写什么?我第一个写的那个似乎比较慢。为什么会这样?

运行 任何第一次编写的代码都可能有一些(显着的)开销,例如可能会加载相关代码,许多事情可能会推迟到需要时才进行(例如内部缓冲区)。 运行 再次做同样的事情可能会花费更少的时间,差异甚至可能是 几个数量级

每当你想测量执行时间时,你应该运行多次,测量多次运行s的执行时间,并计算平均时间。出于上述原因,从计算中排除第一个(某些)运行 也是一个好主意。

在 Go 中,最好和最简单的是使用测试文件和基准函数。阅读 testing 的包文档以获取更多详细信息和示例。

您的案例可以这样进行基准测试:

package main

import "testing"

type abc struct {
    a, b, c, d int
}

func BenchmarkSlice(b *testing.B) {
    a := make([]int, 4)
    for i := 0; i < b.N; i++ {
        a[0] = 1
        a[1] = 2
        a[2] = 3
        a[3] = 4
    }
}

func BenchmarkStruct(b *testing.B) {
    a := abc{}
    for i := 0; i < b.N; i++ {
        a.a = 1
        a.b = 2
        a.c = 3
        a.d = 4
    }
}

将其保存到类似 something_test.go 的文件中,运行 使用 go test -bench .。输出:

BenchmarkSlice-4        2000000000           1.24 ns/op
BenchmarkStruct-4       2000000000           0.31 ns/op

您可以看到使用结构大约 4 倍 快。如果您重新排序基准函数,您将获得相似(非常接近)的结果。

另一个答案解释了时间差异,让我们进入结构与切片。

如果编译器可以在编译时确定切片足够大,那么访问切片和结构的元素将生成相同的代码。当然,在现实中,编译器通常不知道切片有多大,并且会根据您使用的是结构还是切片来应用完全不同的优化,因此为了衡量性能,您必须查看整体程序及其行为,而不仅仅是一个特定的操作。