Thuc notes - Rust - Vector capacity increment
Vector is a common data structure to store list of data with growable size.
Internally, Vector store 3 basic fields:
- a raw pointer pointer to point to first element of the Vector store.
sizeis the number of elements in Vector contains.capacityis the maximum of elements that Vector can add without reallocating.
| |
Same with other languages, Rust use size, capacity and pointer to heap space to support growable size feature.
- If we push an element to Vector that their
sizeis less thancapacity, new element will be follow last element,sizewill be increase as counter and no allocating occurs. - If we push an element to Vector that their
sizeis equal tocapacity, the Vector doesn’t have more space to add. It reallocates elements in bigger capacity before add new element.
┌─────┐
┌────────────┐ │ │
│ Ptr │─────────────────────▶│ │
├────────────┤ ├─────┤
│ Size: 4 │ │ │
├────────────┤ │ │
│Capacity: 5 │ ├─────┤
└────────────┘ │ │
│ │
├─────┤
│ │
│ │
├─────┤
│ │
└ ─ ─ ┘
Deallocate
┌─────┐ ┌────────────┐ ┌ ─ ─ ┐
┌────────────┐ │ │ │ Ptr │───┐ Allocate
│ Ptr │─────────────────────▶│ │ ├────────────┤ │ new space │ │
├────────────┤ ├─────┤ │ Size: 4 │ │ ┌─────┐
│ Size: 5 │ │ │ ├────────────┤ │ │ │ │ │
├────────────┤ │ │ │Capacity: 10│ └──▶│ │
│Capacity: 5 │ ├─────┤ └────────────┘ ├─────┤ │ │
└────────────┘ │ │ │ │
│ │ │ │ │ │
├─────┤ ├─────┤
│ │ │ │ │ │
│ │ │ │
├─────┤ ├─────┤ │ │
│ │ │ │
│ │ │ │ │ │
└─────┘ ├─────┤ ─ ─ ─
│ │
│ │
├─────┤
│ │
│ │
│ │
│ │
│ │
│ │
─ ─ ─
| |
During pushing to a Vector that its size reached to limit of capacity, new space with new capacity is allocated = 2x old capacity = 2x current size.
Minimum of capacity is defined as following table:
| Element’s size | Minimum capacity |
|---|---|
| 1kb | 8 |
| <= 1024kb | 4 |
| > 1024kb | 1 |
| |
The code grow_amortized() is used for both cases while pushing to capacity Vector, and reserve(more_capacity) method.
The reserve() actively expands the capacity of Vector with input argument. But the Vector will decide how much will be grown to avoid re-allocate frequently.
- If we have current
capacityis 10, size is9, we reserve more 5 elements => newcapacity= 2x oldcapacity= 20. - If we have current
capacityis 10, size is9, we reserve more 20 elements => newcapacity= currentsize+ 20 reserved elements = 29.
Rust also provides a method reserve_exact() to force fit to what value they want to reserve, if current capacity is less than current len + additonal
- If we have current
capacityis 10, size is9, we reserve_exact more 5 elements => newcapacity= currentsize+ 9 reserved elements = 14. - If we have current
capacityis 10, size is9, we reserve_exact more 20 elements => newcapacity= currentsize+ 20 reserved elements = 29.
| |