PHP refcount jako optimalizace
Refcount mechanismus v PHP se dá použít k optimalizacím.
Třeba taková funkce unpack
pro parsování binárních dat musí vrátit pole
(z jakéhosi důvodu indexované od jedničky) i když parsuje jen jeden int. V důsledku toho
jednoduché unpack('v', $str)[1]
trvá 75 ns, což je ostudné. Ve své podstatě
jde o tři instrukce: cmp
+ jb
pro kontrolu jestli je ve stringu dost bajtů
a jeden mov
. To by nemělo trvat 75 ns ale jeden takt.
Nicméně to můžu trochu optimalizovat. Když využiju fakt, že je pole je by-value typ, můžu implementovat takhle (pseudokódem, šlo by o nativní funkci):
function unpack($str) { static $arr1 = new array [1 => null]; if (refcount($arr) > 1) { $arr1 = new array [1 => null]; } $arr1[1] = chomp2Bytes($str); return $arr1; }
Funkce unpack
vždy drží jednu referenci na pole, které opakovaně používá jako
výsledek.
Můžou nastat dvě situace:
- Volající kód pole změní. To nám nevadí, protože pole je by-value a program
takové objekty může změnit in-place jen když mají refcount 1 (viz makro
SEPARATE_ARRAY
). A protožeunpack
vždy drží jednu referenci a volající kód druhou, musí dojít ke kopírování pole a změněna bude až kopie. Verze kterou držíunpack
zůstane zachována. - Volající kód si vrácené pole uloží do proměnné. To v příštím volání
unpack
detekujeme přímo, protože najednou refcount je vyšší než 1 a jednoduše alokujeme nové pole. Tohle se stává ale jen velice zřídka.
S touhle optimalizací unpack('v', $str)[1]
trvá 50 ns (časy měřeny v interpreteru, JIT vypnutý). O třetinu lepší, ale stále ostudně pomalé.
Hlavní problém s funkcí unpack
je její složitá sémantika, kdy musí parsovat
vzorový string (v mém případě jen 'v'
, ale může to být i komplikovanější jako
třeba 'Vid/Vdate/Ccount/V*children'
) a pak v gigantickém switchi skákat na
těch pár instrukcí, které interpretují daný počet bajtů jako int nebo float
dané délky, dané znaménkovosti a dané endianovosti. Tahle logika zabere dobrých
25 ns.
To je nakonec důvod, proč tohle píšu jako článek a ne jako patch pro PHP. I s vypětím všech sil se stejně nemůžu dostat do čísel, za které bych se nemusel stydět.
???