본문 바로가기

카테고리 없음

[Swift] 구조체 메모리 최적화

struct Machine {
    let id: Int
    let isRunning: Bool
    let needsRepair: Bool
}

 

위와 같은 구조체가 있을 때, 이 구조체에 대한 바이트 크기를 구하려면 먼저 각 저장 프로퍼티의 크기를 알아야 한다.

print(MemoryLayout<Int>.size) // 8 byte
print(MemoryLayout<Bool>.size) // 1 byte

 

따라서 위 구조체에 대한 바이트 크기를 출력하면

struct Machine {
    let id: Int // 8 byte
    let isRunning: Bool // 1 byte
    let needsRepair: Bool // 1 byte
}

print(MemoryLayout<Machine>.size) // 10 byte
print(MemoryLayout<Machine>.stride) // 16 byte

 

size 는 10 byte, stride 는 16 byte 가 나온다.

 

이 때, 배열에 이 구조체의 인스턴스를 넣고 차지하는 바이트 크기를 출력해보면

 

var machines: [Machine] = [
    Machine(id: 0, isRunning: false, needsRepair: false),
    Machine(id: 1, isRunning: false, needsRepair: false),
    Machine(id: 2, isRunning: false, needsRepair: false),
]

machines.withUnsafeBytes { bufferPointer in
    print(bufferPointer.count) // 48
}

 

stride 크기 * element 갯수 인 48 byte 를 확인할 수 있다.

 

여기서 Machine 구조체의 저장 프로퍼티 순서를 약간 바꾸면 어떻게 될까?

struct Machine {
    let isRunning: Bool // 1 byte
    let id: Int // 8 byte
    let needsRepair: Bool // 1 byte
}

print(MemoryLayout<Machine>.size) // 17 byte
print(MemoryLayout<Machine>.stride) // 24 byte

 

id 프로퍼티가 정의된 위치를 바꿨을 뿐인데 size 와 stride 를 출력해보니 전보다 늘어났다.

이에 따라 똑같이 배열의 크기를 출력해봐도 

var machines: [Machine] = [
    Machine(isRunning: false, id: 0, needsRepair: false),
    Machine(isRunning: false, id: 1, needsRepair: false),
    Machine(isRunning: false, id: 2, needsRepair: false),
]

machines.withUnsafeBytes { bufferPointer in
    print(bufferPointer.count) // 72
}

 

48 byte 에서 72 byte 로 늘어난 것을 확인할 수 있다. 이는 빌드 최적화 세팅을 바꿔도 영향을 받지 않는다.