跳到內容

效能:記憶體碎片分析器

Performance 模組刻意維持精簡。它提供一個僅供觀測的工具——MemoryFragmentationAnalyzer——可在引擎工作中已標記的各個區間量測尖峰與保留記憶體。這個介面也包含該工具產生的不可變快照。它不會強制套用預算、不會節流,也不會改變引擎行為。

範圍與穩定性。 本模組的實際介面只有兩個類別 (MemoryFragmentationAnalyzerMemoryFragmentationSnapshot)。它並非 用來對逐項操作強制套用預算的工具。performance_budget 值在每個模組的 front-matter 中是一種文件慣例,而非本模組會強制套用的設定。這個介面是 experimental:它是於 @since 3.2.0 引入的診斷工具。其快照結構可能會演進。

Terminal window
composer require nextpdf/core:^3

對 PDF 引擎而言,資源使用率是首要品質考量。支撐這項考量的最小可觀測量,是區分尖峰記憶體(區間內的最高水位)與保留記憶體(區間結束後仍佔用的部分)。本模組精準量測這一點,不多做其他事。

MemoryFragmentationAnalyzer 僅供觀測——它不會變更 writer 或文件狀態。reset() 會執行一次 GC 循環並重設 PHP 的尖峰計數器,讓後續量測都歸屬於重設後的區間。mark(string $label) 會在帶有標籤的點擷取一份 MemoryFragmentationSnapshotsnapshots() 會回傳已擷取的資料序列。peakDelta()retainedDelta() 會回報整個執行過程中尖峰與保留記憶體的變化量。

MemoryFragmentationSnapshot 是一個 final readonly 值物件:代表一個帶有標籤的量測點,包含 transientBytes()(尖峰減去保留——曾被使用後又釋放的記憶體)、retentionRatio()(保留除以尖峰),以及供匯出使用的 toArray()。暫態位元組數值偏高但保留比率偏低,代表存在頻繁的記憶體周轉,而緩衝區重用策略有機會消除這種周轉。這兩個類別皆為 @since 3.2.0

類別主要成員職責
MemoryFragmentationAnalyzerreset(), mark(string $label), snapshots(), peakDelta(), retainedDelta()僅供觀測的記憶體分析器(@since 3.2.0
MemoryFragmentationSnapshottransientBytes(), retentionRatio(), toArray()不可變的帶標籤量測值(@since 3.2.0

執行 composer docs:generate-api-php -- --module=Performance 即可取得完整的 PHPDoc 表格。

在熱路徑前後加上標記,再讀取各項變化量。

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Performance\MemoryFragmentationAnalyzer;
$analyzer = new MemoryFragmentationAnalyzer();
$analyzer->reset();
$analyzer->mark('before-write');
// ... engine work under observation ...
$analyzer->mark('after-write');
printf("Peak delta: %d B, retained delta: %d B\n", $analyzer->peakDelta(), $analyzer->retainedDelta());

包覆一次算繪流程,並將碎片快照送往指標接收端,把高暫態位元組且低保留比率的情況視為記憶體周轉訊號。

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Performance\MemoryFragmentationAnalyzer;
use Psr\Log\LoggerInterface;
final readonly class RenderMemoryProbe
{
public function __construct(private LoggerInterface $logger) {}
/** @param callable():void $render The render closure to observe. */
public function observe(callable $render): void
{
$analyzer = new MemoryFragmentationAnalyzer();
$analyzer->reset();
$analyzer->mark('start');
$render();
$analyzer->mark('end');
foreach ($analyzer->snapshots() as $snapshot) {
$this->logger->info('mem-frag', $snapshot->toArray());
}
}
}
  • reset() 會呼叫 gc_collect_cycles()memory_reset_peak_usage()。它會對 PHP 的尖峰計數器造成行程層級的全域影響。請勿在同一個請求中,與另一個同樣會讀取尖峰計數器的元件交錯使用。
  • 量測結果歸屬於自上一次 reset() 以來的區間。若 mark() 之前沒有先呼叫 reset(),量測就會從行程啟動算起,這通常並非你想要的結果。
  • 這是一項診斷工具,並非控制機制。它絕不會節流或中止工作;請勿據此建立回壓機制。
  • 其可重現性類型為 structural:位元組數值取決於執行階段、配置器與 GC 狀態。即使是相同的邏輯工作,兩次執行的數值也會不同。

分析器本身的額外負擔,是在 reset() 時執行一次 GC 循環,以及每次 mark() 進行一次 hrtime() / memory_get_* 讀取——相較於它所觀測的工作量微不足道。每次 mark() 會配置一份小型快照。此 front-matter 中的 performance_budget 是整份文件通用的參考數值;本模組並不會強制套用它。

記憶體數值屬於診斷資料。它們並不包含文件內容,但細緻的記憶體剖析可能會洩漏與輸入大小及結構相關的資訊。請將快照匯出視為內部遙測資料,並在對外分享前,先依專案的日誌清理義務加以處理。本模組不執行任何 I/O,也不嵌入任何外部資料。請參閱 /modules/core/security/ 中的引擎威脅模型。

本模組並未主張任何具 PDF 規範性的規格聲明。它是一項記憶體診斷工具,並未實作任何需要引用條款的標準化協定。其架構理據參考了 ISO/IEC/IEEE 42010 架構描述框架中的資源使用率品質觀點,這屬於架構實務上的對齊,而非 PDF 引用。引擎一致性是由 /modules/core/conformance/ 中所述的 oracle 與 golden 測試套件驗證的。