Realm 파일 크기 줄이기 - Swift SDK
개요
영역 파일의 크기는 항상 그 안에 저장된 객체의 전체 크기보다 큽니다. 이 아키텍처를 사용하면 영역의 뛰어난 성능, 동시성, 안전성의 이점을 누릴 수 있습니다.
Realm은 파일 내에서 추적된 미사용 공간에 새 데이터를 작성합니다. 경우에 따라 사용하지 않는 공간이 영역 파일의 상당 부분을 차지할 수 있습니다. 영역의 기본 동작은 영역 파일이 너무 커지는 것을 막기 위해 자동으로 압축하는 것입니다. 사용 사례에 자동 압축이 충분하지 않거나 자동 압축 기능이 없는 SDK 버전을 사용하는 경우 수동 압축 전략을 사용할 수 있습니다.
Realm 파일 크기
일반적으로 영역 파일은 비슷한 SQLite 데이터베이스보다 디스크 공간을 덜 차지합니다. 예기치 않은 파일 증가는 Atlas App Services가 오래된 데이터를 참조하는 것과 관련이 있을 수 있습니다. 이러한 요소는 파일 크기에 영향을 줄 수 있습니다:
트랜잭션 고정
스레딩
대기열 발송
압축을 통해 파일 크기를 줄이는 것을 고려할 때는 다음과 같은 몇 가지 사항을 염두에 두어야 합니다.
압축은 리소스 집약적인 작업일 수 있습니다.
압축하면 UI 스레드가 차단될 수 있습니다.
이러한 요인들로 인해 Realm을 열 때마다 압축하는 대신 영역영역 압축할 때 을(를) 고려하는 것이 좋습니다. 이는 애플리케이션의 플랫폼과 사용 패턴에 따라 달라집니다. 압축 시기를 결정할 때 iOS 파일 크기 제한을 고려하세요.
트랜잭션 고정 방지
Realm은 읽기 트랜잭션 수명을 영역 인스턴스의 메모리 수명에 연결합니다. 오래된 Realm 트랜잭션을 '고정'하지 않도록 합니다. 자동 새로 고침 영역을 사용하고 명시적 자동 릴리스 풀에서 백그라운드 스레드의 Realm API 사용을 래핑하세요.
스레딩
Realm은 런 루프 반복이 시작될 때 액세스하는 데이터 버전을 업데이트합니다. 이렇게 하면 데이터를 일관성 있게 볼 수 있지만 파일 크기에 영향을 미칩니다.
다음과 같은 시나리오를 상상해 봅니다.
스레드 A: 영역에서 일부 데이터를 읽은 다음 장기 실행 작업에서 스레드를 차단합니다.
스레드 B: 다른 스레드에 데이터를 씁니다.
스레드 A: 읽기 스레드의 버전이 업데이트되지 않습니다. Realm은 데이터의 중간 버전을 보관해야 하므로 쓸 때마다 파일 크기가 커집니다.
이 문제를 방지하려면 영역에서 invalidate()를 호출합니다. 이것은 지금까지 읽은 객체가 더 이상 필요하지 않다는 것을 영역에 알립니다. 이렇게 하면 영역에서 해당 객체의 중간 버전을 추적하지 않아도 됩니다. 다음에 액세스할 때 영역은 최신 버전의 객체를 갖게 됩니다.
다음 두 가지 방법을 사용해 Realm을 압축할 수도 있습니다.
구성에서 shouldCompactOnLaunch를 설정합니다.
대기열 발송
Grand Central Dispatch 을(를) 사용하여 Realm 액세스하는 경우 비슷한 파일 증가를 볼 수 있습니다. 디스패치 대기열의 자동 릴리스 풀은 코드 실행 시 즉시 비워지지 않을 수 있습니다. Realm 은 디스패치 풀이 영역 객체 의 할당을 해제할 때까지 중간 버전의 데이터를 재사용할 수 없습니다. 디스패치 대기열에서 영역 에 액세스할 때는 명시적 자동 릴리스 풀을 사용하세요.
자동 압축
버전 10.35.0의 새로운 기능
SDK는 파일 내 데이터를 지속적으로 재할당하고 사용하지 않는 파일 공간을 제거하여 백그라운드에서 자동으로 Realm 파일을 압축합니다. 자동 압축은 대부분의 애플리케이션에서 Realm 파일 크기를 최소화하는 데 충분합니다.
파일에서 사용되지 않은 공간이 파일의 사용자 데이터 크기의 두 배 이상일 때 자동 압축이 시작됩니다. 자동 압축은 파일에 액세스하지 않을 때만 수행됩니다.
수동 압축
수동 압축은 보다 엄격한 파일 크기 관리가 필요한 애플리케이션이나 자동 압축을 지원하지 않는 이전 버전의 SDK를 사용하는 애플리케이션에 사용할 수 있습니다.
Realm 수동 압축은 다음과 같은 방식으로 작동합니다.
영역 파일의 전체 내용 읽기
다른 위치의 새 파일에 콘텐츠 쓰기
원본 파일 바꾸기
파일에 많은 데이터가 포함되어 있는 경우 이 작업은 많은 비용이 소요될 수 있습니다.
영역의 구성 객체에서 shouldCompactOnLaunch() (Swift) 또는 shouldCompactOnLaunch (Objective-C)를 사용하여 영역을 컴팩트화할 수 있습니다. 이 메서드를 실행할 조건을 다음과 같이 지정합니다.
디스크에 있는 파일의 크기
파일에 포함된 여유 공간의 양
메서드에서 실행할 조건에 대한 자세한 내용은 수동 압축 사용 팁을 참조하세요.
중요
압축이 발생하지 않을 수 있습니다.
구성 설정에 관계없이 영역에 액세스하는 동안에는 압축을 수행할 수 없습니다.
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; config.shouldCompactOnLaunch = ^BOOL(NSUInteger totalBytes, NSUInteger usedBytes) { // totalBytes refers to the size of the file on disk in bytes (data + free space) // usedBytes refers to the number of bytes used by data in the file // Compact if the file is over 100MB in size and less than 50% 'used' NSUInteger oneHundredMB = 100 * 1024 * 1024; return (totalBytes > oneHundredMB) && ((double)usedBytes / totalBytes) < 0.5; }; NSError *error = nil; // Realm is compacted on the first open if the configuration block conditions were met. RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:&error]; if (error) { // handle error compacting or opening Realm }
let config = Realm.Configuration(shouldCompactOnLaunch: { totalBytes, usedBytes in // totalBytes refers to the size of the file on disk in bytes (data + free space) // usedBytes refers to the number of bytes used by data in the file // Compact if the file is over 100MB in size and less than 50% 'used' let oneHundredMB = 100 * 1024 * 1024 return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5 }) do { // Realm is compacted on the first open if the configuration block conditions were met. let realm = try Realm(configuration: config) } catch { // handle error compacting or opening Realm }
비동기적으로 Realm 압축
Swift async/await 구문을 사용하여 비동기적으로 영역을 열면 백그라운드에서 영역을 압축할 수 있습니다.
func testAsyncCompact() async { let config = Realm.Configuration(shouldCompactOnLaunch: { totalBytes, usedBytes in // totalBytes refers to the size of the file on disk in bytes (data + free space) // usedBytes refers to the number of bytes used by data in the file // Compact if the file is over 100MB in size and less than 50% 'used' let oneHundredMB = 100 * 1024 * 1024 return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5 }) do { // Realm is compacted asynchronously on the first open if the // configuration block conditions were met. let realm = try await Realm(configuration: config) } catch { // handle error compacting or opening Realm } }
Realm Swift SDK 버전 10.15.0 및 10.16.0부터 많은 Realm API가 Swift async/await 구문을 지원합니다. 프로젝트는 다음 요구 사항을 충족해야 합니다.
Swift SDK 버전 | Swift 버전 요구 사항 | 지원되는 OS |
---|---|---|
10.25.0 | Swift 5.6 | iOS 13.x |
10.15.0 또는 10.16.0 | Swift 5.5 | iOS 15.x |
앱이 async/await
컨텍스트에서 Realm에 액세스하는 경우 코드를 @MainActor
(으)로 표시하여 스레드 관련 충돌을 방지합니다.
압축 복사본 만들기
Realm .writeCopy( 영역: encryptionKey:) 메서드 를 사용하여 Realm의 압축된(그리고 선택적으로 암호화됨 ) 복사본을 다른 파일 위치 에 저장할 수 있습니다. 메서드. 대상 파일 이 이미 존재할 수 없습니다.
중요
쓰기 트랜잭션(write transaction) 내에서 이 메서드를 호출하지 않도록 합니다. 쓰기 트랜잭션(write transaction) 내에서 호출하면 이 메서드는 절대 최신 데이터를 복사합니다. 여기에는 이 메서드를 호출하기 전에 트랜잭션에서 수행한 커밋되지 않은 모든 변경 사항이 포함됩니다.
수동 압축 사용 팁
영역 압축은 UI 스레드를 차단할 수 있는 비용이 많이 드는 작업일 수 있습니다. 영역을 열 때마다 애플리케이션이 압축되어서는 안 됩니다. 대신 압축을 최적화하여 파일 크기가 너무 커지지 않도록 애플리케이션이 충분히 자주 압축을 수행하도록 하세요. 애플리케이션이 리소스가 제한된 환경에서 실행되는 경우 특정 파일 크기에 도달하거나 파일 크기가 성능에 부정적인 영향을 미칠 때 압축할 수 있습니다.
다음 권장 사항은 애플리케이션에 맞게 수동 압축을 최적화하는 데 도움이 될 수 있습니다.
최대 파일 크기를 평균 영역 상태 크기의 배수로 설정합니다. 평균 영역 상태 크기가 10 MB인 경우 예상 사용량과 기기 제약 조건에 따라 최대 파일 크기를 20 MB 또는 40 MB로 설정할 수 있습니다.
우선, 영역 파일 크기의 50% 이상이 더 이상 사용되지 않는 경우 영역을 압축합니다. 현재 사용 중인 바이트를 전체 파일 크기로 나누어 현재 사용 중인 공간의 비율을 확인합니다. 그런 다음 그 비율이 50% 미만인지 확인합니다. 즉, 영역 파일 크기의 50% 이상이 사용되지 않는 공간이라는 의미이므로 압축하는 것이 좋습니다. 실험을 통해 애플리케이션에 가장 적합한 비율을 찾을 수 있습니다.
이러한 계산은 shouldCompactOnLaunch
콜백에서 다음과 같이 표시될 수 있습니다.
// Set a maxFileSize equal to 20MB in bytes let maxFileSize = 20 * 1024 * 1024 // Check for the realm file size to be greater than the max file size, // and the amount of bytes currently used to be less than 50% of the // total realm file size return (realmFileSizeInBytes > maxFileSize) && (Double(usedBytes) / Double(realmFileSizeInBytes)) < 0.5
여러 조건을 실험하여 애플리케이션에서 영역 파일을 압축하는 빈도에 대한 적절한 균형을 찾아보세요.
iOS 파일 크기 제한 고려
대용량 영역 파일은 앱의 성능과 안정성에 영향을 줄 수 있습니다. 단일 영역 파일은 iOS에서 애플리케이션이 매핑할 수 있는 메모리 양보다 클 수 없습니다. 이 제한은 기기와 해당 시점의 메모리 공간이 얼마나 조각화되어 있는지에 따라 달라집니다.
더 많은 데이터를 저장해야 하는 경우 여러 영역 파일에 걸쳐 매핑하세요.
요약
Realm의 아키텍처는 스레딩과 관련된 이점을 제공하지만 파일 크기가 커질 수 있습니다.
자동 압축은 파일에 액세스하지 않을 때 파일 크기 증가를 관리합니다.
자동 압축이 애플리케이션 요구 사항을 충족하지 못할 경우
shouldCompactOnLaunch()
와(과) 같은 수동 압축 전략을 사용할 수 있습니다.다른 프로세스가 영역에 액세스 중인 경우 압축을 수행할 수 없습니다.
비동기/대기 구문을 사용할 때 백그라운드에서 영역을 압축할 수 있습니다.