panic()与struct vs指针的含义?

时间:2017-11-08 22:58:33

标签: go

使用大型结构调用panic(x)与使用指向该结构的指针调用panic(&x)有什么影响(如果有的话)?

每次堆叠展开一个级别时,你传递给恐慌的interface{}是否会被复制,或者是否还有其他魔法?

编辑:这可能很重要的一个例子是http.Serve内部,它将从任何恐慌中恢复并提供合适的信息。如果我对一个非常大的结构感到恐慌,这可能会对堆栈帧展开并对我的网络服务器造成过度负载产生一些性能影响。

1 个答案:

答案 0 :(得分:1)

取决于panic执行的次数,值或指针参数,struct的大小,依此类推。在Go中,参数按值传递。接口值表示为双字对,给出指向存储在接口中的类型的信息的指针和指向相关数据副本的指针。

使用Go测试包基准测试工具。例如,

package main

import "testing"

var sink int

func panic(interface{}) {}

func BenchmarkPanicVal1K(b *testing.B) {
    var large struct{ big [1024]byte }
    b.ReportAllocs()
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        panic(large)
    }
}

func BenchmarkPanicPtr1K(b *testing.B) {
    var large struct{ big [1024]byte }
    b.ReportAllocs()
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        panic(&large)
    }
}

func BenchmarkPanicVal4K(b *testing.B) {
    var large struct{ big [4096]byte }
    b.ReportAllocs()
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        panic(large)
    }
}

func BenchmarkPanicPtr4K(b *testing.B) {
    var large struct{ big [4096]byte }
    b.ReportAllocs()
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        panic(&large)
    }
}

func BenchmarkIfaceVal1K(b *testing.B) {
    var iface interface{}
    var large struct{ big [1024]byte }
    b.ReportAllocs()
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        iface = large
    }
    _ = iface
}

func BenchmarkIfacePtr1K(b *testing.B) {
    var iface interface{}
    var large struct{ big [1024]byte }
    b.ReportAllocs()
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        iface = &large
    }
    _ = iface
}
func BenchmarkIfaceVal4K(b *testing.B) {
    var iface interface{}
    var large struct{ big [4096]byte }
    b.ReportAllocs()
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        iface = large
    }
    _ = iface
}

func BenchmarkIfacePtr4K(b *testing.B) {
    var iface interface{}
    var large struct{ big [4096]byte }
    b.ReportAllocs()
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        iface = &large
    }
    _ = iface
}

输出:

$ gotest panic_test.go -bench=.

BenchmarkPanicVal1K-4      20000000      70.3 ns/op        0 B/op    0 allocs/op
BenchmarkPanicPtr1K-4    2000000000       0.36 ns/op       0 B/op    0 allocs/op
BenchmarkPanicVal4K-4       1000000    1483 ns/op       4096 B/op    1 allocs/op
BenchmarkPanicPtr4K-4    2000000000       0.36 ns/op       0 B/op    0 allocs/op


BenchmarkIfaceVal1K-4       5000000     378 ns/op       1024 B/op    1 allocs/op
BenchmarkIfacePtr1K-4    2000000000       0.36 ns/op       0 B/op    0 allocs/op
BenchmarkIfaceVal4K-4       1000000    1469 ns/op       4096 B/op    1 allocs/op
BenchmarkIfacePtr4K-4    2000000000       0.36 ns/op       0 B/op    0 allocs/op

参考文献:

Go Data Structures: Interfaces