Autor Zpráva
Ropak
Profil *
Mám problém s "Maximum execution time of 30 seconds exceeded". Generuji data jistym matematickým výpočtem dle kriterii zadaných uživatelem. Dat byva hodně a výpočet trvá dlouho. Vetšinou to skonci na výše uvedené chybe. Obavam se že funkce set_time_limit() neni řešení, protože hrozí i vypršení limitu prohližeče.
Jedine co me napada je v pravidelnych intervalech prerusit vypocet a pomoci hlavicky "Location" zavolat znovu sam sebe s tim ze si stav ulozim nekam do session.
Jde neco takoveho udelat jeste s tim ze se vypise nejaka informace o stavu procesu?
pollo22
Profil
Ja by som sa skôr snažil nejak lepšie zoptimalizovať ten vypočet. čo to počitaš že to trva tak dlho?
mckay
Profil
Ropak:
Nechci se ošklivě zmýlit, ale ještě nikdy se mi nestalo, že by mi vypršel čas provádění skriptu v prohlížeči. Dle mého se všechny výpočty odehrávají na serveru a prohlížeč jen čeká na jeho odpověď, takže by to snad nemělo dělat problémy. (Mám Operu)
Akacko
Profil
Ropak:
O jaký výpočet se jedná? Nešel by nějak zjednodušit (odstranit rekurzi, pokud nějaká je apod.)? Nezacyklí se výpočet? Popř. pošli sem ten výpočet a třeba to někdo vyřeší a pomůže optimalizovat.
tomyx007
Profil
Pokud cerpas data z databaze, pouzivej indexy apod...Nebo to chce proste optimalizaci skriptu. Takto nejde k tomu vice rici, kdyz nevidime ten tvuj algoritmus...
imploder
Profil
Ropak:
Výpočet může během svého průběhu generovat nějaký výstup, aby prohlížeč třeba každých pár sekund něco dostal a neměl tak dojem, že server neodpovídá.

Funkcí microtime se dá zjistit čas v mikrosekundách. Můžeš si ho na začátku uložit, pak během výpočtu kontrolovat, jestli už není třeba o 5 sekund větší a když je tak vypsat stav výpočtu prohlížeči a uložený čas přepsat aktuálním.

Čistější řešení by bylo, aby se ten výpis volal přerušením (aby se čas nemusel kontrolovat a nezpomaloval se tím výpočet) - to nevím, jestli v PHP jde udělat.
Ropak
Profil
pollo22:
Ne ne zadna rekurze ani nekonecna smycka. Generuji náhodné události s hustotou pravdepodobnosti zavislou dle zadani uzivatele (ke kazde udalost se pak prirazujen nekolik parametru). Muze se jednat radove o x*10e6 udalosti, ktere potrebuji naladovat do db. Algoritmus nedokazu udelat v mysql.

pollo22:
vidis to me nenapadlo posilat neco prubezne prohlizeci, to by bylo asi nejjednodussi.
nightfish
Profil
Ropak:
Muze se jednat radove o x*10e6 udalosti, ktere potrebuji naladovat do db
v tom případě doufám, že používáte vícenásobné inserty, protože sunout takového množství řádků do databáze po jednom je za trest (a trvá to dlouho)

