Golang slice expansion mechanism

Slice expanse capacity

The data structure of slice is easy to use and manage data collections. It can be understood as a dynamic array, and slice is also built around the concept of dynamic array. Since it is a dynamic array, how does slice expand?

  • If the capacity of the slice is less than 1024 elements, then the cap of the slice is doubled and multiplied by 2 when expanding the capacity; once the number of elements exceeds 1024 elements, the growth factor becomes 1.25, that is, each time the original capacity is increased by a quarter
  • If the capacity of the original array has not been touched after expansion, then the position pointed by the pointer in the slice is still the original array. If the capacity of the original array is exceeded after expansion, then Go will open up a new piece of memory and store the The value is copied over, this situation will not affect the original array

The dynamic growth of the slice is realized by the built-in function append, which can quickly and efficiently grow the slice, and can also reduce the size of a slice by slicing the slice again. A slice is a very small object that abstracts the underlying array and provides related operation methods. He has three fields, namely: pointer to the underlying array, length, capacity.

Specific analysis (combined with source code)

Source location: runtime/slice.go growslice

Note: We represent the actual capacity after expansion as newCap, the required target capacity obtained according to the incoming parameters of append() is represented as cap, the original slice is represented as oldSlice, the expanded slice is represented as newSlice, and the element type in the slice represents for et

  1. slice combines golang built-in method append for dynamic expansion, the specific implementation method is >
    func growslice(et *_type, old slice, cap int) slice;

     传入的参数分别为切片中元素的类型,原来的切片,目标切片的容量
    
  2. golang first judges the target capacity. If the cap is twice the original cap (oldSlice), then newCap is directly equal to cap.

  3. For cap less than or equal to twice the original cap (oldSlice), there are two processing methods, ①, when cap (oldSlice) is less than 1024, newCap will be directly equal to twice the cap (oldSlice) ②, when cap (oldSlice) ) is greater than or equal to 1024, it will loop to increase a quarter of newCap until newCap is greater than or equal to cap , and then stop the loop.

Source code embodiment: Slice preliminary expansion selection
4. Golang does not completely regard the newCap calculated above as the final newCap, but needs to make minor adjustments according to its memory allocation strategy. Generally speaking, it is the memory alignment of golang. Let’s take a look at it below one example.

insert image description hereAccording to the above memory allocation, the capacity of arr1 above should be 9 (the target capacity (cap) is 9, which is twice the capacity of oldslice, so newCap should be directly equal to cap=9), but the running result is 10, It depends on the subsequent memory alignment strategy
insert image description here

  • Golang subdivides this strategy into four strategies combined with the element type et in the slice, but the core idea is to align the allocated memory, which is specifically implemented as the roundupSize method

Source code embodiment:
insert image description here

  • golang first judges whether the size of size=newCap*unsafe.size(et) calculated from the above is a small object, and if it is a small object, it will fill in the memory according to the memory allocation of golang. That is to say, for example, if The size calculated above is 60, so according to the memory filling, it will become 64 for allocation.

Golang small object memory allocation table:
insert image description hereSo for the program just now, the newCap calculated by the first step is 9, size=9*slice element size 8 is 72, according to the memory completion, this object should be allocated at least 80bytes space, so the final result newCap=80/size of the slice element 8=10

Guess you like

Origin blog.csdn.net/qq_52696089/article/details/126171790