Skip to content

strings: Builder copy check causes a dynamic memory allocation #23382

@achille-roussel

Description

@achille-roussel

What version of Go are you using (go version)?

go version go1.9.1 darwin/amd64

Does this issue reproduce with the latest release?

N/A

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/achilleroussel/dev"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/0p/tfjq063j4hdcjnm0_9qb4bww0000gn/T/go-build417403397=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

What did you do?

Regarding 3058d38

The change causes the strings.Builder value to always escape to the heap if any of its methods is called, which means there will be 2 dynamic memory allocations to build a string (one for the byte slice and one for the builder).

The intent of this type was to save on memory allocations caused by the use of bytes.Buffer, now it seems like it's just as inefficient.

Here's a quick benchmark to highlight what I'm talking about:

package main

import "testing"

type A struct{ self *A }

func (a *A) F() { a.self = a }

func BenchmarkStruct(b *testing.B) {
    for i := 0; i != b.N; i++ {
        a := A{}
        a.F()
    }
}
$ go test -v -run _ -bench . -benchmem
goos: darwin
goarch: amd64
BenchmarkStruct-4   	50000000	        24.6 ns/op	       8 B/op	       1 allocs/op

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.release-blocker

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions