Jde cachovat vytváření requestů?
- ZahorskyJan
- Člen | 59
Řeším optimalizaci aplikace a blackfire mi jako jedno ze slabých míst ukazuje volání createRequest. Jedná se o eshop, takže odkazů je na stránce dost.
Chtěl jsem výsledek funkce cachovat, takže jsem udělal override ve svém BasePresenteru, ale problém je, že nejsem schopen z parametrů metody ($component, $destination, array $args, $mode) vygenerovat unikátní cache klíč. Když to nechám na Nette\Caching\Cache, tak dostanu pochopitelnou hlášku: Object serialization is not supported protože obecně objekt typu Component nejde „uspat“.
Neřešil to už někdo? Díky za každý nápad nebo zkušenost.
- ZahorskyJan
- Člen | 59
přikládám ještě blackfire výpisu produktů v kategorii: https://blackfire.io/…d434bb/graph
Když to vezmu podle pořadí % Excl. tak první s čím si myslím, že můžu něco udělat je právě createRequest.
@CZechBoY Nejčastější scénář vytvoření odkazu je, že jedna metoda vytáhne pole produktů, které se má zobrazit. V poli je jejich ID a Slug. Potom vypadá odkaz v latte šabloně takto:
<a href="{link ':Frontend:Catalog:Product:', id=>$item['id'], slug=>$item['slug']}">nazev produktu</a>
Tady je frontend část RouterFactory:
$public[] = new Routers\Route('[<locale=cs cs|sk|en|de>/]kosik', array(
'module' => 'Shopping',
'presenter' => 'Cart',
'action' => 'default',
), $this->httpSecured ? Routers\Route::SECURED : 0);
$public[] = new Routers\Route('[<locale=cs cs|sk|en|de>/]vyhledat/[!<search>]', array(
'module' => 'Catalog',
'presenter' => 'Category',
'action' => 'search',
), $this->httpSecured ? Routers\Route::SECURED : 0);
$public[] = new Routers\Route('[<locale=cs cs|sk|en|de>/]texty/[!<slug>]', array(
'module' => 'Project',
'presenter' => 'StaticText',
'action' => 'default',
), $this->httpSecured ? Routers\Route::SECURED : 0);
$public[] = new Routers\Route('[<locale=cs cs|sk|en|de>/][!<id [0-9]+>]-[!<slug>]', array(
'module' => 'Catalog',
'presenter' => 'Product',
'action' => 'default',
), $this->httpSecured ? Routers\Route::SECURED : 0);
$public[] = new Routers\Route('[<locale=cs cs|sk|en|de>/]c-[!<id [0-9]+>]-[!<slug>]', array(
'module' => 'Catalog',
'presenter' => 'Category',
'action' => 'default',
), $this->httpSecured ? Routers\Route::SECURED : 0);
$public[] = new Routers\Route('[<locale=cs cs|sk|en|de>/]chyba', array(
'module' => 'Project',
'presenter' => 'Error',
'action' => 'error404',
), $this->httpSecured ? Routers\Route::SECURED : 0);
// general public route
$public[] = new Routers\Route('[<locale=cs cs|sk|en|de>/][<module>[/<presenter>[/<action>[/<id>]]]]', array(
'module' => 'Project',
'presenter' => 'Homepage',
'action'=> 'default',
), $this->httpSecured ? Routers\Route::SECURED : 0);
$router[] = $public;
@JanTvrdík odkazů je na stránce cca 400, v profilování je počet volání createRequest menší protože mám něco cachované na úrovni latte šablony
- Jan Tvrdík
- Nette guru | 2595
Nejjednodušší hotfix je něco jako
{capture $linkTemplate}{link ':Frontend:Catalog:Product:', id => 999, slug => abc}{/capture}
{foreach $items as $item}
<a href="{$linkTemplate|replace:999:$item[id]|replace:abc:$item[slug]}">nazev produktu</a>
{/foreach}
- ZahorskyJan
- Člen | 59
Jan Tvrdík napsal(a):
Nejjednodušší hotfix je něco jako
{capture $linkTemplate}{link ':Frontend:Catalog:Product:', id => 999, slug => abc}{/capture} {foreach $items as $item} <a href="{$linkTemplate|replace:999:$item[id]|replace:abc:$item[slug]}">nazev produktu</a> {/foreach}
Díky, zkusím. Přivedlo mě to na myšlenku, že bych ten createRequest zkusil naučit, že některé jednoduché a časté odkazy může brát z cache a zbytek provede standardně. Protože v detailu produktu nejsou žádné persistentní parametry a podobné chytré věci, které to komplikují.
- ZahorskyJan
- Člen | 59
Tak aktuálně zkouším tento přepis v BasePresenteru a vypadá to, že plní svůj úkol. Ještě dostanu seznam těch adres někam do konfigurace.
V kombinaci s cache v latte pro výpis kategorií, kde bylo taky hodně odkazů, jsem to stáhl o 34%: https://blackfire.io/…7a3c1b/graph
Díky za nakopnutí!
protected function createRequest($component, $destination, array $args, $mode)
{
$allowedDestinations = [
':Frontend:Catalog:Product:',
':Frontend:Catalog:Category:',
':Frontend:Project:Homepage:',
'toCart!',
];
if ( in_array($destination, $allowedDestinations) )
{
$cacheKey = [$destination, $args, $mode];
return $this->cache->load('createRequest/'.md5(serialize($cacheKey)), function(&$dependencies) use ($component, $destination, $args, $mode) {
$dependencies = [
\Nette\Caching\Cache::TAGS => [
'catalog_products/all',
'catalog_categories/all',
'system',
],
];
return parent::createRequest($component, $destination, $args, $mode);
});
}
else
{
return parent::createRequest($component, $destination, $args, $mode);
}
}