co se limitu prohlížeče týká - vcelku běžně mi v prohlížeči běží skript třeba hodinu (Firefox)
Ropak
Profil
nightfish:
ano, ale jen po jednotkach az stovkach. Zalezi to na prubehufunkce v danem kroku.
peta
Profil
Ropak:
Pokud bys muj server zatezoval 30s v kuse, asi bych ti ten script brzo odpojil.
Uz to bylo receno, dej sem kod vypoctu. Idealne celeho souboru, link na nej. Pravdepodobne misto vyuziti pameti vyuzivas mnozstvi jinych prostredku, treba jak pisi, 30x volas databazi nebo neco podobne. Bez kodu tezko rici.
Muzes zkouknout bigdump.php (google), ktery se pouziva misto phpadminu na nasoukani treba 60MB sql kodu do databaze.
TomášK
Profil
Pro načítání velkého množství záznamů je dle mých zkušeností lepší LOAD DATA než INSERT. Při vícenásobném insertu jsem musel řešit omezení na počet vkládaných záznamů, tuším, že se to pohybovalo v desítkách tisíc a LOAD DATA bylo znatelně rychlejší - odhadem desetkrát. Přesná čísla si nepamatuju.
Ropak
Profil
No dobra, je to trosku delsi, ale snad pochopitelne.
function flushsql(&$sql,&$sqlvalues)
{
  $sql .= ";";
  $result = mysql_query ($sql, $GLOBALS["link"]);
  $sql = "INSERT INTO `dbdb`.`".$_SESSION["a"]['tbname']."` (`sec`, `us`, `amp`, `len`) VALUES ";
  $sqlvalues=0;          
}
 
 // ....

  // generujeme hity do db
  $hittime = new uTime;
  $sql = "INSERT INTO `dbdb`.`".$_SESSION["a"]['tbname']."` (`sec`, `us`, `amp`, `len`) VALUES ";
  $sqlvalues=0;
  $printed = 0;
  // vyrabime hity a ukladame je do db
  for ($i=0;$i<$_SESSION["aesrc"]['itvcnt'];$i++)
  {
    // pro kazdy interval
    $a = &$_SESSION["a"]['itv'][$i];
    for($t=$a["start"]->sec; $t<$a["end"]->sec; $t++)
    {
      // jdeme sekundu po sekunde
      $c = (float)(getfv($a, $t) + getfv($a, $t+1))/2.0;  // cetnost jako prumer funkcni hodnoty na zacatku a konci periody
      while ($c>=1.0)
      {
        $hittime->sec = $t;
        $hittime->us = (integer)((random_0_1()*1000000) + ($a["tvar"]*(random_0_1()-0.5))); //pridame neurcitost casu
        $hittime->Normalize();  // us musi byt v intrvalu <0,1000000)
        $amp = random_0_1()* ($a["ampmax"] - $a["ampmin"]) + $a["ampmin"]; // amp nahodne v zadanem intervalu
        if ($hittime->sec > $a["start"]->sec && $hittime->sec < $a["end"]->sec)  // hity ktere padnou mimo zadany interval ignorujeme
        {
          if ($sqlvalues>0) $sql .= ", ";
          $sql .= "(FROM_UNIXTIME(".$hittime->sec."), '".$hittime->us."', '".$amp."', '".(integer)($amp*100)."')";
          $sqlvalues++;
          if ($sqlvalues>100)
            flushsql($sql,$sqlvalues);
        }
        $c -= 1.0;
      }
      if (random_0_1()<$c) // mene nez jedna za sekundu
      {
        $hittime->sec = $t;
        $hittime->us = (integer)(random_0_1()*1000000 + ($a["tvar"]*(random_0_1()-0.5))); //pridame neurcitost casu
        $amp = random_0_1()* ($a["ampmax"] - $a["ampmin"]) + $a["ampmin"];
        if ($hittime->sec>$a["start"]->sec && $hittime->sec<$a["end"]->sec)
        {
          if ($sqlvalues>0) $sql .= ", ";
          $sql .= "(FROM_UNIXTIME(".$hittime->sec."), '".$hittime->us."', '".$amp."', '".(integer)($amp*100)."')";
          $sqlvalues++;
          if ($sqlvalues>100)
            flushsql($sql,$sqlvalues);
        }
      }
      if (time() >= $printed + 3) 
      { // aktualizace počítadla nejdříve za tři vteřiny
        echo "<script type='text/javascript'>document.getElementById('counter').innerHTML = 'Interval:".$i.", Cas:".$t."';</script><noscript>.</noscript>\n";
        ob_flush();
        flush();
        $printed = time();
      }
    }
    if ($sqlvalues>0)
      flushsql($sql,$sqlvalues);
  }
  // tady by mela byt db naplnena



Dopredu upozornuji, ze je to docasna verze. Kod v cyklu While a za IF je nyni identicky a prijde do funkce.
nightfish
Profil
Ropak:
chtělo by to nějaké profilování... tzn. určit, při které činnosti skript stráví nejvíce času - jestli při tom výpočtu, nebo při provádění dotazů do DB...

k těm SQL dotazům:

(FROM_UNIXTIME(".$hittime->sec."), '".$hittime->us."', '".$amp."', '".(integer)($amp*100)."')
tam, kde se vkládají číselné hodnoty, odstraňte ty apostrofy, mysql pak nebude muset přetypovávat

FROM_UNIXTIME($hittime->sec) by se dalo nahradit za "'".Date("Y-m-d H:i:s", $hittime->sec)."'" - ale jestli to přinese zrychlení musíte vyzkoušet sám
DoubleThink
Profil *
mckay:
Nechci se ošklivě zmýlit, ale ještě nikdy se mi nestalo, že by mi vypršel čas provádění skriptu v prohlížeči.
Server obvykle během vykonávání skriptu udržuje s klientem spojení - to může trvat teoreticky nekonečně dlouho.
Ropak
Profil
DoubleThink:
To je dobre. Jen aby vydrzel uzivatel. Ty vypisy co jsou tam udelane pomoci JS nejak nefunguji (asi AVG)

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: