Autor Zpráva
swisst
Profil
Chci dát na svůj web výpočet psanýv PHP, který spotřebuje hodně času (řádově vteřiny). Jak to udělat, aby mi to neblokovalo ostatní návštěvníky?

Předpokládám, že výpočet nebude provádět mnoho návštěvníků současně (ale 2-3 se tam výjimečně sejít mohou). Ostatních návštěvníků, kteří tohle nepoužijí bývá do 10.
Hostuji na WEDOSu, kde mám zajištěno myslím 5 současných procesů. Když se sejde požadavků víc, tak čekají až se uvolní misto. Kdybych to tam pustil "jen tak", tak by se často stávalo, že když někdo spustí výpočet tak silně zpomalí ostatní uživatele.

Rád bych to udělal tak, aby všichny ostatní procesy měli přednost před tím procesem, který počítá. Tj. ten kdo chce výpočet, ten si počká o něco déle, aby "normální" návštěvníci nemuseli čekat na ty, kteří počítají.

Když jsem kdysi programoval na PC, tak tam byly funkce jako ProcessMessages, které se daly do průběhu výpočtu, a ty zajistily obsloužení čekajících událostí. Není v PHP něco podobného? Nebo napadá vás jiné řešení?
Str4wberry
Profil
A nejde ten dlouhý výpočet rozdělit do více kroků?
swisst
Profil
Str4wberry:
Výpočet rozdělit jde. Zvažuji spustit u klienta JavaScript, který by AJAXem volal jednotlivé kroky. Má to jeden háček: mezivýsledky jsou hodně objemné. Znamenalo by to (v případě rozdělení na dva kroky):
- zavolat AXAXem první část výpočtu a jako odpověď přijmout velký balík dat (nemám to spočítané, ale odhaduju tak 100kB)
- pak analogickým postupem zavolat druhou část -tj. předat ten velký balík a přijmout výsledek.
Šlo by i více kroků, to už není podstatné. Bohužel tam pořád zůstává to předávání objemných dat.

Jak se dá mezivýsledek uložit na serveru? Napadá mne MySQL přijde mi to trochu složité (identifikace úlohy, čištění zbytků při přerušení výpočtu uživatelem). Není nějaký elegantní způsob, jak ukončit PHP úlohu a pak zase navázat (v rámci session - ale neukládat to u klienta, to by zase bylo hodně dat)
Kajman
Profil
Co si koupit na výpočty další hosting?
Str4wberry
Profil
Možná by pomohlo, kdybyste napsal, co řešíte.

Jinak předávat 100 kB dat nevidím jako moc velký problém. Předávat to ze serveru na klienta a potom zase zpátky jsem nemyslel, mezivýsledek se může uložit k identifikátoru uživatele na serveru třeba do serializovaného pole. Jediný rozdíl by byl v tom, že by se úkon provedl ve více krocích a po každém by se mohl návštěvník dozvědět, jak výpočet probíhá.
swisst
Profil
Kajman:
To mám v záloze jako nouzové řešení. Hostingů mám víc, ale nelíbí se mi, když je jeden web moc rozkouskovaný.


Str4wberry:
„... že by se úkon provedl ve více krocích a po každém by se mohl návštěvník dozvědět, jak výpočet probíhá.

Jojo, to by bylo pěkné (hlavně ta průběžná informace). Jen hledám co nejjednodušší cestu. To co dělám není hlavní část webu, jen taková parádička navíc a nechci kvůli takové drobnosti dělat nějaké komplikované věci. Jakmile se na webu něco změní, tak podobné vyfikulence jsou vždycky semeniště problémů. Proto bych upřednostnil něco, co dá PHP procesu nižší prioritu a nemusím se o to starat.
Keeehi
Profil
swisst:
PHP samozřejmě umí komunikovat mezi procesy. Když jsem to ale posledně testoval, tak na WEDOSu jsou ty funkce zakázané. A ani se nedivím.
Pokud bye chtěl pracovat s procesy, doporučil bych virtuální server. Pak ale zase nemáš na počet procesů omezení neb jsi pánem všeho.
swisst
Profil
Str4wberry:
Takže vyhrálo řešení s kouskováním procesu. Díky za inspiraci.

