Вопрос:

Последствия panic () со структурой против указателя?

go

68 просмотра

1 ответ

2230 Репутация автора

Каковы последствия, если таковые имеются, вызова panic(x)с большой структурой по сравнению с вызовом panic(&x)с указателем на эту структуру вместо этого?

Копируется ли то, interface{}что вы передаете панике, каждый раз, когда стек раскручивает уровень, или происходит какая-то другая магия?

РЕДАКТИРОВАТЬ: Пример, где это может быть важно, находится внутри http.Serve, где он оправится от любой паники и подаст подходящее сообщение. Если я паникую из-за очень большой структуры, это может оказать некоторое влияние на производительность, поскольку кадры стека раскручиваются и вызывают чрезмерную нагрузку на мой веб-сервер.

Автор: Dave Источник Размещён: 08.11.2017 10:58

Ответы (1)


1 плюс

109097 Репутация автора

Решение

Это зависит от того, сколько раз выполнено panics, от значения или аргумента указателя, от размера 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: Интерфейсы

Автор: peterSO Размещён: 09.11.2017 12:14
Вопросы из категории :
32x32