Problém s výkonností generování odkazů
- Acci
- Člen | 83
Ahoj. Začal jsem pronikat do tajů Nette rovnou s verzí 2.0 alpha. Mám
ovšem celkem velké problémy s výkonností, přesněji s vytvářením
odkazů. Vypisuji přibližně 100 položek, ke které generuji jeden
normální odkaz a dva signály, což znamená vytvoření 300 odkazů. Jenže
vytvoření všech těchto položek trvá přes půl sekundy (přibližně
polovinu NRoute->constructUrl
a druhou
NPresenter->createRequest
), další půl sekundy zabere
generování stránky. Je toto normální chování frameworku nebo něco
dělám špatně?
- Tharos
- Člen | 1030
Nedávno jsem řešil podobnou situaci. Já bych to celé nenazýval „problémem Nette“, protože to je prostě fakt, že když chci na nějaké stránce vygenerovat 300 odkazů, které budou závislé na nějakém routování, tak že to prostě bude mít nějakou režii (v praxi několik desítek milisekund). Jaký jiný framework, který odkazy generuje, se s tím vypořádá podstatně lépe?
Já jsem své zadání vyřešil podobně, jako hrach. Připravil jsem si metodu, která prováděla replace v závislosti na definované route. Takže i po změně route se mi stále generovaly korektní odkazy. Je to sice o malý overhead, ale „prasárnou“ bych to nenazýval. Kde je problém, „prasárna“? Zadání splněno, výkon zvýšen, přizpůsobitelnost kódu zachována. Občas prostě účel světí prostředek. :)
Editoval Tharos (31. 10. 2010 1:32)
- Ani
- Člen | 226
Podlemě by bylo fajn, když by nette provádělo něco jako ten replace.
Těch 300 linků je hned když máte třeba komentáře s karmou, editací,
linkem na autora, mazáním, reakcí. To máte třeba 6 linků na jeden
komentář. K tomu normální odkazy v menu, aplikaci…
Nedávno jsem si taky všimnul, že je to pomalé.
btw. createRequest je final
Editoval Ani (31. 10. 2010 18:04)
- David Grudl
- Nette Core | 8218
Kešování na úrovni metody createRequest() je poměrně problematické a
budu to řešit asi až v dalších verzích. Zatím se dá poměrně účinně
kešovat na úrovní šablon, a to buď makry {cache}...{/cache}
nebo vlastním makrem pro generování odkazů.
Taký nástřel, jak by šlo upravit makro {link ...}
aby
kešovalo (jde o úpravu LatteMacros.php), můžete to vyzkoušet:
public function macroLink($content, $modifiers)
{
return 'Nette\Templates\LatteMacros::cachedLink($control, ' . $this->formatLink($content) .')', $modifiers);
}
public static function cachedLink($control, $destination, $args = array())
{
$key = $destination . spl_object_hash($control);
$n = 1e5;
foreach ($args as $k => $v) {
$v = (string) $v;
if ($v === '' || $v === '0' || $v === '1') { // problematic values
$key .= ";$k=$v";
} else {
$key .= ";$k";
$args[$k] = $n;
$placeholders[$n++] = urlencode($v);
}
}
static $linkCache;
$cached = & $linkCache[$key];
if ($cached === NULL) {
$cached = $control->link($destination, $args);
if ($control->presenter->lastCreatedRequest === NULL) { // error
$cached = FALSE;
}
}
if ($cached === FALSE) {
return $control->link($destination, func_get_arg(2));
}
if (isset($placeholders)) {
return str_replace(array_keys($placeholders), array_values($placeholders), $cached);
} else {
return $cached;
}
}