A
A
Alexander Vladimirovich2021-06-22 08:02:00
go
Alexander Vladimirovich, 2021-06-22 08:02:00

Does the built-in copy function use lazy copying?

Greetings!
Does lazy copying (copy on write) work when copying a slice, that is, only the resource descriptor is copied, without the resource itself, and for owners the resource becomes shared and available in read-only mode, but as soon as some does the owner need to modify the shared resource, is the resource copied and then the owner works with his copy, or does the copy occur immediately with memory allocation?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
E
Evgeny Mamonov, 2021-06-22
@polyanin

There is no lazy copying when copying a slice.
Here is the source of the function that copies the slices.
https://golang.org/src/runtime/slice.go#L34
The function comment says:

// makeslicecopy allocates a slice of "tolen" elements of type "et",
// then copies "fromlen" elements of type "et" into that new allocation from "from".

The source code of the function in case the source is not available

// makeslicecopy allocates a slice of "tolen" elements of type "et",
// then copies "fromlen" elements of type "et" into that new allocation from "from".
func makeslicecopy(et *_type, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer {
  var tomem, copymem uintptr
  if uintptr(tolen) > uintptr(fromlen) {
    var overflow bool
    tomem, overflow = math.MulUintptr(et.size, uintptr(tolen))
    if overflow || tomem > maxAlloc || tolen < 0 {
      panicmakeslicelen()
    }
    copymem = et.size * uintptr(fromlen)
  } else {
    // fromlen is a known good length providing and equal or greater than tolen,
    // thereby making tolen a good slice length too as from and to slices have the
    // same element width.
    tomem = et.size * uintptr(tolen)
    copymem = tomem
  }

  var to unsafe.Pointer
  if et.ptrdata == 0 {
    to = mallocgc(tomem, nil, false)
    if copymem < tomem {
      memclrNoHeapPointers(add(to, copymem), tomem-copymem)
    }
  } else {
    // Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory.
    to = mallocgc(tomem, et, true)
    if copymem > 0 && writeBarrier.enabled {
      // Only shade the pointers in old.array since we know the destination slice to
      // only contains nil pointers because it has been cleared during alloc.
      bulkBarrierPreWriteSrcOnly(uintptr(to), uintptr(from), copymem)
    }
  }

  if raceenabled {
    callerpc := getcallerpc()
    pc := funcPC(makeslicecopy)
    racereadrangepc(from, copymem, callerpc, pc)
  }
  if msanenabled {
    msanread(from, copymem)
  }

  memmove(to, from, copymem)

  return to
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question