Files
docview/tests/STRESS-PDF-VALIDATION.md
2026-09-21 13:41:40 +09:00

73 lines
8.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 大容量 PDF の負荷試験記録
最新のUI修正後の再測定は [ui-finalの記録](results/ui-final/stress/README.md) を参照してください。[completion-finalの記録](results/completion-final/stress/README.md)と以下は、以前の本体による測定履歴です。資料構造と再現手順は共通です。
2026-09-19、Arch Linux x86_64 / kernel 7.2.2-zen1-1-zen / Qt 6.11.2、Xvfb の専用 X11 表示と Qt Quick software rendering で当時のビルドを測定した。画面は 1400×900、アプリ窓は 1100×800、DPR 1。PDFium ワーカーの Landlock/seccomp と資源制限は有効のままである。以下は [stress-final/report.json](results/stress-final/report.json) の結果で、[従来の記録](results/stress/report.json) は旧ビルドの履歴として保持する。
## 入力と再現方法
`generate_stress_pdf.py` は、オリジナルの紙面テクスチャ・ブロック文字・バーコードを持つ **1,280 個の異なる 512 × 512 RGB 画像**を、フィルターなしの各 768 KiB PDF image stream として書く。5,000 ページの全てに画像を描画し、画像を `pageIndex % 1280` で再利用する。全画像が少なくとも一度参照される。サイズを稼ぐだけの未参照データや padding はない。
- PDF サイズ: **1,009,828,104 bytes**(約 963.05 MiB / 0.940 GiB)。
- 実ラスター payload: **1,006,632,960 bytes**(960 MiB)。
- SHA-256: `a8657fdaef99e4e6d3eb650bfc4afe9ded74dee4873c69698fcd73021617dc2e`。
- ページ: 600 × 800 pt。画像矩形: `[44, 180, 556, 692]`。ページ番号・画像番号の本文マーカーと二つの色マーカーを持つ。
- 生成前空き容量: 318,780,846,080 bytes。出力見積りに加え 512 MiB の余裕を要求する。
- ラスター用バッファ: テンプレートと現在の画像の計 1.5 MiB。全文書を RAM に保持せず、逐次書き込みと SHA-256 更新を行う。
通常のビルド後、次で生成・検査・GUI 試験・削除まで実行する。
```sh
python3 tests/test_stress_generator.py
python3 tests/test_stress_runner.py
python3 tests/run_stress_pdf.py --xvfb --binary build/docview --output tests/results/stress-final
```
最初のコマンドは 5 ページ・2 画像のみを使用する軽量試験で、再現性、画像の固有性と参照、xref、空き容量不足、既存ファイル保護を確認する。二番目の新しい runner 回帰は GUI/大容量 PDF を使わず、出力 schema、実 open 数、メモリ圧迫、no-op 除外、close 後解放、起動失敗時の旧集計除去、実行ファイル改変時の失敗を検査する。今回 3 試験が通過し、[軽量試験ログ](results/stress-final/runner-tests.log)を保存した。三番目は `build/stress/` 内の一時ディレクトリに大容量 PDF を作り、成功・失敗のどちらでも回収する。利用者の設定・履歴には一時 XDG ディレクトリを使用する。
## 測定結果
アプリ自身が focused window にキーイベントを送り、`frameSwapped` で初回応答を記録し、全可視タイルがそろった後のフレームを最終品質とする。これは提示キュー時刻であり、物理ディスプレイの scanout を確認する値ではない。`--benchmark-runs 3 --benchmark-close-cycles 2 --benchmark-operations 100 --benchmark-scroll-steps 0` を明示し、実際に 3 open、操作前の単純 open/close 2 回、操作後の close 1 回を行った。3 回の open は毎回新しいワーカー、100 操作はページ移動 80 回と拡大/fit-width 20 回から成る。キャッシュ分類は位置が変わったページ移動だけを含み、no-op は 0 件だった。継続スクロールはこの有限試験では実施していない。生成直後の OS ファイルキャッシュは残している。
| 項目 | 件数 | P50 | P95 | 最大 |
|---|---:|---:|---:|---:|
| open → 可視本文の提示 | 3 | 96.71 ms | 97.70 ms | 97.70 ms |
| キー → 初回応答フレーム | 100 | 6.61 ms | 8.14 ms | 11.69 ms |
| キー → 全可視タイルの最終品質 | 100 | 12.01 ms | 24.12 ms | 40.35 ms |
| キャッシュ済みページ移動 | 68 | 11.86 ms | 15.87 ms | 18.87 ms |
| 新規可視タイルを要するページ移動 | 12 | 18.67 ms | 40.35 ms | 40.35 ms |
| メモリ・要求 | 実測 |
|---|---:|
| アプリのピーク RSS | 410,173,440 bytes |
| アプリと子プロセス合計のピーク RSS | 752,041,984 bytes |
| 各 open 完了時のプロセス合計 RSS | 379,916,288 / 384,729,088 / 386,531,328 bytes |
| タイルキャッシュのピーク charged bytes | 268,423,168 bytes |
| タイルキャッシュ上限 | 268,435,456 bytes(256 MiB) |
| 可視/先読みタイル要求 | 205 / 281 |
| 描画待ち/queued render/active render の最大 | 4 / 3 / 1 |
| 破棄済み queued requests | 28 |
| 最大メモリ圧迫段階 | 0(通常解像度条件を維持) |
表はアプリ内の 100 ms 間隔の標本である。独立した 50 ms 間隔の `/proc` 監視はアプリ 413,401,088 bytes、子を含む合計 755,404,800 bytes を観測した。標本時刻が異なるため値は一致しない。合計 RSS は共有ページをプロセスごとに数えるため PSS ではなく、Xvfb は含めない。有限間隔のサンプルなので瞬間的な全ピークを保証しない。
全 3 close で Empty とタイル cache 0 を確認した。単純 open/close 2 回後の合計 RSS は 132,026,368 / 134,127,616 bytes、操作後の最終 close は 376,856,576 bytes だった。プロセスの allocator 等に残る RSS を含み、2 回の均一条件だけで長期リークを判定する試験ではない。
## 終端ページとクリーンアップ
独立した `pdfinfo` が 5,000 ページを認識し、`pdftotext` が 1・1,280・5,000 ページの予定マーカーを抽出した。1,280 個の画像 digest は全て異なる。先頭・中間・末尾の image stream を再読込してハッシュ一致と xref を検査した。アプリが試験後に算出した全文書 SHA-256 も生成時の値と一致した。
別プロセスで `--page 5000 --smoke-output ...` を実行し、Ready / pdf、可視 PDF 寸法、viewportReady、PNG/runtime 保存の成功を満たして終了した。[保存画面](results/stress-final/last-page/screen.png)を `view_image` で目視し、`DOCVIEW STRESS PAGE 05000 OF 05000 IMAGE 1159`、ラスター画像、ステータス `5000 / 5000` を確認した。自動 OCR 検証ではない。メモリ圧迫 0 の集計対象は benchmark プロセスであり、smoke の runtime 出力には圧迫段階の時系列は含まれない。
証跡は [report.json](results/stress-final/report.json)、[benchmark.json](results/stress-final/benchmark.json)、[source-manifest.json](results/stress-final/source-manifest.json) に保存した。原本 SHA は benchmark 終了時と smoke 後の独立読込の両方で生成時と一致した。大容量 PDF は削除済みで、`sourceRemoved=true` と `build/stress/` に PDF が残っていないことを確認した。全工程 14.291 s、benchmark プロセス 7.468 s、smoke プロセス 4.893 s。
次の主 3 実行ファイルは試験前後で SHA-256 が一致した。report の `executableSha256`/`executableSha256After`/`executablesUnchanged` に保存する。
| 実行ファイル | SHA-256 |
|---|---|
| docview | `9612bccb5ce864174c1898843a90fa75c2598ac47e8abb3b9822d35c78d766c5` |
| docview-pdf-worker | `b199d491f411dc32c60c5f19bd07c24d0cc85fb5e43ca1f08f085615574dc461` |
| docview-archive-worker | `312dc77c52f9b40441f339381ae5209cac4d11d8131c9f1f239aa025713f0966` |
この試験は大容量・大量ページの取扱い、遠方移動、キャッシュ上限の観測である。3 回の open は 30 回の性能受入条件を置き換えず、仮想表示器は設計書の基準機ではない。1,280 画像を再利用する合成文書は、5,000 ページ全てが異なる高解像度スキャン、圧縮画像の複雑な復号、実書籍の互換性、長時間のリーク検証を網羅しない。