Keith made me aware of the fact that my benchmark is using the 
binary.BigEndian interface instead of "unrolling" the interface to use the 
specific type at runtime.  

cpu: Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
BenchmarkUnsafe-8       1000000000               5.991 ns/op           0 
B/op          0 allocs/op
BenchmarkEnc-8          1000000000               6.327 ns/op           0 
B/op          0 allocs/op

This now gets within 6% of the unsafe method.
On Saturday, March 4, 2023 at 3:53:42 PM UTC+1 TheDiveO wrote:

> Keith, thank you very much for your feedback, it is highly appreciated!
>
> With this in mind, it's time for lies, more lies, and statistics, 
> benchmarking the three different implementations below:
>
> func (r *Reader) Uint32() uint32 {
> if r.err != nil {
> return 0
>
> }
> var s struct {
> _ [0]uint32
> b [4]byte
> }
> _, r.err = r.buff.Read(s.b[:])
> if r.err != nil {
> return 0
> }
> return *(*uint32)(unsafe.Pointer(&s.b[0]))
> }
>
> func (r *Reader) Uint32X() uint32 {
> if r.err != nil {
> return 0
> }
> var v uint32
> _, r.err = r.buff.Read((*[4]byte)(unsafe.Pointer(&v))[:])
> if r.err != nil {
> return 0
> }
> return v
> }
>
> func (r *Reader) Uint32N() uint32 {
> if r.err != nil {
> return 0
>
> }
> b := make([]byte, 4)
> _, r.err = r.buff.Read(b)
> if r.err != nil {
> return 0
> }
> return hostnative.Uint32(b)
> }
>
> The benchmarking results using "go test -bench=. -benchtime=60s -benchmem 
> .":
>
> cpu: Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
> BenchmarkReadUint32
> BenchmarkReadUint32-8           1000000000               5.974 ns/op       
>     0 B/op          0 allocs/op
> BenchmarkReadUint32X
> BenchmarkReadUint32X-8          1000000000               5.977 ns/op       
>     0 B/op          0 allocs/op
> BenchmarkReadUint32N
> BenchmarkReadUint32N-8          1000000000              20.81 ns/op       
>      4 B/op          1 allocs/op
>
> The two "unsafe" contenders are absolutely neck-to-neck, so in terms of 
> better readability and maintainability your proposed variant wins for me. 
> And as I was somehow suspecting, encoding/binary takes almost 4 times as 
> much as the first two implementations, and throwing a needless heap 
> allocation into the bargain. 
>
> On Saturday, March 4, 2023 at 1:20:01 AM UTC+1 Keith Randall wrote:
>
>> If you're using unsafe anyway, I'd go the other direction, casting from 
>> the larger alignment to the smaller one. That avoids any alignment concerns.
>>
>> var x uint32
>> b := (*[4]byte)(unsafe.Pointer(&x))[:]
>> r.buff.Read(b)
>> return x
>>
>> I would encourage you to use encoding/binary though. It all works out 
>> just as well without unsafe, with a bit of trickiness around making sure 
>> that calls can be resolved and inlined.
>>
>> b := make([]byte, 4)
>> buf.Read(b)
>> if little { // some global variable (or constant) you set
>>    return binary.LittleEndian.Uint32(b)
>> }
>> return binary.BigEndian.Uint32(b)
>> On Friday, March 3, 2023 at 12:30:37 PM UTC-8 TheDiveO wrote:
>>
>>> In dealing with Linux netlink messages I need to decode and encode 
>>> uint16, uint32, and uint64 numbers that are in an arbitrary aligned byte 
>>> buffer in an arbitrary position. In any case, these numbers are in native 
>>> endianess, so I would like to avoid having to go through encoding/binary.
>>>
>>> buff := bytes.NewBuffer(/* some data */)
>>>
>>> // ...
>>>
>>> func foo() uint32 {
>>>     var s struct {
>>>         _ [0]uint32
>>>         b [4]byte
>>>     }
>>>     r.buff.Read(s.b[:])
>>>     return *(*uint32)(unsafe.Pointer(&s.b[0]))
>>> }
>>>
>>> Will the go compiler (1.19+) allocate on the stack with the correct 
>>> alignment for its element b, so that the unsafe.Pointer operation correctly 
>>> works on different CPU architectures?
>>>
>>> Or is this inefficient anyway in a subtle way that my attempt to avoid 
>>> non-stack allocations is moot anyway?
>>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/3e632724-a13d-42bc-a3ef-9c3bf2d88a26n%40googlegroups.com.

Reply via email to