Rust에서 Box를 사용하여 옵션형, 알려진 길이의 배열 메모리 할당 최적화하기
2024-07-27
배경
Rust는 메모리 안전성을 위해 컴파일 타임에 메모리 할당을 검사합니다. 이는 대부분의 경우 유리하지만, 옵션형(optional) 또는 알려진 길이(known length)의 배열을 다룰 때 불필요한 메모리 할당과 복사가 발생할 수 있습니다.
Box
사용하기
Box
는 Rust에서 스마트 포인터 역할을 하는 자료구조입니다. Box
를 사용하면 메모리 할당을 직접 관리하지 않고도 힙(heap) 메모리에 데이터를 저장할 수 있습니다.
예시
다음 예시는 Box
를 사용하여 옵션형 배열을 메모리 할당하는 방법을 보여줍니다.
// Option<T>
let mut array: Option<Box<[i32]>> = None;
// 값 할당
if some_condition {
array = Some(Box::new([1, 2, 3]));
}
// 값 사용
if let Some(array) = array {
for element in array.iter() {
println!("{}", element);
}
}
이 예시에서 array
는 옵션형 변수이며, Box::new()
를 사용하여 힙 메모리에 배열을 할당합니다. array
에 값이 할당된 경우, iter()
메서드를 사용하여 배열 요소를 반복할 수 있습니다.
장점
- 옵션형 배열의 경우,
Box
를 사용하면 불필요한 메모리 할당과 복사를 줄일 수 있습니다. - 알려진 길이의 배열의 경우,
Box
를 사용하면 컴파일 타임에 배열 크기를 확인할 수 있어 메모리 안전성을 향상시킬 수 있습니다.
단점
Box
를 사용하면 메모리 관리가 더 복잡해질 수 있습니다.Box
는 가비지 컬렉션(garbage collection) 대상이므로, 메모리 누수(memory leak)를 방지하기 위해 주의해야 합니다.
결론
예제 코드
옵션형 배열
// Option<T>
let mut array: Option<Box<[i32]>> = None;
// 값 할당
if some_condition {
array = Some(Box::new([1, 2, 3]));
}
// 값 사용
if let Some(array) = array {
for element in array.iter() {
println!("{}", element);
}
}
알려진 길이의 배열
// [T; n]
let array: Box<[i32]> = Box::new([1, 2, 3]);
// 값 사용
for element in array.iter() {
println!("{}", element);
}
옵션형 배열
알려진 길이의 배열
Box
대체 방법
옵션형 배열
Vec::with_capacity
메서드를 사용하여 배열 용량을 미리 할당할 수 있습니다.MaybeUninit
자료구조를 사용하여 초기화되지 않은 배열을 만들 수 있습니다.
알려진 길이의 배열
[T; n]
형식을 사용하여 알려진 길이의 배열을 직접 선언할 수 있습니다.std::array::from_fn
함수를 사용하여 배열 요소를 직접 생성할 수 있습니다.
옵션형 배열 예시
// Vec::with_capacity
let mut array: Vec<i32> = Vec::with_capacity(3);
// 값 할당
if some_condition {
array.push(1);
array.push(2);
array.push(3);
}
// 값 사용
for element in array.iter() {
println!("{}", element);
}
// MaybeUninit
use std::mem::MaybeUninit;
let mut array: MaybeUninit<[i32; 3]> = MaybeUninit::uninit();
// 값 할당
if some_condition {
unsafe {
let mut array = array.assume_init();
array[0] = 1;
array[1] = 2;
array[2] = 3;
}
}
// 값 사용
if let Some(array) = unsafe { array.assume_init() } {
for element in array.iter() {
println!("{}", element);
}
}
알려진 길이의 배열 예시
// [T; n]
let array: [i32; 3] = [1, 2, 3];
// 값 사용
for element in array.iter() {
println!("{}", element);
}
// std::array::from_fn
use std::array;
let array: [i32; 3] = array::from_fn(|i| i + 1);
// 값 사용
for element in array.iter() {
println!("{}", element);
}
rust serde