Opcode PHP: migliorare il rendimento dell’applicazione senza modificare il tuo codice

Gli opcode generati dal motore PHP sono fortemente influenzati dalla modalità di scrittura del codice, non solo in termini di numero di istruzioni per compiere una task. Chiaramente, questo è molto importante e penso sia ovvio per te.

Cosa potrebbe essere meno ovvia è che persino la sintassi del codice può cambiare completamente gli opcode generati, causando un overhead considerevole per il CPU dell’apparecchio nell’esecuzione dello stesso codice.

Negli ultimi anni, il mio prodotto SaaS è cresciuto molto, e mi ha dato l’opportunità di approfondire sempre più nelle tecniche di ottimizzazione per portare il mio carico di lavoro all’efficienza massima possibile.

I risultati che ho ottenuto sono impressionanti e mi hanno aiutato molto a sbloccare il flusso di cassa libero per continuare a sviluppare il mio percorso SaaS.

A questo punto, il processo PHP all’interno del mio prodotto SaaS sta processando oltre 1,2 miliardi (con una “m”) di pacchetti di dati al giorno su una macchina con 2vCPU e 8GB di memoria. Utilizzo un gruppo di autoscaling AWS per avere maggiore flessibilità in caso di spinte imprevedibili, ma raramente aggiunge una seconda macchina (una/due volte a settimana).

Vogliamo entrare nel soggetto dell’articolo. Penso che lo troverai molto interessante.

Cos’è gli Opcode in PHP?

Gli opcode in PHP stanno per operation code, e si riferiscono agli istruzioni a basso livello che sono eseguite dal motore PHP dopo che il codice sorgente PHP che hai scritto è stato compilato.

In PHP, la compilazione del codice avviene in runtime: fondamentalmente, la prima volta che il tuo codice è preso dal motore PHP sarà compilato in questo codice amico del machine, memorizzato (così il motore non compila nuovamente lo stesso codice) e quindi eseguito.

Questa è una semplice rappresentazione del processo:

Memorizzazione degli Opcode in PHP

La memorizzazione degli opcode in PHP consente di risparmiare tre passaggi nel processo di esecuzione del codice: l’analisi del codice PHP grezzo, la tokenizzazione e la compilazione.

Una volta generati gli opcode la prima volta, vengono memorizzati in memoria in modo da poterli riutilizzare nelle richieste successive. Ciò riduce la necessità per l’engine PHP di ricompilare lo stesso codice PHP ogni volta che è eseguito, risparmiando così molta CPU e memoria.

L’opcode cache più comunemente usato in PHP è OPCache, e è incluso in default a partire da PHP 5.5 fino alle versioni recenti. È altamente efficiente e largamente supportato.

Il caching del bytecode precompilato del script richiede l’invalidazione del cache dopo ogni deploy. Questo perché se i file modificati hanno la versione del bytecode nel cache, PHP continuerà a eseguire l’vecchia versione del codice fino a quando non si svuota il cache degli opcode, quindi il nuovo codice verrà compilato di nuovo generando un nuovo elemento del cache.

Come investigare gli Opcode in PHP

Per capire come la diversa sintassi può influenzare l’opcode del script, abbiamo bisogno di un metodo per catturare il codice compilato generato dall’engine PHP.

Ci sono due modi per ottenere l’opcode.

Funzioni native dell’estensione OPCache

Se l’estensione OPCache è abilitata sul tuo sistema, puoi usare le sue funzioni native per ottenere l’opcode di un file PHP specifico:

PHP

 

VLD (Vulcan Logic Disassembler) PHP Extension

VLD è una popolare estensione PHP che decompone il codice PHP compilato e produce l’opcode. È un potente strumento per capire come PHP interpreta e esegue il tuo codice. Una volta installato, puoi eseguire un script PHP con VLD abilitato utilizzando il comando php con le opzioni -d:

Shell

 

La nostra uscita include informazioni dettagliate sugli opcode compilati, inclusa ogni operazione, la riga di codice associata e altro ancora.

