什么更有效,返回指向uint或uint的指针?

nil*_*nus 1 performance pointers go

在Go中,从函数返回的效率更高:返回uint或返回*uint

该函数在cpu密集型库的内部for循环中调用.

icz*_*cza 12

一般来说,只要效率是问题,就应该运行基准测试.

让我们创建非常简单的例子:

func fuint() uint {
    return 0
}

func fpuint() *uint {
    var i uint
    return &i
}
Run Code Online (Sandbox Code Playgroud)

基准代码:

func BenchmarkUint(b *testing.B) {
    for i := 0; i < b.N; i++ {
        fuint()
    }
}

func BenchmarkPuint(b *testing.B) {
    for i := 0; i < b.N; i++ {
        fpuint()
    }
}
Run Code Online (Sandbox Code Playgroud)

需要注意的一件事是:由于我们的函数非常简单,因此代码优化可能会导致结果失效(例如,我们可能会看到相同的结果).

所以我们应该通过禁用编译器优化来测试.所以让我们这样测试一下:

go test -gcflags '-N -l' -bench . -benchmem
Run Code Online (Sandbox Code Playgroud)

测试结果:

BenchmarkUint-4     500000000        3.21 ns/op      0 B/op     0 allocs/op
BenchmarkPuint-4    100000000       22.4 ns/op       8 B/op     1 allocs/op
Run Code Online (Sandbox Code Playgroud)

正如我们可能已经猜到的那样:分配一个uint值并返回指向它的指针更慢并且需要分配(在堆上),而返回一个简单的uint值则不然.

但不要以为情况总是如此.在此测试期间,我们禁用了编译器优化.当您将应用程序编译为生产时,显然不会禁用优化,因此您的实际示例可能没有那么大的差异,或者根本没有差异.测试/测试您的实际代码,看看返回指针实际上是否会产生明显的差异.

作为参考,这是启用编译器优化的结果(默认行为):

go test -bench . -benchmem

BenchmarkUint-4     2000000000         0.35 ns/op        0 B/op      0 allocs/op
BenchmarkPuint-4    2000000000         0.35 ns/op        0 B/op      0 allocs/op
Run Code Online (Sandbox Code Playgroud)

我们看到没有任何区别fuint(),并fpuint()在所有在上面的具体例子.