Codableなstructデータを保存に使うことって結構ないですか?
最近は PropertyListEncoder なども標準ライブラリに入り、ユーザーデータの保存にも使われているように感じます。
しかしJSONもPropertyListもテキスト形式のデータであり、保存すると容量が大きくなります。なので、最大それらの数万倍軽くなるBoxEncoderを作ってみました。
まず実際どうなるか
Person というデータを作り、そのデータ10万個を保存した時の値です。
このデータだと4万倍小さくなりました。
| Type | File Size |
|---|---|
| Box | 126 B |
| JSON | 5.8 MB |
| Plist | 5.4 MB |
// Codableなデータ
struct Person: Codable {
let name: String
let age: UInt8
let birth: Conutry
struct Conutry: Codable {
let name: String
let id: UInt8
}
}
let alice = Person(name: "Alice", age: 16, birth: .init(name: "UK", id: 12))
/// 100000 データ
let people = Array(repeating: alice, count: 100000)
(ランダム性が大きともっと大きくなります。)
使用方法
pod 経由でインストールできます。
pod 'BoxData'
BoxEncoder と BoxDecoder は JSONEncoder や PropertyListEncoder などと同様に使えるので、すでにこれらを使っていた場合は、名前以外に変更するとことは一切ありません。
do {
// Encoding
let data = try BoxEncoder().encode(people)
// Decoding
let decoded = try BoxDecoder().decode(Array<Person>.self, from: data)
} catch {
print(error)
}
JSON・Plistと異なり、単一のデータも保存できます。
let bool = try encoder.encode(true)
let string = try encoder.encode("Hello Box Format!")
let int = try encoder.encode(1000_0000)
let array = try encoder.encode([12, 13, 14, 15])
なぜ容量が小さいか
- バイトフォーマット
- 構造の保存
-
gzip圧縮
という理由です。
バイトフォーマット
まず、JSON・Plistなどと異なり、データをバイト列として保存します。更に、適切に型 (UInt8・Int16など)を使い分けることで更に容量を軽くできます。
構造の保存
JSON・Plistなどでは配列データなどについても全ての構造を保存しますが、Boxではヘッダに全てのデータ構造を書き込むので繰り返し構造データを書き込むことがありません。
今回のコードは https://github.com/ObuchiYuki/BoxData においてあります。
結構頑張ったので使ってくれると嬉しい