# OPcache razložen: predpomnilnik bajtne kode PHP

> OPcache razložen: kako deluje predpomnilnik bajtne kode PHP, katere nastavitve štejejo, zakaj ga je treba po posodobitvah izprazniti in kako ga zaščititi.

Vir: https://phpsos.de/sl/php/opcache/  
Stanje: 25.10.2026  
Ponudnik: PHP SOS, Nujna pomoč za PHP in varnost strežnikov. Takojšnja pomoč po WhatsAppu: https://wa.me/491736494914?text=Pozdravljeni%2C%20PHP%20SOS%2C%20potrebujemo%20pomo%C4%8D%20z%20na%C5%A1im%20stre%C5%BEnikom%20PHP.%20Podjetje%3A%20%E2%80%A6%20Spletna%20stran%3A%20%E2%80%A6

**Na kratko:** OPcache je vgrajeni predpomnilnik bajtne kode PHP. Po priročniku v skupni pomnilnik shrani vnaprej prevedeno bajtno kodo, tako da PHP skript ob vsaki zahtevi ni treba znova nalagati in prevajati. V dobavljenem obsegu je od PHP 5.5.0. OPcache PHP pospeši, vendar ne nadomešča posodobitve: po popravku PHP je treba znova zagnati vse procese PHP, ne samo izprazniti predpomnilnika.

## Kaj točno počne OPcache?

