.madはデータセットではなく、定義です。レポートが表示するすべての内容は派生データであり、再生成可能であり、意図的にアーカイブの外に置かれています。ドキュメントの傍らには次の3種類のファイルが生成されます:
| ファイル | 出力元 | 格納内容 |
|---|---|---|
<hash>.maddb |
MADDataTableFast |
レポートの行データ |
<hash>.mdcache |
MADDataTable (:354) |
そのデータ上の仮想テーブル群を記述するplist |
<hash>{ih,lh}{w, h}.madac |
MADArrayCaching(MADReportFormatter :179, :183から供給) |
レンダリング済みページコンテンツ——レイアウト識別子とページサイズをキーとするSQLiteデータベース。ihはレポートインデックスキャッシュ、lhはレポートレイアウトキャッシュ |
これら3つはすべて、ドキュメントごとにdataTableIdHashで命名された1つのディレクトリ内にまとめて配置されます。MADocument.m:286-300は、MADURLFactory newURLCacheFilesDirectoryForFilename:(MADURLFactory.m:47-49)が提供するディレクトリ(ドキュメント外のユーザーごと・デバイスごとの場所)からテーブルを構築します:
MADDataTableFast *datatable = [[MADDataTableFast alloc] initWithId:dataTableIdHash];
...
NSURL *cacheUrl = [self newUrlCacheForFilename:cacheName];
self.urlDataTableCache = cacheUrl;
[datatable loadFromCacheWithUrl:cacheUrl error:&error];
実際のLibrary/Caches/配下のキャッシュディレクトリでの実測値は以下の通りです:
| 種類 | ファイル数 | 合計サイズ |
|---|---|---|
<hash>.maddb |
1 | 816 KB |
<hash>.mdcache |
1 | 1.7 KB |
<hash>{ih,lh}{...}.madac |
6 | 約15 MB |
.madacファイルはフォーマッタのページキャッシュです。ihおよびlhキーはMADReportFormatter.m:179および:183で生成され、<layoutIdentifier>ih<CGSize>および<layoutIdentifier>lh<CGSize>の形をとります({612, 792}はポイント単位のUS Letterサイズ)。つまり、キャッシュはレイアウト識別子とページジオメトリをキーとしており、これが§5.3で述べる2つの問題を引き起こす原因となっています。
80 KB未満のドキュメントに対し、レンダーキャッシュはドキュメントの約200倍に達します。大半を占めると予想されがちな行データは、ディレクトリ全体の6%未満にすぎません。
意図的にこのサイズになっている理由。 このサイズは設計上の帰結であり、最適化不足による偶発的なものではありません。開発者自身の説明(2026-10-01)による2つの理由は以下の通りです:
キャッシュを圧縮すること自体は可能ですが、現時点で優先すべき変更ではありません。
.madは小さく自己完結している:データセットではなく定義であるため、出荷されている両サンプルとも80 KB未満です。.madは一見そう見えるような「データが詰まった圧縮SQLiteファイル」ではありません。定義が格納された圧縮SQLiteファイルです。ディレクトリ名と格納処理は実装されていますが、仕様としては未規定の箇所があります。別プラットフォームの実装者が推測せざるを得ない3つのギャップは以下の通りです:
レンダーキャッシュのキーがコンテンツではなくファイル名になっている(2026-10-01確認)。
MADReportFormatter -layoutIdentifier(MADReportFormatter.m:186)は_overrideIdentifier ? _overrideIdentifier.hash : _filename.hashを返します。つまりキーはドキュメントのファイル名とページサイズの組み合わせであり、読み込みパスではコンテンツの検証を一切行いません。MADArrayCaching -initializeDatabase(MADArrayCaching.m:141)は、acテーブルが存在しさえすれば既存のSQLiteファイルをそのまま再利用し、キーや読み込み処理のどこにもバージョン、タイムスタンプ、コンテンツハッシュを含みません。同じファイル名のままドキュメントを編集しても.madacファイルは無効化されず、ファイルが削除されるか別のページサイズでレンダリングされるまで古いページが返され続けます。
2026-10-01の実測でもこの挙動と一致。 15:22にLondonドキュメントに対してヘッドレスの更新とエクスポートを実行した後、キャッシュディレクトリ内は以下の状態でした:
| ファイル | サイズ | 更新時刻 (mtime) |
|---|---|---|
<hash>.maddb |
835,584 | 15:22 |
<hash>.mdcache |
1,644 | 15:22 |
<layoutId>ih{612, 792}.madac |
81,920 | 15:22 |
<layoutId>lh{612, 792}.madac |
737,280 | 15:22 |
<layoutId>ih{0, 0}.madac |
1,867,776 | 10:52 |
<layoutId>lh{0, 0}.madac |
4,333,568 | 10:52 |
更新処理は必要なファイル——PDFのページジオメトリである{612, 792}(US Letter)のエントリ——のみを書き直し、残りはそのまま放置します。{0, 0}のエントリには手が付けられず、この2ファイルだけでディレクトリ全体(15 MB)のうち6.0 MBを占めています。{0, 0}は実際のジオメトリが確定する前のページサイズであるため、これら2ファイルはほぼ間違いなく計測パスの産物であり、ファイル名をキーとする方式のもとでは削除しない限り決して無効化されません。
.maddbが存在するケースがあり、データが充填される前にディレクトリが作成されることが分かります。そのような空ディレクトリに意味があるのかどうかは規定されていません。.mdcacheのplistスキーマ。 現在は判明しています——これは結果テーブルのシリアライズされたスキーマであり、MADDataTableFast -copyPlistで書き込まれ、-loadWithPlist:で読み込まれます。トップレベルキーは、name、columnKeys(c<hash> IDの順序付き配列)、columns(c<hash>をキーとする辞書で、各要素はMADDataColumnのplist:caption、fieldName、identifier、type、nativeType、dataLength、dataPercision、isPrimaryKey、isNotNull、isAutoIncrement、defaultValue)、rowCounter、sortDescriptors、および高速テーブルのbulkInsertLoopです。defaultValueには番兵値~MTNull~(MADDataColumnNullSentinel、MADDataColumn.m:23)が使われます。なお、フォーマット上の永続的な癖(quirk)が2点あります。1つ目はdataPercisionというスペルミスがフォーマットに組み込まれていること、2つ目は~MTNull~番兵値がdocs/project/BUGS.md Track 1.5に記載されている"<null>" / "(null)"系とは別の第3のNULLマーカーであることです。このページは英語原文の日本語翻訳です。内容に相違がある場合は、英語原文が優先されます。