Some idea to speedup code

Author Message

Matteo Tomasini

Saturday 24 March 2007 1:52:53 am

I have a page with a Google Map and I want to create content for the script taking it from 2 classes named "Place" and "Insertion". Each insertion is related to a Place and has an enum attribute containing the kind of a place. For each place I have to count the number of times a particular enumvalue appears in all insertions related to it. Then I'd like to print only the three best kinds in witch each palce has been categorized.
This code is very slow, but I don't know how to speed it up, can you help me, please?

{def $places=fetch('content','list',hash(parent_node_id,59))}
{foreach $places as $p1}
	{def $content=concat('<a href=',
                                        $p1.path_identification_string|ezurl(no),
                                        '><b>', $p1.object.data_map.name.data_text,
                                        '</b></a> - ', $p1.creator.name,'<br />') }

	{set $content=concat($content,'<br /><b>Tipologia:</b>')}
	{def $kind_elements=array()}
	{def $kind_elements_count=array()}

	{def $insertions=fetch('content','list',
                                        hash(parent_node_id,$p1.node_id,
					order_by,array('published',true()),class_filter_type, 
                                        "include", class_filter_array, array(17)) ) }
	{foreach $insertions[0].object.data_map.kind.value.enum_list as $enum_element}
	     {set $kind_elements=$kind_elements|append($enum_element.enumelement)}
	     {set $kind_elements_count=$kind_elements_count|append(0)}
	{/foreach}
	
        {foreach $insertions as $insertion}
	    {for 0 to sum(count($kind_elements),-1) as $i}
		{if eq($insertion.object.data_map.kind.value.enumobject_list[0].enumelement,
                        $kind_elements[$i]) }
		    {def $e=$kind_elements_count[$i]}
		    {set $e=sum($e,1)}
	            {set $kind_elements_count=$kind_elements_count|remove($i,1)}
		    {set $kind_elements_count=$kind_elements_count|insert($i,$e)}
		    {undef $e}
		{/if}
	    {/for}
	{/foreach}
	
        {if ge(count($kind_elements),2)}
	    {def $swapped=false()}
	    {do}
		{set $swapped=false()}
		{for 0 to sum(count($kind_elements),-2) as $i }
		    {if lt($kind_elements_count[$i],$kind_elements_count[sum($i,1)]) }
			{def $tmp1=$kind_elements_count[$i]}
			{set $kind_elements_count=$kind_elements_count|remove($i,1)}
			{set $kind_elements_count=
                                             $kind_elements_count|insert($i,$kind_elements_count[$i])}
			{set $kind_elements_count=$kind_elements_count|remove(sum($i,1),1)}
			{set $kind_elements_count=
                                                         $kind_elements_count|insert(sum($i,1),$tmp1)}
			{undef $tmp1}
			{def $tmp1=$kind_elements[$i]}
			{set $kind_elements=$kind_elements|remove($i,1)}
			{set $kind_elements=$kind_elements|insert($i,$kind_elements[$i])}
			{set $kind_elements=$kind_elements|remove(sum($i,1),1)}
			{set $kind_elements=$kind_elements|insert(sum($i,1),$tmp1)}
			{undef $tmp1}
			{set $swapped=true()}
		    {/if}
		{/for}
	    {/do while $swapped }
	    {undef $swapped}
	{/if}

        {for 0 to min(2,sum(count($kind_elements),-1)) as $i}
	    {if gt($kind_elements_count[$i],0)}
		{set $content=concat($content,' ',$kind_elements[$i],
                                                                                  ' (',$kind_elements_count[$i],') ')}
	    {/if}
	{/for}
{*then I pass the $content variable to the function addMarker of the Google Maps*}

kracker (the)

Saturday 24 March 2007 2:32:01 am

@Matteo,

While I am impressed with your first post being so very detailed,
I fear the first thought when I glanced at your first post was ....

Most of this code belongs in php instead of tpl.

