Problém s výkonností generování odkazů

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Acci
Člen | 83
+
0
-

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ě?

Acci
Člen | 83
+
0
-

Díky moc za odkaz, takže to není jen můj problém, ale problém nacházející se v Nette.

Tharos
Člen | 1030
+
0
-

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)

Acci
Člen | 83
+
0
-

Taky už jsem si na to napsal keš v BasePresenteru, ale je pravda že to není vůbec čisté řešení, protože toto by měl řešit přímo framework. Generovat totiž kolem 300 odkazů podle mne totiž není vůbec nic výjimečného, spíše naopak.

h4kuna
Backer | 740
+
0
-

je pravda ze kdyz je link bez parametru tak by mohl byt automaticky kesovany (plus moznost vypnout kesovani) a u ostatnich dat volbu, kesovat ci nikoliv

mkoubik
Člen | 728
+
0
-

Proč be to měl řešit framework? Vždyť je to přetížení jedné metody v BasePresenteru (od toho ostatně je) a standardní je nekešovat nic.

h4kuna
Backer | 740
+
0
-

mkoubik napsal(a):

standardní je nekešovat nic

Tak to beru zpet. To dava smysl

Acci
Člen | 83
+
0
-

Já myslel, že framework je od toho, aby mi práci zjednodušil a aby mi přidělával starosti.

mkoubik napsal(a):
standardní je nekešovat nic

A to si myslíš proč? Naopak standardní je kešovat vše, kde je to potřeba.

Editoval Acci (31. 10. 2010 15:26)

h4kuna
Backer | 740
+
0
-

Acci napsal(a):

A to si myslíš proč? Naopak standardní je kešovat vše, kde je to potřeba.

Ja to pochopil jakoze framework standartne nic nekesuje.

mkoubik
Člen | 728
+
0
-

Špatně jsem se vyjádřil standardně → defaultně.

Ani
Člen | 226
+
0
-

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)

Tharos
Člen | 1030
+
0
-

matata napsal(a):

Ja to pochopil jakoze framework standartne nic nekesuje.

No, třeba RobotLoader (interní záležitost) kešuje.

Editoval Tharos (31. 10. 2010 18:56)

David Grudl
Nette Core | 8142
+
0
-

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;
		}
	}