Ob vsaki zahtevi mora PHP skripto prebrati, razčleniti in prevesti v opcode, torej v ukaze za navidezni stroj [Zend Engine](https://phpsos.de/sl/php/zend-engine/). Pri CMS-ju s stotinami datotek je to veliko dela, ki se nenehno ponavlja.

OPcache rezultat tega prevajanja shrani v skupni pomnilnik (shared memory). Do njega dostopajo vsi workerji storitve PHP-FPM ali vsi procesi Apache z mod_php. Če se datoteka ne spremeni, se njena bajtna koda neposredno ponovno uporabi.

OPcache se naloži kot razširitev Zend, ne kot navadna razširitev:

```ini
; Linux (pot je odvisna od paketa)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll
```

Po priročniku naj se OPcache naloži pred Xdebug, kadar sta aktivna oba.

Pomembno je, čigav je skupni pomnilnik. Pri PHP-FPM ga ustvari glavni proces, uporabljajo pa ga vsi workerji vseh poolov te storitve. Pri mod_php pripada glavnemu procesu Apache. Ponovni zagon storitve zato predpomnilnik v celoti izprazni, en sam nov worker pa ne. Za ukazno vrstico skupnega pomnilnika med klici ni, ker je vsak klic samostojen proces; tam je OPcache privzeto izklopljen.

Za odločevalce zadošča pravilo palca: OPcache je na produkcijskih strežnikih skoraj vedno smiseln, a zahteva jasen potek namestitev in posodobitev.

## Katere nastavitve OPcache štejejo?

Naslednje vrednosti izvirajo iz strani s konfiguracijo v priročniku PHP. Stolpec „Spremenljivo“ kaže, kje se nastavitev sme določiti: `INI_SYSTEM` samo v php.ini ali konfiguraciji strežnika, `INI_ALL` povsod.

| Direktiva | Privzeto | Spremenljivo | Pomen |
|---|---|---|---|
| `opcache.enable` | 1 | INI_ALL | predpomnilnik vklopljen ali izklopljen, med izvajanjem ga je mogoče samo izklopiti |
| `opcache.enable_cli` | 0 | INI_SYSTEM | predpomnilnik za ukazno vrstico |
| `opcache.memory_consumption` | 128 | INI_SYSTEM | velikost skupnega pomnilnika v MB |
| `opcache.interned_strings_buffer` | 8 | INI_SYSTEM | pomnilnik za skupne nize znakov v MB |
| `opcache.max_accelerated_files` | 10000 | INI_SYSTEM | največje število predpomnjenih skript |
| `opcache.validate_timestamps` | 1 | INI_ALL | preverja, ali so se datoteke spremenile |
| `opcache.revalidate_freq` | 2 | INI_ALL | razmik preverjanja v sekundah, 0 = ob vsaki zahtevi |
| `opcache.restrict_api` | prazno | INI_SYSTEM | funkcije API dovoli samo iz ene poti |
| `opcache.validate_permission` | 0 | INI_SYSTEM | preverja pravice datotek glede na trenutnega uporabnika |
| `opcache.validate_root` | 0 | INI_SYSTEM | preprečuje trke imen pri chroot |
| `opcache.file_cache` | prazno | INI_SYSTEM | druga raven predpomnilnika na disku |

Značilna produkcijska konfiguracija bi lahko izgledala takole. Vrednosti pred tem preverite z vašo aplikacijo:

```ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.restrict_api=/var/www/admin-tools
```

Kdor nastavi `opcache.validate_timestamps=0`, pridobi nekaj zmogljivosti. Takrat pa OPcache spremenjenih datotek sploh ne prepozna več in vsaka namestitev potrebuje ponastavitev predpomnilnika ali ponovni zagon.

## Opazovanje in ciljno praznjenje predpomnilnika

OPcache prinaša lastne funkcije, med njimi `opcache_get_status()`, `opcache_get_configuration()`, `opcache_invalidate()` in `opcache_reset()`. Kratek bralni pogled na zasedenost:

```php
<?php
$status = opcache_get_status(false);
if ($status === false) {
    exit("OPcache ist nicht aktiv.\n");
}
printf("Gecachte Skripte: %d\n", $status['opcache_statistics']['num_cached_scripts']);
printf("Freier Speicher: %.1f MB\n", $status['memory_usage']['free_memory'] / 1048576);
```

Na strežnikih z več spletnimi stranmi ne bi smela vsaka aplikacija moči izprazniti ali brati predpomnilnika vseh drugih. Za to je namenjen `opcache.restrict_api`: funkcije API smejo klicati samo skripte pod navedeno potjo.

## JIT: prevajalnik strojne kode v OPcache

Od PHP 8.0 OPcache vsebuje prevajalnik JIT, ki opcode prevede v strojno kodo. Po RFC za JIT je skoraj samostojen del OPcache in ustvarjeno kodo shrani v lasten predel skupnega pomnilnika. Upravlja se ga z `opcache.jit` in `opcache.jit_buffer_size`. Od PHP 8.4.0 je `opcache.jit` privzeto na `disable`. Kdaj se JIT splača, razlaga prispevek [JIT in zmogljivost v PHP 8](https://phpsos.de/sl/php/jit-und-performance/).

## OPcache in varnost: kaj velja po PHP2Shell

OPcache ni varnostno orodje, a ima posledice za varnost. Po PHP2Shell so pomembne tri točke:

1. **Ponastavitev predpomnilnika ni posodobitev.** `opcache_reset()` izprazni samo predpomnjene skripte. Interpreter z ranljivostma CVE-2026-109618 in CVE-2026-109619 ostane v pomnilniku, dokler niso vsi procesi znova zagnani. Kako, piše na strani [Ponovni zagon PHP-FPM in vseh workerjev](https://phpsos.de/sl/php2shell/php-fpm-neustart/).
2. **Vnesena koda lahko živi naprej v predpomnilniku.** Če je bila datoteka spremenjena in pozneje zamenjana, se pri izklopljenem preverjanju časovnih žigov lahko stara različica še naprej izvaja. Po čiščenju zato sodi zraven ponovni zagon.
3. **Skupni pomnilnik zahteva ločevanje.** Na strežnikih z več strankami pomagajo lastni pooli PHP-FPM za vsako spletno stran ter `opcache.validate_permission` in `opcache.restrict_api`. Imenik za `opcache.file_cache` sme biti zapisljiv samo za uporabnika PHP.

> **Nasvet:**
> Po vsaki posodobitvi preverite, ali je čas zagona procesov PHP po posodobitvi. Poln OPcache z visokim deležem zadetkov ni dokaz, da teče novi interpreter.

## Kako PHP SOS pomaga konkretno?

- **Preverjanje konfiguracije:** preberemo aktivno konfiguracijo OPcache za vsak način delovanja in jo uskladimo z vašo aplikacijo.
- **Zavarovanje namestitev:** vzpostavimo trden potek ponastavitve predpomnilnika in ponovnega zagona, da ne teče nobena stara različica kode.
- **Ločevanje strank:** v okviru [utrjevanja strežnika](https://phpsos.de/sl/leistungen/server-haertung/) nastavimo ločene poole, `restrict_api` in ustrezne pravice.
- **Kontrola po posodobitvah:** prek časov zagona procesov dokažemo, da posodobljeni interpreter resnično teče.


## Pogosta vprašanja

**Ali je OPcache privzeto aktiven?**  
OPcache se dobavlja s PHP od različice 5.5.0 in po priročniku teče z opcache.enable=1 kot privzeto vrednostjo, ko je razširitev naložena. Ali je naložena, je odvisno od vašega paketa ali ponudnika gostovanja. V ukazni vrstici je OPcache privzeto izklopljen (opcache.enable_cli=0).

**Zakaj po namestitvi še vedno vidim staro kodo?**  
Verjetno OPcache spremembe datotek preverja samo v presledkih ali sploh ne. Z opcache.revalidate_freq privzeto čaka dve sekundi, z opcache.validate_timestamps=0 nikoli. Takrat pomaga samo ponastavitev predpomnilnika ali ponovni zagon PHP-FPM oziroma Apacheja.

**Ali po posodobitvi PHP zadošča opcache_reset()?**  
Ne. opcache_reset() izprazni samo predpomnilnik s prevedenimi skriptami. Posodobitev PHP zamenja interpreter sam, ta pa je naložen v vsakem tekočem procesu. Za to je treba znova zagnati vse procese PHP.

**Ali je JIT v PHP 8.4 vklopljen?**  
Po priročniku je opcache.jit od PHP 8.4.0 privzeto nastavljen na disable, opcache.jit_buffer_size pa znaša 64M. Prej je bilo obratno: jit na tracing, medpomnilnik na 0. V obeh primerih JIT brez zavestne konfiguracije ni aktiven.

## Viri

- [Priročnik PHP: OPcache](https://www.php.net/manual/en/book.opcache.php)
- [Priročnik PHP: konfiguracija OPcache](https://www.php.net/manual/en/opcache.configuration.php)
- [Priročnik PHP: namestitev OPcache](https://www.php.net/manual/en/opcache.installation.php)
- [PHP RFC: JIT](https://wiki.php.net/rfc/jit)
