Protobuf a NaN

Školení, která pořádám

Většina produktů Google komunikuje téměř výhradně pomocí Protocol Buffers. V tomto formátu se komunikuje s úložištěm, mezi servery a posílají se v něm data i do klienta a z klienta. Na serveru se protocol buffery přenáší v binárním formátu, na klienta se posílá řetězec obsahující JavaScriptový literál pro pole. Ve srovnání třeba s JSONem jde o formát mnohem úspornější, protože názvy polí se vůbec nepřenáší. Srovnejte:

{"id":1,"name":"Jakub"} // JSON
[1,"Jakub"] // Protobuf

Při buildu se vygenerují metody jako getName a setName, pomocí kterých se s protocol bufferem pracuje. To má zároveň tu výhodu, že když uděláte v názvu metody překlep, tak build spadne. U JSONu tato ochrana chybí, protože např. obj.anme je platná hodnota při čtení i zápisu. Closure Compiler vygenerované metody potom obvykle zase inlinuje, taže i výsledný JavaScriptový kód je malý.

Na klientu se řetězec obsahující protocol buffer dá přeložit do JavaScriptového pole v zásadě dvěma způsoby: eval nebo JSON.parse. Oba způsoby jsou v moderních prohlížečích velmi rychlé, JSON.parse o něco rychlejší. eval má zase tu výhodu, že nepoužitá pole lze vynechat: eval('[1,,,"Jakub"]') versus JSON.parse('[1,null,null,"Jakub"]'). Tahle výhoda ale není příliš zásadní, protože mnohokrát opakovaný fragment ,null lze dobře komprimovat. Při mnoha prázdných polích se pak použije formát {"1":1,"2000":"Jakub"}.

Většina produktů Google v současnosti pro zpracování protocol bufferů používá eval. Důvod je ten, že JSON nepodporuje speciální číselné hodnoty, které podporuje protobuf i JavaScript. Jde o NaN, Infinity a -Infinity. Nekonečno se dá simulovat pomocí obřího čísla (1e404 se zaokrouhlí na Infinity), ale s NaN je problém. Přenášená data jsou tak rozmanitá, že tu a tam se NaN bohužel někde vyskytne.

Rozhodli jsme se proto NaN přenášet jako řetězec "NaN" a při deserializaci ho přeložit zase zpátky na NaN. Opačnou změnu je samozřejmě potřeba udělat i při serializaci, protože JSON.stringify převádí NaN na null. Díky tomu budeme moci z kódu odstranit eval a z CSP potom vyhodit unsafe-eval.

Jakub Vrána, Řešení problému, 19.2.2016, diskuse: 0 (nové: 0)

Vložit příspěvek

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL:

avatar © 2005-2016 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.