13

What is the complexity of Go's builtin append function? What about string concatenation using +?

I'd like to remove an element from a slice by appending two slices excluding that element, ex. http://play.golang.org/p/RIR5fXq-Sf

nums := []int{0, 1, 2, 3, 4, 5, 6, 7}
fmt.Println(append(nums[:4], nums[5:]...))

=> [0 1 2 3 5 6 7]

http://golang.org/pkg/builtin/#append says that if the destination has sufficient capacity, then that slice is resliced. I'm hoping that "reslicing" is a constant time operation. I'm also hoping the same applies to string concatenation using +.

wasmup
  • 14,541
  • 6
  • 42
  • 58
Kaleidoscope
  • 3,609
  • 1
  • 26
  • 21

1 Answers1

26

This all depends on the actual implementation used, but I'm basing this on the standard Go as well as gccgo.

Slices

Reslicing means changing an integer in a struct (a slice is a struct with three fields: length, capacity and pointer to backing memory).

If the slice does not have sufficient capacity, append will need to allocate new memory and copy the old one over. For slices with <1024 elements, it will double the capacity, for slices with >1024 elements it will increase it by factor 1.25.

Strings

Since strings are immutable, each string concatenation with + will create a new string, which means copying the old one. So if you're doing it N times in a loop, you will allocate N strings and copy memory around N times.

Dominik Honnef
  • 17,937
  • 7
  • 41
  • 43
  • Thanks! What about passing a slice of uint8 to the `string` function? Is that `O(1)` or `O(n)`? (standard Go implementation) – Kaleidoscope Jun 27 '13 at 00:05
  • 3
    O(n). Slices are mutable, strings are not → it has to copy the data. – Dominik Honnef Jun 27 '13 at 00:48
  • 12
    In other words, appending an element to a slice is amortized O(1). – newacct Jun 28 '13 at 00:58
  • 2
    Is this documented anywhere official? – Bryan Mar 26 '15 at 16:15
  • 1
    @Bryan As pointed out in this post http://www.reddit.com/r/golang/comments/39w6e2/stackgo_a_slicebased_implementation_of_a_simple/ you can find this behaviour hardcoded here http://golang.org/src/runtime/slice.go#L59 – alediaferia Jun 15 '15 at 21:09
  • Re strings: using the concatenation operator actually has O(n^2) complexity. Perhaps that's what you meant with your example when you mentioned copying data around but I don't think this part was clear enough in your answer. – user1301428 Jan 02 '19 at 19:18
  • I think this should be clearly described as part of the class contract in the slice documentation. For example the Java ArrayList explicitly states that add() is amortized constant time, so all implementations must conform to that or they're in violation of the API. – theferrit32 Sep 10 '19 at 19:07