Sorun giderme: bellek ve başarım
Kapsam
“Kapsam” başlıklı bölümBu girdiler, yük altında karşılaştığınız iki başarısızlık ailesini kapsar: bir işleme sırasında PHP’nin belleğinin tükenmesi ve bir süreç sıcak ya da doygun olduğunda bir uçurumdan düşen verim. Her girdi bir belirti, en olası neden ve gerçek NextPDF yüzeyi veya standart PHP-FPM denetimlerini kullanan bir düzeltme adlandırır. Altta yatan akış işleme modeli ve bir çalışan eğitimi için Akış işleme ve bellek sayfasını okuyun; bu sayfa ona olay tarafı eşlikçisidir.
Önce ölçün. Bir işleme öncesinde ve sonrasında memory_get_peak_usage(true)
örnekleyin ve yinelemeler arasında memory_reset_peak_usage() çağırın; motorun
karşılaştırma ölçütünün işleme başına maliyeti yalıttığı şekilde. Bir temel olmadan
ayar yapmak, uçurumu kaldırmak yerine taşır.
Girdi: üretim sırasında “Allowed memory size exhausted”
“Girdi: üretim sırasında “Allowed memory size exhausted”” başlıklı bölüm- Belirti. Bir işleme, genellikle büyük veya görüntü ağırlıklı bir belgede,
PHP çalışma zamanından gelen ölümcül bir
Allowed memory size of <n> bytes exhaustedile yarıda kalır. - Olası neden. Varsayılan yazma yolu, önce belgenin tamamını oluşturur, sonra
serileştirir, dolayısıyla tepe bellek toplam çıktı boyutunu izler. Büyük bir
belge, büyük gömülü görüntüler ya da büyük bir gömülü yazı tipi yüzeyi, isteği
memory_limit’in ötesine itebilir. - Çözüm.
- Görüntü önbelleğini sınırlandırın.
NextPDF\Core\Config,imageCacheBytessunar (varsayılan52428800, yani 50 MB). Onu örnek wither’ı$config->withImageCacheBytes($bytes)(imzawithImageCacheBytes(int $bytes): self) ile düşürün, böylece birçok görüntü gömen bir derleme, takas etmek yerine bilinen bir tavanda hızlıca başarısız olur. Bu, bellek içi görüntü önbelleğini sınırlar; görüntülerin kendilerini yeniden örneklemez veya yeniden kodlamaz. - Gömmeden önce girdileri küçültün. Core, görüntüleri ölçek küçültmez ya da yeniden kodlamaz. Aşırı boyutlu raster sanatı gömmeden önce yeniden boyutlandırın ve yeniden kodlayın ve gerçekten kullandığınız yazı tiplerini gömün, böylece alt küme oluşturmanın saklayacağı küçük bir glif kümesi olur (bkz. PDF dosya boyutunu küçültün).
- Sıkıştırmayı açık tutun. Taze bir
Config’incompressdeğeritrueolarak ayarlıdır. Onu normal derlemeler için açık bırakın;withCompress(false)bir boyut en iyileştirmesi değildir (genellikle çıktıyı artırır). İşlem hattını ayıklamak veya profillemek için ona başvurun — belleği azaltmak yerine CPU/bellek ödünleşimini (sıkıştırma adımını atlayarak) kaydırır. memory_limit’i bilinçli olarak, çalışan başına yükseltin. Bu, bir NextPDF anahtarı değil, standart bir PHP ayarıdır. Onu havuz yapılandırmasında ya da CLI/kuyruk süreci içinini_set('memory_limit', '256M')ile ayarlayın ve bir tahmine değil, profillenmiş bir tepeye göre boyutlandırın.
- Görüntü önbelleğini sınırlandırın.
- İlgili. Akış işleme ve bellek.
Girdi: çok büyük belgelerde bellek sayfa sayısıyla büyür
“Girdi: çok büyük belgelerde bellek sayfa sayısıyla büyür” başlıklı bölüm- Belirti. Çok binlerce sayfalı bir belge, her sayfa küçük olsa bile belleği tüketir ve tepe, kabaca sayfa sayısıyla orantılı olarak yükselir.
- Olası neden. Arabelleğe alan yazıcı, serileştirilen belgenin tamamını yığında tutar. Çok büyük belgeler için baskın maliyet budur.
- Çözüm.
- Akışlı yazma yolunu tercih edin.
Akış işleme ve bellek sayfasında
tarif edilen belgelenmiş akışlı yazma yolunu kullanın: her sayfayı oluşturulduğu
anda serileştirir ve arabelleği serbest bırakır, bu da sayfa-arabelleği/çıktı
büyümesini azaltır; küçük nesne başına meta veri (konumlar, sayfa ağacı) yine de
sayfa/nesne sayısıyla ölçeklenebilir. Dahili sınıfları kopyalamak yerine
belgelenmiş giriş noktasını izleyin — altta yatan akış motoru
experimentalkatmandadır ve sembolleri kararlı genel yüzey değildir. - Yerel
writeHtml()ayrıştırıcısı için, girdi tarafı belleğinin hem yuvalama-derinliği hem de öğe-sayısı korumalarıyla sınırlı olduğunu unutmayın: ADR-001, yuvalamayıMAX_NESTING_DEPTH = 100ile sınırlar veMAX_ELEMENT_COUNT = 50000üzerindeki belgeleri reddeder. Öğe sınırına ulaşan bir belgeye, belleği sessizce tüketmek yerine bu açıkça söylenir. Bu ADR-001 sınırları yalnızca yerel ayrıştırıcıyı yönetir; isteğe bağlı Chrome köprüsü (writeHtmlChrome()) süreç dışında işler ve bu sınırlar değil, kendi ayrı bellek/girdi sınırlarına sahiptir.
- Akışlı yazma yolunu tercih edin.
Akış işleme ve bellek sayfasında
tarif edilen belgelenmiş akışlı yazma yolunu kullanın: her sayfayı oluşturulduğu
anda serileştirir ve arabelleği serbest bırakır, bu da sayfa-arabelleği/çıktı
büyümesini azaltır; küçük nesne başına meta veri (konumlar, sayfa ağacı) yine de
sayfa/nesne sayısıyla ölçeklenebilir. Dahili sınıfları kopyalamak yerine
belgelenmiş giriş noktasını izleyin — altta yatan akış motoru
- İlgili. Akış işleme ve bellek.
Girdi: uzun ömürlü bir çalışan birçok işten sonra belleği tüketir
“Girdi: uzun ömürlü bir çalışan birçok işten sonra belleği tüketir” başlıklı bölüm- Belirti. Tek işlemeler başarılı olur, ancak birçok PDF’i art arda işleyen bir kuyruk çalışanı, dakikalar veya saatler sonra belleği tüketir.
- Olası neden. Uzun ömürlü bir PHP süreci, işler boyunca tahsisleri biriktirir. Tek bir istekte görünmez olan yavaş bir büyüme, binlercesi boyunca birikir.
- Çözüm.
- Kayıt defterlerini paylaşın, belgeleri yeniden oluşturun.
FontRegistryveImageRegistry’yi başlatmada bir kez oluşturun ve onları birDocumentFactory’ye geçirin; iş başına$factory->create($config)ile taze birDocumentoluşturun. Yazı tipi ve görüntü ayrıştırma o zaman iş başına bir kez değil, süreç için bir kez gerçekleşir ve iş başına belge ağacı, kapsamdan çıktığında toplanır.examples/14-worker-factory.php’yi izleyin. - Paylaşılan görüntü önbelleğini
new ImageRegistry(maxCacheBytes: ...)ile sınırlandırın, böylece işler boyunca sınırsızca büyüyemez. - Çalışanı geri dönüştürün — bir motor garantisi değil, süreç denetimi.
PHP-FPM’de, her alt sürecin sabit bir istek sayısından sonra yeniden doğması
için
pm.max_requestsayarlayın. Laravel kuyruklarındaqueue:work --max-jobs/--max-time/--memorykullanın; Symfony Messenger’damessenger:consume --limit/--time-limit/--memory-limitkullanın.
- Kayıt defterlerini paylaşın, belgeleri yeniden oluşturun.
- İlgili. Akış işleme ve bellek.
Girdi: soğuk veya yetersiz ısıtılmış bir süreçte verim uçurumu
“Girdi: soğuk veya yetersiz ısıtılmış bir süreçte verim uçurumu” başlıklı bölüm- Belirti. Taze bir süreçteki ilk işlemeler yavaştır ya da her istek, sıcak isteklerin ödememesi gereken bir ayrıştırma maliyeti öder.
- Olası neden. İki soğuk başlatma maliyeti üst üste biner. Opcache olmadan PHP,
her istekte her dosyayı yeniden derler ve ısıtılmamış bir
FontRegistry, her yazı tipi yüzeyini ilk kullanıldığında ayrıştırır. - Çözüm.
- Opcache’i etkinleştirin (ve yardımcı olduğu yerde JIT’i).
opcache.enable=1ve cömert biropcache.memory_consumptionayarlayın; üretimde önbelleğin istek başına yeniden denetlenmemesi içinopcache.validate_timestamps=0ayarlayın. O ayar, her sürümde PHP-FPM’i yeniden başlatan veya yeniden yükleyen (ya da opcache’i başka şekilde sıfırlayan, ör.opcache_reset()/cachetool) bir dağıtım sürecini gerektirir — aksi takdirde opcache eski bayt kodunu sunmaya devam eder ve bir dağıtımdan sonra eski kod çalışır. Bunlar standart PHP ini ayarlarıdır, NextPDF anahtarları değil. - Yazı tipi kayıt defterini başlatmada ısıtın ve kilitleyin. Bir
FontRegistryörneğinde,$fontRegistry->warmup($fontFiles)yüzeyleri başlatma sırasında bir kez ayrıştırır ve$fontRegistry->lock()kayıt defterini dondurarak istek zamanı kodunun paylaşılan durumu mutasyona uğratamamasını sağlar;$fontRegistry->isLocked()durumu bildirir. Gerçekten uzun ömürlü bir çalışanda veya uygulama sunucusunda — aynı PHP sürecini birçok istek boyunca canlı tutan bir kuyruk tüketicisi ya da bir RoadRunner/Swoole/Octane çalışanı — ısıtılmış, kilitlenmiş bir kayıt defteri, ayrıştırılmış yüzeylerini nesne durumunda tutar ve istek başına yazı tipi ayrıştırmayı bir kerelik bir süreç-başlatma maliyetine çevirir. Standart PHP-FPM istek modeli altında, o ısıtılmış nesne durumu istekler arasında hayatta kalmaz: opcache, ısıtılmış userland nesne durumunu değil, derlenmiş sınıfları ve bayt kodunu önbelleğe alır, dolayısıyla ısıtılmış birFontRegistry, bir alt sürecin içinde istekler arasında sıcak tutulmaz, istek başına yeniden oluşturulur (her istek alt sürecin önyüklemesinden yeniden çalıştırılır). Yalın PHP-FPM’de, opcache esas olarak bayt kodu yeniden derleme maliyetini amortize eder; yazı tipi ayrıştırmanın ortadan kaldırılmadığını, istek başına ödendiğini kabul edin. İstekler arası amortizasyon — her yüzeyi sürecin ömrü boyunca bir kez ayrıştırma — yalnızca aynı PHP sürecini birçok istek boyunca canlı tutan bir RoadRunner/Swoole/Octane çalışanı ya da bir kuyruk tüketicisi gibi gerçekten uzun ömürlü bir süreçte geçerlidir. - Aynı şablonu istek başına yeniden ayrıştırmayın. Yazı tiplerini ve yeniden
kullanılabilir kaynakları başlatmada bir kez paylaşılan kayıt defterleri
aracılığıyla çözümleyin; istekte yalnızca iş başına
Documentoluşturulmalıdır.
- Opcache’i etkinleştirin (ve yardımcı olduğu yerde JIT’i).
- İlgili. Akış işleme ve bellek.
Girdi: sunucu eşzamanlılık altında doygunlaşır ve gecikme sıçrar
“Girdi: sunucu eşzamanlılık altında doygunlaşır ve gecikme sıçrar” başlıklı bölüm- Belirti. İşleme başına gecikme yalıtık olarak iyidir, ancak yük altında makine takas eder, CPU doygunlaşır ya da istekler kuyruğa girer ve zaman aşımına uğrar.
- Olası neden. Mevcut RAM için çok fazla PHP-FPM çalışanı, dolayısıyla çalışan tepelerinin toplamı fiziksel belleği aşar ve ana makine takas eder; ya da çok az çalışan, dolayısıyla istekler küçük bir havuzun ardında serileşir.
- Çözüm.
-
pm.max_children’ı profillenmiş bir tepeden boyutlandırın. Standart formülü kullanın:pm.max_children = (total RAM - OS/other overhead) / per-worker peak memoryBir çalışanın gerçek tepesini temsili bir belgeyle ölçün (Kapsam’daki profilleme notuna bakın), OS ve birlikte yerleşik hizmetler için manevra alanı ayırın ve bölün. Bir pay bırakın; RAM’in %100’üne boyutlandırmayın.
-
Sıkıştırma maliyetini bütçenizde sabitleyin. Flate sıkıştırması, bir akış yazmanın önemli bir CPU maliyeti olabilir ve sıkıştırılabilir akış baytlarının hacmiyle ölçeklenir, dolayısıyla sayfa sayısı ve gömülü yazı tipi hacmi işleme başına CPU’yu etkiler; görüntü işleme, yazı tipi alt küme oluşturma ve girdi ayrıştırma da baskın olabilir. Temsili belgelerle ölçün ve çalışan sayısını ve CPU’yu seçerken gerçek sürücüyü hesaba katın.
-
Çocukların geri dönüşmesi ve herhangi bir yavaş büyümeyi geri alması için, yukarıdaki çalışan girdisinde olduğu gibi
pm.max_requests’ipm.max_childrenile birlikte ayarlayın.
-
- İlgili. Akış işleme ve bellek.
Girdi: büyük güvenilmeyen girdi ayrıştırması yavaş veya pahalı
“Girdi: büyük güvenilmeyen girdi ayrıştırması yavaş veya pahalı” başlıklı bölüm- Belirti. Bir işleme, büyük veya derinlemesine yuvalanmış bir girdide, özellikle HTML veya üretmediğiniz bir yazı tipinde, yavaş ya da bellek ağırlıklıdır.
- Olası neden. Ayrıştırma maliyeti, girdi boyutu ve yapısıyla ölçeklenir. Patolojik bir girdi (derin yuvalama, devasa bir öğe sayısı veya hatalı biçimlendirilmiş bir yazı tipi) bütçeye baskın olabilir.
- Çözüm.
- Motorun sınırlarına yaslanın. Yerel
writeHtml()HTML ayrıştırıcısıMAX_NESTING_DEPTH = 100veMAX_ELEMENT_COUNT = 50000(ADR-001) zorlar; bu sınırların üzerindeki girdiler, sürecin tükenmesine izin verilmek yerine reddedilir. (İsteğe bağlı Chrome köprüsü,writeHtmlChrome(), bu ADR-001 sınırları için kapsam dışıdır ve kendi ayrı bellek/girdi sınırlarını zorlar.) - Çağıranın sağladığı yazı tiplerini güvenilmeyen olarak ele alın. Hatalı
biçimlendirilmiş bir yazı tipi, çıktıyı bozmak yerine
NextPDF\Exception\FontParsingExceptionfırlatır, dolayısıyla belirli istisnayı yakalayın ve yeniden denemek yerine girdiyi reddedin. - Girdileri sınırınızda doğrulayın ve boyutlandırın ve çağıranın etkilediği içerik için belge boyutu üzerinde istek düzeyinde sınırlar uygulayın.
- Motorun sınırlarına yaslanın. Yerel
- İlgili. Sorun giderme: yazı tipleri ve etiketleme.
Karar tablosu: belirtiden kaldıraca
“Karar tablosu: belirtiden kaldıraca” başlıklı bölüm| Belirti | En olası kaldıraç |
|---|---|
Tek bir işlemede Allowed memory size … exhausted | $config->withImageCacheBytes() değerini düşürün; gömmeden önce görüntüleri küçültün; çalışan başına memory_limit’i yükseltin |
| Tepe bellek sayfa sayısıyla yükselir | Belgelenmiş akışlı yazma yolunu kullanın |
| Çalışan belleği birçok iş boyunca tırmanır | FontRegistry/ImageRegistry’yi DocumentFactory aracılığıyla paylaşın; pm.max_requests / --max-jobs ayarlayın |
| İlk istekler yavaş, istek başına ayrıştırma maliyeti | Opcache’i etkinleştirin; başlatmada $fontRegistry->warmup() sonra ->lock() |
| Yük altında ana makine takas eder / gecikme sıçrar | pm.max_children = (RAM − ek yük) / çalışan başına tepe boyutlandırın |
| Büyük/güvenilmeyen girdide yavaş veya ağır | ADR-001 sınırlarına yaslanın; hatalı biçimlendirilmiş yazı tiplerini FontParsingException üzerinde reddedin |
Sınır durumları ve püf noktaları
“Sınır durumları ve püf noktaları” başlıklı bölümimageCacheBytes, bir bellek tavanıdır, bir boyut düğmesi değil. Onu düşürmek, bir derlemenin hızlıca başarısız olması için önbelleği sınırlar; gömdüğünüz görüntüleri asla yeniden örneklemez veya yeniden kodlamaz. Core’un bir görüntü kalitesi denetimi yoktur.withCompress(false), dosyaları daha büyük kılar ve bir ayıklama/profilleme yardımcısıdır. Bir boyut en iyileştirmesi değildir; CPU/bellek ödünleşimini kaydırır (sıkıştırma adımını atlar), belleği azaltmaz.- Akış motorunun tam bellek profili bir
experimentalkatman özelliğidir ve minör sürümler arasında kayabilir. Herhangi bir tek ölçümü, taşınabilir bir sabit değil, bir gözlem olarak ele alın. memory_limit,opcache.*,pm.max_childrenvepm.max_requests, standart PHP / PHP-FPM ayarlarıdır. NextPDF bunlar için kendi anahtarlarını sunmaz; onlarıConfig’te değil, çalışma zamanınızda yapılandırın.
Ayrıca bakınız
“Ayrıca bakınız” başlıklı bölüm- Akış işleme ve bellek — akış işleme modeli, ADR-001 sınırları ve tam toplu-çalışan eğitimi.
- PDF dosya boyutunu küçültün — sıkıştırma ve yazı tipi alt küme oluşturma, iki gerçek boyut denetimi.
- Sorun giderme: yazı tipleri ve etiketleme — yazı tipi çözümleme, ayrıştırma ve alt küme oluşturma başarısızlıkları.
- Bilgi tabanı dizini
Sözlük: akışlı yazıcı · yazı tipi alt küme oluşturma