Autor Zpráva
janbarasek
Profil
Ahoj,
ve svém vyhledávači bych rád zvedl rychlost načítání výsledků, takže jsem je rozdělil na mnoho logických bloků, které se načítají asynchronně (protože některé výsledky se zpracovávají delší dobu, nebo jsou datově náročné a musí se přenést větší balík dat, například obrázek). Výsledky nelze předem cachovat, protože se jedná o matematický vyhledávač.

Výsledky jsou rozděleny do mnoha boxů. Když dorazí první balík dat do prohlížeče, tak obsahuje informace o všech boxech, které budou na finální stránce (ale samotné boxy ještě nemusejí mít vypočítaný obsah), takže se uživatel akorát dívá na skupinku prázdných boxů, kde se za několik sekund obsah donačte.

Ideálně bych chtěl toto chování:
- Při requestu na server vrátím seznam všech budoucích boxů + informace o tom, odkud dostanou data
- Prohlížeč na dané adresy pošle další requesty a bude čekat na načtení dat
- Jakmile budou data načtena, tak se v boxu zobrazí, do té doby bude součástí boxu načítací animačka (tu si nakresím pomocí CSS animace)
- Pokud se data nenačtou do 3 sekund, tak bude box automaticky skryt (úplně vyřazen) a kdyby se náhodou data později donačetla (než vyprší platnost PHP procesu, takže asi 90 sekund), tak se znovu zobrazí s kompletním výsledkem

Napadá někoho z vás, jak to jednoduše udělat, například pomocí JavaScriptu, nebo jiné technologie?

Obsahem boxů jsou většinou generované matematické zápisy pomocí obrázků (a čeká se na jejich načtení), nebo specializovaný HTML kód (například interaktivních grafů).

Předem děkuji za jakoukoli radu.
juriad
Profil
Přesně tak jak říkáš. Ohledně technologie bych asi zvolil JSONP, tedy generovaný javascript, který se bude načítat do elementu <script>, který do stránky dorazí v rámci prvního balíku.

Ale varuji tě, toto ti zvýší počet requestů řekněme 10x (počet boxů krát) a každý z nich bude pomalejší než samotný výpočet kvůli režii spojené se spuštěním a ukončením. Takže to ve výsledku znamená, že obsloužíš méně uživatelů. Navíc se může stát, že uživatel zadá dotaz, který zaměstná mnoho procesů.

Něco takového podle mě nemá smysl dělat, pokud používáš PHP, které pracuje na principu 1 požadavek = 1 proces. Mnohem výhodnější je například Node.js. A ještě lepší je mít nějaký cluster, na který budeš jednotlivé úlohy delegovat.

mathematicator.com/search.php?q=sin%281%2Fx%29%2Fcos%281%2Fx%29 (také ukázka toho, že ti parsování vstupu nefunguje)
janbarasek
Profil
juriad:
Takže to ve výsledku znamená, že obsloužíš méně uživatelů.
Server má výkonu hodně a každý proces běží paralelně a navzájem se neovlivňují. Momentálně obsluhuji zhruba 30 tisíc dotazů denně, reálně zvládnu 100x víc.

Navíc se může stát, že uživatel zadá dotaz, který zaměstná mnoho procesů.
To vůbec nevadí. Každý boxík se může počítat nezávisle na ostatních, dokonce by každý z nich mohl zpracovávat úplně jiný procesor na úplně jiném serveru.

Mnohem výhodnější je například Node.js
Ještě musíš brát v potaz to, že je jádro už napsané a jeho překlad do jiného jazyka by bylo velice obtížné (nejdřív bych se tu technologii musel naučit používat a pak teprve bych mohl přeložit mnoho tisíců řádků kódu).

také ukázka toho, že ti parsování vstupu nefunguje
Protože to je funkce a ještě mi tam blbne parser závorek. Stačí je doplnit a funguje to. Až na to bude čas, tak to opravím, teď řeším závažnější chyby.

Co se týče ohledně počtu requestů, s tím bych problém až tak moc neviděl. Většina výsledků jsou obrázky generované pomocí technologie LaTeX a ty zkrátka ani jinak řešit nelze. Sice bych je mohl všechny vygenerovat najednou na serveru, spojit do jednoho obrázku a pak to celé poslat a přes CSS sprite zase rozdělit, ale přijde mi to jako zbytečná úchylárna - navíc by uživatel musel čekat na načtení všech výsledků.

U některých typů dotazů se generují opravdu rozsáhlé výstupy obsahující mnoho grafů (některé 3D grafy se generují i několik sekund, generuji to na grafické kartě, srazit se to prostě nedá, jsou to náročné operace) a uživatel by tak musel kvůli tomu čekat - ale díky skupině requestů by mohl aspoň část výsledků vidět hned.
juriad
Profil
janbarasek:
Podle toho, co jsem četl v [#1], jsem myslel, že ti vše běží v PHP na hostingu/VPS a pár věcí execneš (treba ty LaTeXové obrázky). Netuším, jakou tam máš infrastrukturu.

V tom případě bych si pro každý boxík přidal
<div class="box" id="abc-plot3d">
<script src="?id=abc&type=plot3d">
</div>
A uvnitř toho skriptu prostě výstup zobrazíš v příslušném divu. Můžeš také volat funkce, které definuje stránka pro nahlášení dokončení načtení boxu.
janbarasek
Profil
juriad:
Technicky zvládnu napsat veškerou agendu, která zaručí načtení obsahu do boxů. Mě jde spíše o to, jak detekovat fakt, že jsou výsledky již načtené. Teď odesílám data pomocí API, surový výstup vypadá zhruba takto: http://185.8.237.158/search/api.php?q=sin%28x%29

Jde mi o to, že chci v každém boxu detekovat například to, že byl načten obrázek LaTeXu, že se přenesl graf a tak dále. U některých dotazů (typicky analytická geometrie) trvá generování prostorových grafů a rovnic relativně dlouho.
juriad
Profil
A proč chceš detekovat, že už je vygenerovaný? Prostě pošleš request a až bude vygenerováno, dostaneš na něj odpověď.
Toto ti omezí počet spojení na server, takže to úplně paralelně nebude; typicky se bude najednou čekat na 6 boxů: stackoverflow.com/a/985704/4052811
Můžeš ale mít jeden alias; tím zvýšíš limit na dvojnásobek. yuiblog.com/blog/2007/04/11/performance-research-part-4

Toto je použitelné bez ohledu na logiku na backendu. Pokud by tvé API umělo nějak udržovat výsledky ve frontě, mohl bys něco chytřejšího vytvořit pomocí AJAXu:
1. request počká na 1. výsledek a vrátí ntici (výsledek, zbývající počet výsledků, počet výsledků čekajících ve frontě).
Po obdržení výsledku si klient pošle maximální neblokující počet requestů pro všechny výsledky ve frontě.
Spolu s výsledkem dostane opět aktualizované údaje (pozor na to, že pro některé výsledky si již sahají jiné requesty, takže je musíš odečíst, nebo jim třeba přiřadit identifikátory pro rozpoznání).
Opět pošleš requesty pro všechny dostupné.
Až dostaneš všechny dostupné výsledky a nějaké jsou stále počítané, pošleš další request, který počká na první z nich - což je výše popsaný 1. krok.

Vaše odpověď


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: