readonly []byte required

122 views
Skip to first unread message

Ally Dale

unread,
Jul 4, 2019, 10:27:58 PM7/4/19
to golang-nuts
[]byte is mutable in Go, but string is readonly, so []byte(string) in Go is actually allocate&memcopy, and this operation is costly.
Sometimes, we need a readonly []byte parameter but we have string only, and we have no choice but allocate&memcopy to make a new []byte variable from string.
Eg: net.Send([]byte("ping")) is costly, but net.Send(readonly []byte("ping")) can be cheaply.

Max

unread,
Jul 5, 2019, 7:54:35 AM7/5/19
to golang-nuts
I think it could be a useful optimization.

There are at least in two different (and much more general) proposals that, if accepted, would include readonly slices as a special case.
The the compiler could recognize that a readonly slice created from a string can reuse string's underlying data:

* proposal: Go 2: read-only types https://github.com/golang/go/issues/22876
  proposes a new 'ro' keyword to mark readonly values

* proposal: Go 2: immutable type qualifier https://github.com/golang/go/issues/27975
  proposes to allow marking with 'const' values (including function/method parameters) and field declarations

Slawomir Pryczek

unread,
Jul 5, 2019, 8:00:29 AM7/5/19
to golang-nuts
Not sure if that's a good idea. Strings are immutable so you can pass string to function by reference, in thread safe manner. So if you pass same string to 2 threads and one of them modify it - you'll really have allocate+copy+modify so you're never touching the original thing so you can't have a race.

Now if go introduced readolny []byte, we'd probably want to change all io functions to use that... and this would create a lot of confusion, because it'd be required to cast []byte to readonly version. And this casted variable wouldn't be readonly nor thread-safe at all, because underlying memory could still be changed using the original slice. So we'd need allocate+memcopy for readonly cast to do a network write.

Or maybe there could be readonly []byte version for each io op. But it'd result only in many unnecessary OS calls.

So what is needed in this case (i guess) is a reusable buffer anyway, and then you can do a copy to a byte buffer without a cast and allocation
tstr := "abc"
t := make([]byte, 10, 10)
copy(t, tstr)

Robert Engels

unread,
Jul 5, 2019, 8:10:50 AM7/5/19
to Slawomir Pryczek, golang-nuts
In the case of high performance IO, where probably most strings are converted, you use a ByteBuffer to avoid many small kernel calls anyway, and these can copy the string data (WriteString) to the buffer directly without an intermediate allocation. 
--
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...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/804e9ecf-4d2e-4ffd-8cca-1a9c91928bb9%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Ugorji Nwoke

unread,
Jul 5, 2019, 8:36:09 AM7/5/19
to golang-nuts
This came up about 5 or so years ago.

Brad proposed it, it was deliberated for a while, and Russ articulated why it was no doable at the time. There may be a chance to resurrect it, but it will be good to see what was written before.

See


Having said that, Russ put this on his list of items to think through for 2017 (along with other items which are making it to Go 2 now). See https://research.swtch.com/go2017

It may be worth it to see what his current thinking on that is.

+rsc @rsc 
Reply all
Reply to author
Forward
0 new messages