Salta ai contenuti

Prestazioni: analizzatore della frammentazione della memoria

Il modulo Performance è volutamente essenziale. Espone un unico strumento di sola osservazione — MemoryFragmentationAnalyzer — che misura la memoria di picco e quella trattenuta nelle finestre contrassegnate dell’esecuzione del motore. La superficie include anche lo snapshot immutabile prodotto dallo strumento. Non impone budget, non applica throttling né modifica il comportamento del motore.

Ambito e stabilità. La superficie reale di questo modulo è costituita da due classi (MemoryFragmentationAnalyzer, MemoryFragmentationSnapshot). Non è uno strumento per imporre budget per singola operazione. Il valore performance_budget presente nel front-matter di ogni modulo è una convenzione documentale, non qualcosa che questo modulo impone. La superficie è experimental: è uno strumento diagnostico introdotto in @since 3.2.0. La forma del suo snapshot può evolvere.

Terminal window
composer require nextpdf/core:^3

L’utilizzo delle risorse è una caratteristica qualitativa fondamentale per un motore PDF. L’osservabile minimo utile a descriverla è la distinzione tra la memoria di picco (il valore massimo raggiunto durante una finestra) e la memoria trattenuta (ciò che resta in uso dopo la finestra). Questo modulo misura esattamente questa distinzione e nulla di più.

MemoryFragmentationAnalyzer è di sola osservazione: non modifica lo stato del writer né del documento. reset() esegue un ciclo di GC e azzera il contatore di picco di PHP, così che le misurazioni successive siano attribuibili alla finestra aperta dall’azzeramento. mark(string $label) cattura uno MemoryFragmentationSnapshot in un punto contrassegnato. snapshots() restituisce la serie acquisita. peakDelta() e retainedDelta() riportano la variazione di picco e quella trattenuta nell’arco dell’esecuzione.

MemoryFragmentationSnapshot è un value object final readonly: rappresenta un punto contrassegnato con transientBytes() (picco meno trattenuta — memoria usata e poi rilasciata), retentionRatio() (trattenuta rispetto al picco) e toArray() per l’esportazione. Un elevato numero di byte transitori associato a un basso rapporto di ritenzione indica un ricambio che una strategia di riutilizzo dei buffer potrebbe eliminare. Entrambe le classi sono @since 3.2.0.

ClasseMembri principaliRuolo
MemoryFragmentationAnalyzerreset(), mark(string $label), snapshots(), peakDelta(), retainedDelta()Analizzatore di memoria di sola osservazione (@since 3.2.0)
MemoryFragmentationSnapshottransientBytes(), retentionRatio(), toArray()Misurazione contrassegnata immutabile (@since 3.2.0)

Eseguire composer docs:generate-api-php -- --module=Performance per consultare la tabella PHPDoc completa.

Delimitare un percorso critico e leggere i delta risultanti.

<?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());

Avvolgere un rendering ed emettere gli snapshot di frammentazione verso un sink di metriche, considerando un basso rapporto di ritenzione associato a un elevato numero di byte transitori come segnale di ricambio.

<?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() chiama gc_collect_cycles() e memory_reset_peak_usage(). Ha un effetto globale sul processo rispetto al contatore di picco di PHP. Non alternarne l’uso con quello di un altro componente che, nella stessa richiesta, legge a sua volta il contatore di picco.
  • Le misurazioni sono attribuibili alla finestra a partire dall’ultimo reset(). Un mark() senza un reset() precedente misura a partire dall’avvio del processo, e di norma non è il comportamento desiderato.
  • Si tratta di uno strumento diagnostico, non di un meccanismo di controllo. Non applica mai throttling né interrompe il lavoro; non basare su di esso meccanismi di back-pressure.
  • Il profilo di riproducibilità è structural: i valori in byte dipendono dal runtime, dall’allocatore e dallo stato del GC. Due esecuzioni differiscono numericamente anche a parità di lavoro logico.

L’overhead dell’analizzatore consiste in un ciclo di GC su reset() e in una lettura di hrtime() / memory_get_* per ogni mark() — trascurabile rispetto al lavoro osservato. Alloca un piccolo snapshot per ogni mark(). Il performance_budget presente in questo front-matter è il valore di riferimento valido per l’intera documentazione; questo modulo non lo impone.

I valori di memoria sono dati diagnostici. Non contengono il contenuto del documento, ma un profilo di memoria a grana fine può far trapelare informazioni su dimensione e forma dell’input. Trattare le esportazioni degli snapshot come telemetria interna e rispettare l’obbligo di sanificazione dei log previsto dal progetto prima di condividerle all’esterno. Il modulo non esegue alcun I/O e non incorpora dati esterni. Vedere il modello di minaccia del motore in /modules/core/security/.

Questo modulo non formula alcuna affermazione normativa relativa alla specifica PDF. È uno strumento diagnostico della memoria e non implementa alcun protocollo standardizzato le cui clausole debbano essere citate. La sua motivazione architetturale fa riferimento alla vista qualitativa sull’utilizzo delle risorse del framework di descrizione dell’architettura ISO/IEC/IEEE 42010: si tratta di un allineamento alle pratiche architetturali, non di una citazione PDF. La conformità del motore è validata dalle suite oracle e golden descritte in /modules/core/conformance/.