golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
122.69k stars 17.49k forks source link

proposal: time: add a non allocating way to marshal Time in the binary format #66972

Open sylr opened 4 months ago

sylr commented 4 months ago

Proposal Details

Hi,

I wrote a zero allocation marshaller with mus-go for a struct that contains a lot of time.Time. Unfortunately, it still allocates because of time.MarshalBinary().

I played a bit with the standard library and implemented another version of time.MarshalBinary() ([]byte, error) that does not allocate (see: https://github.com/sylr/go/commit/384f060cc8da29846bc381beadbd6881010ebb3f).

Here are the results:

goos: darwin
goarch: arm64
pkg: utils/nats
cpu: Apple M2
                   │    old.txt    │              new5.txt               │
                   │    sec/op     │   sec/op     vs base                │
Encoders/mus/raw-8   15.259µ ± 91%   6.268µ ± 0%  -58.92% (p=0.000 n=10)

                   │   old.txt    │             new5.txt             │
                   │    bytes     │    bytes      vs base            │
Encoders/mus/raw-8   4.001Ki ± 0%   4.001Ki ± 0%  ~ (p=1.000 n=10) ¹
¹ all samples are equal

                   │   old.txt    │               new5.txt                │
                   │     B/op     │     B/op      vs base                 │
Encoders/mus/raw-8   1.562Ki ± 0%   0.000Ki ± 0%  -100.00% (p=0.000 n=10)

                   │  old.txt   │              new5.txt              │
                   │ allocs/op  │ allocs/op  vs base                 │
Encoders/mus/raw-8   100.0 ± 0%    0.0 ± 0%  -100.00% (p=0.000 n=10)

I'm wondering if we could merge something like this, possible implementations I could think of are:

icholy commented 4 months ago

https://github.com/golang/go/issues/62384

ianlancetaylor commented 4 months ago

I think this would be addressed more generally by #62384.