- Prohlížeč si stáhne stránku a spustí se JavaScript.
- JS si postupně AJAXem říká o výpočet. Na domovském serveru vždy proběhne kus výpočtu, zapíše se tam mezivýsledek a vrátí AJAXu info, že je nutno pokračovat.
- A takhle se to cyklí dokud volaný server nevrátí AJAXu info, že je výpočet u konce (a výsledek).

Má to jeden háček: JS (AJAX) může volat pouze php na tom webu, ze kterého se webová stránka stáhla. Takže ten výpočet pořád probíhá na hlavním webu a potenciálně zpomaluje ostatní uživatele. Je nějaká možnost, jak celou tu zátěž přenést na jiný server?

Momentálně to mám vyřešené tak, že "domácí" server to nepočítá, ale zavolá php script na vedlejším serveru, kde se to počítá. To ale není žádná výhra (spíš naopak), protože hlavní server stejně čeká na odezvu a tím blokuje jeden php proces (takže vlastně blokuje dva servery - sebe a ten výpočetní).

Je nějaký způsob jak to obejít? Potřeboval bych z JS volat php na jiném serveru.
Asi by šlo dát do stránky iframe, který by obsahoval ten JS... ale přijde mi to už hodně "přes ucho" (takhle budu mít na webu džungli). Je nějaké elegantnější řešení?
Kajman
Profil
JS může volat i jiný server, mrkněte třeba na jsonp.

Osobně bych to asi nekouskoval, zavolal bych lokální skript, co spustí výpočet na jiném stroji a vrátí identifikátor výpočtu, pak bych se periodicky ptal lokálního skriptu, jak na tom výpočet je, buď vrátí např. procenta nebo výsledek (přestanu se dále dotazovat). Takže požadavky klient - server tam budou kratičké.
Fisir
Profil
Reaguji na swissta:
A je nutné, aby ten výpočet provádělo PHP? Nešlo by ten algoritmus přepsat do JavaScriptu, takže by si každý návštěvník zpracoval svůj výpočet a na server by odeslal jen jeho výsledek?
swisst
Profil
Kajman:
Díky, jsonp jsem neznal - to je přesně ono!
Už mi to běhá "rozkouskované". Jen prosím o upřesnění - jak to myslíte s tím, že by se spustil výpočet na serveru (nerozkouskovaný) a lokální script by periodicky zjišťoval, jak je daleko? Já jsem myslel, že JS může zavolat PHP a pak od něj dostat nějakou odezvu (synchonně nebo asynchronně). Ale ta odezva je jednorázová - nebo se pletu? To co píšete by znamenalo, že PHP na serveru občas pošle informaci o tom, jak je daleko a JS to nějak lapá. Takhle je to myšleno? A jak se to dá dělat?

Fisir:
Asi by to šlo i v JS, ale v PHP je docela funkční přesná aritmetika, kterou potřebuji (rozšíření GMP) a mám tam zajištěný nějaký výpočetní výkon (není velký a musím ho platit já, ale je to aspoň jistota). Navíc mám ochráněný algoritmus.

Na server bych to v JS posílat nemusel, jde čistě o výpočet pro uživatele (návštěvníka).
Kajman
Profil
Ano, odezva je jednorázová, ale JS se může ptát opakovaně.

JS -> spusť výpočet
      spuštěno s tímto id <- PHP
      
JS -> už máš výsledek pro toto id?
      nemám, zatím 1% <- PHP
      
JS -> už máš výsledek pro toto id?
      nemám, zatím 45% <- PHP
      
JS -> už máš výsledek pro toto id?
      nemám, zatím 80% <- PHP
      
JS -> už máš výsledek pro toto id?
      mám a předávám <- PHP
