일단 Array의 기본 지식을 알고 싶다면 Array 를 참고하면 됩니다!

쨋든 Array 검사 **(Inspecting an Array)**를 공부하던 중 도대체 왜 capacity가 있는지 이유를 모르겠어서 찾아보다가 좋은 아티클을 찾게 되어서 그 내용을 공유해보려고 한다.

1. capacity란?

일단 우리에게 익숙한 count는 컬렉션 타입의 요소의 개수를 나타낸다. 그럼 capacity는 무엇인가.

: 새로운 스토리지를 할당 없이, Array 에 얼만큼의 element 를 담을 수 있는지를 나타냅니다. 이게 무슨 소리냐? 코드로 보면서 알아보죱

var ayomiMember = ["희재", "석우", "윤서", "승찬"]
print(ayomiMember.count) // 4
print(ayomiMember.capacity) // 4

ayomiMember.remove(at: 2)
print(ayomiMember.count) // 3
print(ayomiMember.capacity) // 4 -> 요소를 제거를 해도 capacity는 그대로!

즉 무슨 소리냐!

모든 컬렉션 타입은 콘텐츠를 저장하기 위해 특정 양의 메모리를 예약하기 때문에, 특정 element 를 제거한다고해도 이 공간의 크기는 변하지 않는다.

2. 배열의 크기 할당 방식

그럼 궁금증이 생기죠? 만약 요소를 추가한다면 어떤 값이 나올까?

ayomiMember.append("민")
print(ayomiMember.count) // 5
print(ayomiMember.capacity) // 8 -> ???? 갑자기 8

요소를 추가할 때 Array가 예약된 용량을 초과하기 시작하면, 배열의 용량을 늘려야한다. So. Array 는 요소를 메모리에 연속적으로 저장 하기 때문에 더 큰 메모리 영역을 재할당하고 모든 요소를 이전 저장소에서 새 저장소로 복사합니다.

이때 새 스토리지의 크기는 이전 스토리지 크기의 배수입니다.

이러한 지수 성장 (exponential growth) 정책은 요소를 추가하는 것이 일정한 시간에 발생한다는 것을 의미하며, 많은 추가 작업의 성능을 평균화합니다. 재할당을 트리거하는 추가 작업에는 성능적으로 비용이 들지만 어레이가 커질수록  발생하는 빈도는 점점 줄어듭니다.

var arr: [Int] = []
var lastCapacity = arr.capacity
(0..<1200).forEach { element in
    arr.append(element)
    
    if (arr.capacity != lastCapacity) {
        print(arr.capacity)
        lastCapacity = arr.capacity
    }
}

정확히 딱 배수는 아니더라도 배수 비스무리하게 증가하는 것을 볼 수 있다.

/* 결과값
2
4
8
16
32
64
188
380
764
1532
*/

⭐️ 결론 → 컬렉션 타입의 크기 할당 과정은!

  1. 초기에 적당한 크기의 공간을 할당해둔 다음