In moving the logic (up the chain-o-command) to php (I think) you will the gain motivating performance improvements you seek.

You might want to take a look at using the Wrap Operator extension which can provide a simple flexible way to write a php code which can return results inside of a template using a custom template operator. http://ezpedia.org/wiki/en/ez/wrap_operator

<i>//kracker

Audio Book - Noam Chomsky : Failed States Unabridged</i>

Member since: 2001.07.13 || http://ezpedia.se7enx.com/

Matteo Tomasini

Monday 26 March 2007 1:14:54 am

@kracker

Thanks for the answer! Now it works!

kracker (the)

Monday 26 March 2007 1:25:54 am

@Matteo Tomasini

Your welcome. I'm glad.

Would you be willing to share your solution?
You could simply post it here in the forum.

Respectfully,
//kracker

Member since: 2001.07.13 || http://ezpedia.se7enx.com/

Matteo Tomasini

Monday 26 March 2007 1:44:19 am

This is the code in the template

{def $kinds=array('Bene culturale','Luogo rupestre','Paesaggio/Attrazione naturale','Flora/Fauna')}
{def $places=fetch('content','list',hash(parent_node_id,59))}
{foreach $places as $place}
  {def $content=concat('<a href=',$place.path_identification_string|ezurl(no),' ><b>',$place.object.data_map.name.data_text,'</b></a> - ',$place.creator.name,'<br />')}
  {def $insertions=fetch('content','list',hash(parent_node_id,$place.node_id,
									 order_by,array('published',true()),class_filter_type, "include", class_filter_array, array(17)) ) }
  {set $content=concat($content,'<br /><b>Tipologia:</b>',wrap_user_func('generateMarkerContent', array($kinds,2,$insertions)))}

{*then I pass the $content variable to the function addMarker of the Google Maps*}

The values passed to the 'generateMarkerContent' function represent the list of kinds, the array position of the Selection attribute 'kind' and the list of insertions associated to a place.

This is the 'generateMarkerContent' function

function generateMarkerContent($list,$type,$insertions)
{
	$count=array();
	$allKinds=array();
	foreach($insertions as $insertion) {
	  end($insertion->ContentObject->ContentObjectAttributes);
	  $curr=current($insertion->ContentObject->ContentObjectAttributes);
	  array_push($allKinds,$list[$curr['eng-GB'][$type]->DataText]);
	}
	$count=array_count_values($allKinds);
	arsort($count);
	$str='';
	for ($i=0; $i<3; $i++)
	{
	  $curr=each($count);
	  if (isset($curr['key']))
	    $str=$str . ' ' . $curr['key'] . '(' . $curr['value'] . ')';
	}
	if (count($count)>3)
	  $str=$str . ' ...'
	
	return ($str);
}
?>

it returns a string containing the 3 most rated kinds

Xavier Dutoit

Monday 26 March 2007 3:03:41 pm

Hi,

What was the impact on speed ?

X+

http://www.sydesy.com

Matteo Tomasini

Monday 26 March 2007 11:13:12 pm

@Xavier Dutoit

Before the modification the template processing time was about 8 seconds, now is less than a second. During this time the CPU works at 100% (I have an AMD Athlon 64 3500+). The page has 5 places and about 20 Insertions.
Now I have inserted 9 places with about 50 Insertions and the template time is about 1.8sec, always with the CPU at 100%. I am quite worried about that, with about 100 places and 1000-1500 Insertions what will be the load page time? Have you got some more ideas to improve speed of my page?
Thanks

Xavier Dutoit

Tuesday 27 March 2007 2:47:29 am

Hi,

Assuming places and so on aren't going to change that often, use cache-block around them (with the right keys and update only when a new place is published, no time out). That's still as slow the first time, but much quicker the other times.

Have a look at the documentation.

X+

http://www.sydesy.com

Powered by eZ Publish™ CMS Open Source Web Content Management. Copyright © 1999-2014 eZ Systems AS (except where otherwise noted). All rights reserved.