Re: [golang-dev] Copy-on-write optimization

888 views
Skip to first unread message

Russ Cox

unread,
Aug 24, 2014, 9:24:30 PM8/24/14
to manu.va...@gmail.com, golang-nuts
[+golang-nuts, bcc golang-dev]

golang-nuts is a better list for questions about Go programming.

On Sat, Aug 23, 2014 at 4:17 PM, <manu.va...@gmail.com> wrote:
First at all, is there is way to pass a big struct or array (not slice) while keeping the memory on the stack and preventing the memory to be copied in the heap? 

Example:

  func main() {
      // allocated in stack (good!)
      type BigStruct { a string; data [64]byte }
      var identifier BigStruct

      // passing as value (does it copy the value?)
      // it should not, since the value is inmutable, a COW optimization could be applied
      a := sum(identifier)

Yes, it copies the value.
 
     // passing as pointer (is it copied to the heap? --> bad)
     // also, semantically is confusing, since it looks like that function has side-effects when it doesn't.
     a = sumPtr(&identifier)
}

It is left on the stack if the compiler can prove that sumPtr does not retain the pointer after returning. In this case it can prove that, so the variable is left on the stack, not copied to the heap. You can check this by passing '-gcflags -m' to your go command. After fixing the various compilation errors in your program, I get:

g% go build -gcflags -m x.go
# command-line-arguments
./x.go:21: sum a does not escape
./x.go:29: sumPtr a does not escape
./x.go:18: main &identifier does not escape
g% 

  func sum(a BigStruct) int {
      var sum int
      for i:=0; i < 16; i++ {
          sum += a.data[i]
      }
      return sum
  }


  func sumPtr(a *BigStruct) int {
      var sum int
      for i:=0; i < 16; i++ {
          sum += a.data[i]
      }
      return sum
  }

is there plans to add copy-on-write optimization?

There are no plans today. For the most part, Go does what you tell it. If you want Go to pass a pointer, write the code to pass a pointer.

Note that this "optimization" actually breaks if the call to sum can run longer than the caller does. This would happen in 'go sum(identifier)'.

Russ
Reply all
Reply to author
Forward
0 new messages