swisst
Profil
Kajman:
Takže by běžel výpočet v v jednom PHP scriptu (procesu), který by průběžně někam ukládal informaci o tom, jak je daleko. A jiný PHP proces volaný JS by se na tohle info mohl podívat a vrátit JavaScriptu buď výsledek, nebo zprávu jak je to daleko. Rozumím správně?

Jasně, to by šlo. Pro mne má "rozkouskování" tu výhodu, že neblokuje server tak dlouho v jednom kuse. Takže se dostanou "k lizu" i ostatní uživatelé. Navíc, každá část může spotřebovat max_execution_time, takže to může běžet i pár minut. Sice WEDOS má 90 sec, což je dost, ale v mém případě je to tak nějak na hranici.
Ale uznávám, že tohle průběžné ukládání je stylovější a tak nějak čistší.
V každém případě díky!
swisst
Profil
Tak už to běhá rozkouskované.
V některých případech je výpočet hodně pomalý, ale to se nedá svítit. Díky tomu rozdělení dojde čas málokdy.
Tady je výsledek (počítá to RPSN)
www.stavebky.cz/kalkulator-rpsn-irr-cash-flow
Davex
Profil
swisst:
Není důvod, aby výpočet musel trvat tak dlouho. Nepoužíváš na výpočet IRR nějaký neefektivní algoritmus? Zkus třeba tento: www.snip2code.com/Snippet/145405/IRR-formula-for-PHP.
swisst
Profil
Davex:
Já používám postup, který je sice pomalý, ale zato najde všechna řešení. Ono se moc nemluví o tom, že RPSN je řešení algebraické rovnice n-tého řádu, které má obecně n řešení. V praxi sice velmi často existuje řešení jediné, ale ne vždy. Ostatně níž na té stránce jsou na to nějaké příklady.

Newtonova metoda (na kterou odkazuješ) je sice super rychlá, ale dá se použít pouze pokud jsou splněny určité předpoklady, což není tento případ. Největší problém je zjistit počet řešení a najít intervaly, ve kterých se jednotlivá řešení nacházejí. Když je v intervalu jediné řešení, tak už je vyhráno a dá se použít třeba i ta Newtonova metoda, na kterou vede odkaz. Ale to už je o několik řádů jednodušší (a hlavně rychlejší) úloha, takže tam používám staré dobré půlení intervalů, což je sice oproti Newtonovi dřevorubecká práce, ale zase mám zaručené, že najdu řešení.

Pro lidi co spěchají je defaultně nastaven zjednodušený výpočet, který tohle všechno ignoruje a zkusí najít aspoň jedno rozumné řešení, což je easy a tam problémy s časem nejsou.

Takže: důvod je zatraceně silný ;) jmenuje se hledání reálných kořenů polynomu stupně 100
Keeehi
Profil
Napadá mě, že by tedy možná stálo za to si na ten problém napsat řešící algoritmus v Cčku. Ten z optimalizovat co to jde. A prodalší zvýšení výkonu využít nějakého cloudu, třeba od amazonu.
Asymptotická složitost algoritmu se nezmění ovšem vždy se dá pracovat s konstantami. Kamarád měl na škole předmět kde se optimalizovala úloha násobení bitových matic. Optimalizovalo se tam až opravdu na úroveň architektury procesoru. Počítalo se s pipeliningem, velikostí registrů sběrnic atp. Výsledkem bylo, že i když asymptotická složitost byla pořád stejná, reálné zrychlení bylo v řádu tisíců.
Myslím si že i kdybs nedělal tyto optimalizace, už samotné přepsání do samostatného binárního programu by mělo pomoct.
swisst
Profil
Keeehi:
Jasně, že php není na takovéhle výpočty stavěné. Ale chci to mít na webu a na druhé straně to není pro web natolik podstatné, abych kvůli tomu měnil hosting (mám standardní, zcela postačující). Tenhle výpočet použije jen pár uživatelů, kteří o tom něco věcí. Většina lidí netuší, co RPSN vůbec znamená. A že to může mít více řešení, to už je pro ně zcela za horizontem chápání.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

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