Is there a "strings.Clone(string) string" alike function?

2,488 views
Skip to first unread message

T L

unread,
Feb 1, 2017, 4:18:56 AM2/1/17
to golang-nuts
Sometimes, I want to create a new string which will not share the underlying bytes with other strings.
For example, to avoid the substring memory leak problem.

newStr := string([]byte(oldStr)) is simple but will make two memory allocations, and one of them is a waste.

There are two solutions which only make one memory allocation in https://groups.google.com/forum/#!topic/golang-nuts/naMCI9Jt6Qg
(code: https://play.golang.org/p/3rVsMTaHUz).
But in that thread, someone said the two are not safe from being optimized unexpectedly in later compiler versions.

I found the most approached function in the standard lib is strings.Repeat(), but it also makes two memory allocations.

Is there a safe way to do this with only one memory allocation?



Jan Mercl

unread,
Feb 1, 2017, 4:22:51 AM2/1/17
to T L, golang-nuts
On Wed, Feb 1, 2017 at 10:19 AM T L <tapi...@gmail.com> wrote:

> newStr := string([]byte(oldStr)) is simple but will make two memory allocations, and one of them is a waste.

Is the above an assumption or have you verified that? It would not surprise me that nowadays the compiler can infer the []byte slice does not leak.

--

-j

T L

unread,
Feb 1, 2017, 4:33:15 AM2/1/17
to golang-nuts, tapi...@gmail.com

I just remember one of the go authors said there are two allocations in it. I forgot who said it.
 

--

-j

T L

unread,
Feb 1, 2017, 4:59:27 AM2/1/17
to golang-nuts, tapi...@gmail.com


On Wednesday, February 1, 2017 at 5:22:51 PM UTC+8, Jan Mercl wrote:

package main

import (
    "runtime"
    "fmt"
    "strings"
)

func printMemStat() {
    runtime.GC()
    var stat runtime.MemStats
    runtime.ReadMemStats(&stat)
    fmt.Println("TotalAlloc", stat.TotalAlloc)
}

func main() {
    printMemStat() // TotalAlloc 64064
    s := strings.Repeat("x", 1 << 20) // 1M
    printMemStat() // TotalAlloc 2162200
    s2 := string([]byte(s))
    printMemStat() // TotalAlloc 4260336
    runtime.KeepAlive(s2)
}

It is obviously that both strings.Repeat and string([]byte(s)) make two 1M memory allocations.


 

Jan Mercl

unread,
Feb 1, 2017, 5:14:24 AM2/1/17
to T L, golang-nuts

On Wed, Feb 1, 2017 at 10:59 AM T L <tapi...@gmail.com> wrote:

> It is obviously that both strings.Repeat and string([]byte(s)) make two 1M memory allocations.

The observation is correct. However, stack allocating of non-leaking items is capped in size and I guess 1M is out of limits. The specific constant is to be found somewhere in the runtime sources.

--

-j

T L

unread,
Feb 1, 2017, 7:20:50 AM2/1/17
to golang-nuts
Is it a good idea to make the builtin copy function support one parameter?
So that we can use it to deep copy string and interface values.

roger peppe

unread,
Feb 3, 2017, 9:54:59 AM2/3/17
to T L, golang-nuts
This program reports only one allocation per operation, which seems
to indicate that your solution is already the right one:

https://play.golang.org/p/Fx1EMYKRRd
> --
> 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.
> For more options, visit https://groups.google.com/d/optout.

T L

unread,
Feb 7, 2017, 1:34:56 AM2/7/17
to golang-nuts, tapi...@gmail.com


On Friday, February 3, 2017 at 10:54:59 PM UTC+8, rog wrote:
This program reports only one allocation per operation, which seems
to indicate that your solution is already the right one:

https://play.golang.org/p/Fx1EMYKRRd



Yes, but only for small strings with length <= 32

https://play.golang.org/p/TfdahRKVr3

 
Reply all
Reply to author
Forward
0 new messages