Комментарии 10
Как-то однобоко:
Тест производится на небольшой структуре. Очевидно, что после определенного размера структуры ситуация изменится. После какого?
Производительность - это не только скорость, но и потрабление памяти/аллокации
Вот и выросло очередное поколение, заново открывающее для себя числа, которые обязан знать каждый.
Да, понятно, что бывают пограничные случаи, когда сходу неясно что выгоднее — передача по значению или по ссылке. Но если вы будете помнить, что один проход по ссылке, которой не посчастливилось попасть ни в один из кешей эквивалентен пересылке 400-500 байт данных, то вы поймёте, что ссылки имеют смысл сильно реже, чам многим кажется.
Ссылка не открывается, вот альтернатива https://gist.github.com/jboner/2841832
В данном случае проблема не в этих числах, а в том, что в куче по-одному создается миллион объектов, которые никак не используются и тут-же уничтожаются, что нагружает GC.
В реальном коде объект создается и какое-то время живет и используется, в этом случае если нам надо работать с оным объектом из разных методов - выгоднее передавать его по ссылке. Однако если это кратковременный объект, чистое ДТО исключительно для передачи каких-то данных из одной функции в другую, то тут может быть действительно выгоднее эти данные передавать через стек, а не через кучу управляемую GC - здесь и выгода, что объект создается и уничтожается сам, без затрат на GC, и дает больше простора всяким оптимизациям во время сборки.
И вот в статье взяли этот один единственный кейс, тестанули (причем даже это сделали неправильно: возвращаемый объект никак не используется, так что есть шанс, что оптимизатор более агрессивно соптимизировал код для случая возврата по-значению), ничего не пояснили и оставили читателя додумывать что ему захочется.
В моих задачах еще бы пришлось решать вопрос обратного копирования. Даже подумать страшно, как это решать, интересно что бы сказал автор
В первом тесте бенчится не передача структуры (в функцию) по значению или указателю, а возврат структуры из функции или указателя на неё. Разумеется, в первом случае (возврат структуры) можно (иногда) обойтись без аллокации (положить структуру в стек), а во втором (возврат указателя) без аллокации уже не обойтись.
В то время как передавать структуру в функцию (последний тест, уже без страшных графиков) быстрее всего по указателю, что вполне очевидно.
func BenchmarkMemoryHeap2(b *testing.B) {
f, err := os.Create("heap.out")
if err != nil {
panic(err)
}
defer f.Close()
err = trace.Start(f)
if err != nil {
panic(err)
}
for i := 0; i < b.N; i++ {
s := byPointer()
if s.a != 1 {
panic("a!=1")
}
}
trace.Stop()
b.StopTimer()
}
BenchmarkMemoryStack-4 193849980 6.160 ns/op
BenchmarkMemoryHeap-4 18460486 62.46 ns/op
BenchmarkMemoryHeap2-4 195428566 6.141 ns/op
Собственно, уже было
Говоря про типы по значению и по указателю в golang, я бы обязательно говорил, что эти понятия размыты донельзя, поскольку на типе по значению можно вызывать методы по указателю https://play.golang.org/p/IW2bLAfz1l8
Эта "фича" и ещё больше ослабила систему типов, к сожалению.
Go: стоит ли использовать указатели вместо копий структуры?