Usa 3v4l (acronimo per EVAL)

3v4l è uno strumento online molto utile che ti permette di visualizzare l’opcode generato da un codice PHP che inserisci nell’editor. In pratica è un server PHP con VLD installato così può catturare l’output di VLD e mostrarti l’opcode nel browser.

Beh, essendo gratuito, userremo questo strumento online per le prossime analisi.

Come generare efficienti opcode PHP

3v4l è perfetto per capire come il sintassi del codice che usi può influenzare il risultante opcode PHP in modo positivo o negativo. Cominciamo a incollare il codice qui sotto in 3v4l. Mantiene la configurazione “tutte le versioni supportate” e clicca su “eval”.

PHP

 

Dopo l’esecuzione del codice, apparirà una scheda nel basso. Naviga nella scheda VLD per visualizzare l’opcode corrispondente.

Shell

 

Notare che la prima operazione è INIT_NS_FCALL_BY_NAME. L’interprete costruisce il nome della funzione usando lo spazio dei nomi del file corrente, ma non esiste nello spazio dei nomi App\Example — allora come funziona?

L’interprete controllerà se la funzione esiste nello spazio dei nomi corrente. Se non esiste, tenta di chiamare la funzione corrispondente della piattaforma di base.

Qui abbiamo l’opportunità di dirigere l’interprete a non fare questa doppia verifica e eseguire direttamente la funzione di base.

Provare ad aggiungere un backslash (\) prima di strlen e fare clic su “eval”:

PHP

 

Nella scheda VLD, ora puoi vedere l’opcode con solo una istruzione.

Poiché hai fornito l’esatto punto di funzione, non deve considerare alcuna fallback.

Se non ti piace usare il backslash, puoi importare la funzione come qualsiasi altra classe dalla root namespace:

PHP

 

Sfrutta le Ottimizzazioni Automatiche degli Opcode

Ci sono anche molti automatismi interni del motore PHP per generare un opcode ottimizzato che valuta le espressioni statiche in anticipo. Questo è stato uno degli argomenti più importanti per il grande miglioramento delle prestazioni di PHP dalla versione 7.x.

Essere consapevole di queste dinamiche può davvero aiutarti a ridurre il consumo di risorse e tagliarne i costi. Una volta fatto questo studio, ho cominciato a usare queste trucce nel codice in ogni momento.

Permettimi di mostrarti un esempio usando le costanti PHP. Esegui questo script in 3v4l:

PHP

 

Guarda le prime due righe dell’opcode PHP:

FETCH_CONSTANT cerca di ottenere il valore di PHP_OS dal namespace corrente e controllerà nel namespace globale poiché non esiste qui. Poi, l’istruzione IS_IDENTICAL esegue l’istruzione IF.

Adesso prova ad aggiungere il backslash a una costante:

PHP

 

Come puoi vedere nell’opcode, il motore non deve cercare di ottenere la costante perché ora è chiaro dove si trova, e poiché è un valore statico già ha questo in memoria.

Anche l’istruzione IF è scomparsa perché l’altro lato dell’istruzione IS_IDENTICAL è una stringa statica (‘Linux’) quindi l’IF può essere contrassegnato come “true” senza il costo aggiuntivo di interpretarlo in ogni esecuzione.

Ecco perché hai molto potere per influenzare il performance finale del tuo codice PHP.

Conclusione

Spero che sia stato un argomento interessante. Come vi ho detto all’inizio dell’articolo sto trattando questa tattica con molti benefici e, anzi, sono anche utilizzati nei nostri pacchetti.

Puoi vedere un esempio qui di come ho usato questi consigli nel nostro pacchetto PHP per ottimizzarne le prestazioni.

Se vuoi imparare di più sulle sfide nella costruzione di una compagnia guidata dai sviluppatori, puoi seguirmi su LinkedIn.

Source:
https://dzone.com/articles/php-opcode-improve-application-performance