Panel speed / cache?

sorry if is a numb question.

i need to acelerate de panel, i have 6500 pages with 26000 children (totaly).

can anybody point me in the right direction o give some suggestion? thanks a lot!

What is your page structure like?

TIP: be mindful of how you use the query syntax in blueprints. replace long running queries with custom page methods utilizing a custom cache (using lapse plugin etc).

hi, and thanks. i will investigate it!!

hi bnomei,

my intention is to speed up the panel pages section, i am usign a custom method. the section inisde the panel works, but is the same loading time using or not using Lapse plugin.

i have this code:

class autorizacionesPage extends Kirby\Cms\Page {

public function historial() {
    
    
    $collection = pages('afiliados')
            ->grandChildren()
            ->filterBy('intendedTemplate', 'in', ['autorizacion', 'consulta']);
    

          
$data = Bnomei\Lapse::io(
    $collection, // this will turn into a key taking modification date of all objects into consideration
    function () use ($collection) {
       return [
        
        
        'historiales' => $collection,
        
        
    ];
    }
);


$h = $data['historiales'];

    return $h;
  }


}

gaining performance does not work that way. you have to delay the creation of the pages collection to inside the call to lapse. so if there is no cache or it is expired the collection will be created anew.

<?php

class AutorizacionesPage extends Kirby\Cms\Page {

	public function historial(): Kirby\Cms\Pages
	{
	    
	    // speed up the time to fetch ids from an complex pages tree
		$data = Bnomei\Lapse::io(
		    'AutorizacionesHistorial',
		    function () {
			    $collectionForIds = pages('afiliados')
		            ->grandChildren()
		            ->filterBy('intendedTemplate', 'in', ['autorizacion', 'consulta']);

		             return [
		        	'historiales' => $collectionForIds, 
		    	     ];
	    	        }
			, 1 // expire in minutes. adjust to your needs.
		);

		// what exactly did this code save you?
		// probably not much.
		// your gain in performance mostly depends on how 
		// many files have be skipped when using the cache.

		// kirby is lazy loading data required when crawling
		// the file tree. it is NOT reading the content files that
		// do not match your template filter.
		// if you would do more complex stuff or modified checks
		// you would gain more.

		return $data['historiales'];
	}
}

i think lapse should be doing fine with serialization of the pages object but i have not tested that recently but i will.

if it does not work consider just storing the ids and rebuilding the collection yourself.

<?php

class AutorizacionesPage extends Kirby\Cms\Page {

	public function historial(): Kirby\Cms\Pages
	{
		$data = Bnomei\Lapse::io(
		    'AutorizacionesHistorial',
		    function () {
			    $collectionForIds = pages('afiliados')
		            ->grandChildren()
		            ->filterBy('intendedTemplate', 'in', ['autorizacion', 'consulta']);

		        return [
		        	'historiales' => $collectionForIds->keys(), // for pages: key == id 
		    	];
	    	}
			, 1 // expire in minutes. adjust to your needs.
		);
		
		// new pages collection
		$collection = new Pages(
			array_map(function($id) {
				return page($id); // get page foreach id
			}, $data['historiales'])
		);

		return $collection;
	}
}

@diezmilseres serialization does NOT work out-of-the-box. you need to recreate the pages collection yourself. but since kirby is clever enough to do that from an array of ids the code from above can be made shorter see <!--------.

<?php

class AutorizacionesPage extends Kirby\Cms\Page {

	public function historial(): Kirby\Cms\Pages
	{
		$data = Bnomei\Lapse::io(
		    'AutorizacionesHistorial',
		    function () {
			    $collectionForIds = pages('afiliados')
		            ->grandChildren()
		            ->filterBy('intendedTemplate', 'in', ['autorizacion', 'consulta']);

		        return $collectionForIds->keys(); // for pages: key == id  <!--------

	    	}
			, 1 // expire in minutes. adjust to your needs.
		);
		
		// new pages collection from array of ids <!--------
		return new Pages($data);
	}
}

hi again BNOMEI,

can you explain me how sqlite, virtualpages and lapse plugin can work together? i am lost on this subject.

thank again!

thats a broad subject. what exactly are you stuck at?

i am usign:

1.sqlite database with virtual page model
2.my table has 20000 row with 50 columns
3.i need to list all pages on a section on the panel

when i cache the databse array to file system i have terrible performance…

class DBautorizacionesPage extends Kirby\Cms\Page
{




    public function children()
    {

        $dbchildren = [];
        $afCache = kirby()->cache('af');
        $afData  = $afCache->get('afData');

        if(empty($afData)){

          $dba = Db::select('autorizaciones', '*', 'id IS NOT NULL');

          foreach ($dba->limit(200) as $autorizacion) {

              $dbchildren[] = [
                  'slug'     => $autorizacion->slug(),
                  'num'      => $autorizacion->status() === 'listed' ? 0 : null,
                  'template' => 'dbautorizacion',
                  'model'    => 'dbautorizacion',
                  'content'  => [
                    'title'  => $autorizacion->id(),
                    'status' => is_null($autorizacion->status()) ? 'unlisted' : $autorizacion->status(),
                    'fecha' => $autorizacion->fecha(),
                    'nro_afiliado' => $autorizacion->nro_afiliado(),
                    'fecha_emision' => $autorizacion->fecha_emision(),
                    'fecha_recepcion' => $autorizacion->fecha_recepcion(),
                    'prestador' => $autorizacion->prestador(),
                    'coseguro' => $autorizacion->coseguro(),
                    'orden1toggle' => $autorizacion->orden1toggle(),
                    'orden1mensaje' => $autorizacion->orden1mensaje(),
                    'orden1codigo' => $autorizacion->orden1codigo(),
                    'orden1descripcion' => $autorizacion->orden1descripcion(),
                    'orden1nomenclador' => $autorizacion->orden1nomenclador(),
                    'orden2toggle' => $autorizacion->orden2toggle(),
                    'orden2mensaje' => $autorizacion->orden2mensaje(),
                    'orden2codigo' => $autorizacion->orden2codigo(),
                    'orden2descripcion' => $autorizacion->orden2descripcion(),
                    'orden2nomenclador' => $autorizacion->orden2nomenclador(),
                    'orden3toggle' => $autorizacion->orden3toggle(),
                    'orden3mensaje' => $autorizacion->orden3mensaje(),
                    'orden3codigo' => $autorizacion->orden3codigo(),
                    'orden3descripcion' => $autorizacion->orden3descripcion(),
                    'orden3nomenclador' => $autorizacion->orden3nomenclador(),
                    'orden4toggle' => $autorizacion->orden4toggle(),
                    'orden4mensaje' => $autorizacion->orden4mensaje(),
                    'orden4codigo' => $autorizacion->orden4codigo(),
                    'orden4descripcion' => $autorizacion->orden4descripcion(),
                    'orden4nomenclador' => $autorizacion->orden4nomenclador(),
                    'orden5toggle' => $autorizacion->orden5toggle(),
                    'orden5mensaje' => $autorizacion->orden5mensaje(),
                    'orden5codigo' => $autorizacion->orden5codigo(),
                    'orden5descripcion' => $autorizacion->orden5descripcion(),
                    'orden5nomenclador' => $autorizacion->orden5nomenclador(),
                    'orden6toggle' => $autorizacion->orden6toggle(),
                    'orden6mensaje' => $autorizacion->orden6mensaje(),
                    'orden6codigo' => $autorizacion->orden6codigo(),
                    'orden6descripcion' => $autorizacion->orden6descripcion(),
                    'orden6nomenclador' => $autorizacion->orden6nomenclador(),
                    'diagnostico' => $autorizacion->diagnostico(),
                    'observaciones' => $autorizacion->obsevaciones(),
                    'informe' => $autorizacion->informe(),
                    'creado' => $autorizacion->creado(),
                    'nota_interna' => $autorizacion->nota_interna(),
                    'mensajeria' => $autorizacion->mensajeria(),
                    'pdf' => $autorizacion->pdf(),


                  ]
              ];
          }


          $dbc = Db::select('consultas', '*', 'id IS NOT NULL');

          foreach ($dbc->limit(200) as $consulta) {

              $dbchildren[] = [
                  'slug'     => $consulta->slug(),
                  'num'      => $consulta->status() === 'listed' ? 0 : null,
                  'template' => 'dbconsulta',
                  'model'    => 'dbconsulta',
                  'content'  => [
                    'title'  => $consulta->title() ?? 'Nueva consulta',
                    'status' => is_null($consulta->status()) ? 'unlisted' : $consulta->status(),
                    'fecha' => $consulta->fecha(),
                    'creado' => $consulta->creado(),
                    'observaciones' => $consulta->obsevaciones(),
                    'localidad' => $consulta->localidad(),
                    'especialidad' => $consulta->especialidad(),
                    'profesional' => $consulta->profesional(),
                    'diagnostico' => $consulta->diagnostico(),
                    'prestador' => $consulta->prestador(),
                    'nro_afiliado' => $consulta->nro_afiliado(),


                  ]
              ];
          }


          $dbm = Db::select('memos', '*', 'id IS NOT NULL');

          foreach ($dbm->limit(200) as $memo) {

              $dbchildren[] = [
                  'slug'     => $memo->slug(),
                  'num'      => $memo->status() === 'listed' ? 0 : null,
                  'template' => 'dbmemo',
                  'model'    => 'dbmemo',
                  'content'  => [
                    'title'  => $memo->title() ?? 'Nuevo memo',
                    'status' => is_null($memo->status()) ? 'unlisted' : $memo->status(),
                    'fecha' => $memo->fecha(),
                    'creado' => $memo->creado(),
                    'observaciones' => $memo->obsevaciones(),
                    'memo' => $memo->notas(),
                    'nro_afiliado' => $memo->nro_afiliado(),


                  ]
              ];
          }


          $afData = $dbchildren;
          $afCache->set('afdata', $afData);


        }


        return Pages::factory($afData, $this);
    }





}

try using something like stopwatch to measure what exactly takes up the cpu time. but my guess is

  • Pages::factory($afData, $this) and of course
  • the panel trying to fetch and (browser tools dev tools, how may kb is the response, how many entries)
  • render the list (not sure how to measure).

i am not sure if pagination does help here. there is no such thing as lazy collections in kirby but maybe @lukasbestle know a trick how to tell Pages::factory that a virtual page has to load the content lazily and how to hook that up (that happens with real page objects afaik).

Hi,

  1. i guess this is the problem
  2. 1.5k, 35000 entries, paginated by 10 entries
  3. it render almost instantly

The Page lazy-loading works by loading the content once the $page->content() method is first called.

So what you @diezmilseres could do is to create a custom page class extending Kirby\Cms\Page that overrides the content() method with your own code that loads the content from the database. In your DBautorizacionesPage::children() method you can then modify the DB queries to only load metadata (slug and status) from the DB.

1 Like