Script braucht zu lange habe es nur geschafft von 9 sec auf 5 sec zu reduzieren

splasch

Erfahrenes Mitglied
Ich schreib momentan einen Map Editor für eine Broswergame (entwickler tool)

Hab ihr eine Idee wie man das Script noch schneller machen kann Momentan dauert der Seiten aufbau Lokal ca 5 Sekunden.
Dabei werden 667 Datensätze eingelesen und ausgeben.Mitterweilen hab ich rausgefunden das die While schleife wesendlich schneller ist als die For (mit For ca 9sek)

PHP:
<?
// Daten aus der Db einlesen
$Sql_allmap="Select F_artid,Weg,H,V from map1 "; 
$db->query($Sql_allmap);

while ($db->next_record()) {
	$Mh[]=$db->r("H");
	$Mv[]=$db->r("V");
	$Mweg[]=$db->r("Weg");
	$Mf_artid[]=$db->r("F_artid");
	$daten++; // Zählt die Datensätze
}	


// Hier erfolgt die Schleife die das ganze verzögert $V ist die vertikale spalte je nach Map größe momentan 50 und $H die Horenzentale auch momenatn bei 50
<? while($coV < $V){
	$coV++; ?>	
<tr>
  <? while($count < $H){
	$count++; ?>
<form id="Feld<?=$coV."-".$count;?>" action="<? echo $_SERVER['PHP_SELF']; ?>" method="post" >		
<?
		$i='0'; $Gefunden='';//zurücksetzen
		while ($i <= $daten or $Gefunden=='5'){
		  if ($Mv[$i]==$coV and $Mh[$i]==$count){
			$Gefunden='5';	
			break; 
			} // ende if
			$i++; } // ende while
			
			
		if($Mweg[$i]=='n'){$Farbe='gray';	}
		elseif($Mweg[$i]=='j'){$Farbe='yellow';	}
		else{$Farbe="";}
			
		?>		
		<td width="15" height="15" bgcolor="<?=$Farbe;?>" style=" font-size:9">
		<INPUT class="input" type="hidden" name="neu" value="<?=$wg;?>" >	
		<INPUT class="input" type="hidden" name="Kordinaten" value="<?=$coV.'-'.$count;?>" >
		<a href="javascript:document.getElementById('Feld<?=$coV.'-'.$count;;?>').submit();"> <?=$Mf_artid[$i].str_repeat('&nbsp;',5);?></a>
		</td>
		</form>
		<? };$count=0;   ?>
		
	</tr>
<? } ?>
 
Zuletzt bearbeitet:
Dass das while-Konstrukt schneller ist, liegt in deinem Fall wahrscheinlich an der Implementierung. Denn meiner Erfahrung nach ist ein for-Konstrukt schneller. Aber das hängt wie bereits gesagt vor allem von der Implementierung ab.

Probier mal Folgendes:
PHP:
$query = '
	SELECT
	        `F_artid`,
	        `Weg`,
	        `H`,
	        `V`
	  FROM
	        `map1`
	  ORDER BY
	        `H`,
	        `V`
	';
$db->query($query);

$fetch = true;
for( $coordX=0; $coordX<$V; $coordX++ ) {
	echo '<tr>';
	for( $coordY=0; $coordY<$H; $coordY++ ) {
		if( $fetch ) {
			$record = $db->next_record();
			$fetch = false;
		}
		if( $record['H'] == $coordY && $record['V'] == $coordX ) {
			echo '<td style="color:' . ($record['Weg'] === 'j' ? 'yellow' : 'gray') . '">';
			echo '<form id="Feld'.$coordX.'-'.$coordY.'" action="'.$_SERVER['PHP_SELF'].'" method="post" onclick="this.submit()">';
			echo '<INPUT class="input" type="hidden" name="neu" value="'.$wg.'">';
			echo '<INPUT class="input" type="hidden" name="Kordinaten" value="'.$coordX.'-'.$coordY.'">';
			echo $record['F_artid'].str_repeat('&nbsp;', 5);
			echo '</form>';
			$fetch = true;
		} else {
			echo '<td>';
		}
		echo '</td>';
	}
	echo '</tr>';
}
 
Danke

Der Oder by teil hat 0,66 sekunden mehr gebracht also schneller.
Den anderen Teil muß ich erst Testen bwz das Script anpassen. ich geb nacher dann Bescheid.

Mfg Splasch
 
Was meinst du, wer sich eine Ausgabe mit 670 Zeilen am Bildschirm ankuckt

Also klar, vielleicht kannst du das noch schneller machen (btw versuch das asynchron mit JS nachzuladen - dann wartet man nicht so lang auf die erste Ausgabe) aber direkt schick wird das IMO nicht werden.

Eine vernünftiger Filter sollte da doch die bessere Variante sein, oder?

Dirk
 
Was meinst du, wer sich eine Ausgabe mit 670 Zeilen am Bildschirm ankuckt

Wer genau liest ist klar Vorteill ES IST EIN ENTWICKLER TOOL (EDITOR) UM EINE MAP IN EINEM BROSWER GAME ZU ERSTELLEN.(Die Map selbst wird später von einen anderen Script angezeigt das läuft auch schnell)

Keines was der Enduser je sehen wird ;)

Bin noch dabei dein gepostet Code anzupassen. Die X Y position wurde vertauscht.Dazu sollen auch leere Felder angezeigt werden (editor).Daher muß er bei jeden feld alle Datensätze abfragen bis was gefunden wird (nicht nur einen pro Td) ausser man sendet immer einen neuen Sql befehlt mit where V='' anh H=''.
Sobald ich das angepasst hab und es Fehlerfrei läuft geb ich bescheid obs schneller oder langsamer ist.

Mfg Splasch
 
Daher muß er bei jeden feld alle Datensätze abfragen bis was gefunden wird (nicht nur einen pro Td) ausser man sendet immer einen neuen Sql befehlt mit where V='' anh H=''.
Ich habe den Algorithmus doch gerade geändert, damit eben nicht jedes Mal alle Datensätze durchlaufen werden müssen. Deswegen werden doch die Datensätze bereits anhand ihrer in der Tabelle auftretenden Position sortiert, sodass der nächste Datensatz der Ergebnismenge auch der nächste Datensatz ist, der in der Tabelle ausgegeben werden soll.

Verbesserte Version:
PHP:
$fetch = true;
for( $coordY=0; $coordY<$H; $coordY++ ) {
	echo '<tr>';
	for( $coordX=0; $coordX<$V; $coordX++ ) {
		if( $fetch ) {
			$record = $db->next_record();
			$fetch = false;
		}
		if( $record['H'] == $coordY && $record['V'] == $coordX ) {
			echo '<td style="color:' . ($record['Weg'] === 'j' ? 'yellow' : 'gray') . '">';
			echo '<form id="Feld'.$coordX.'-'.$coordY.'" action="'.$_SERVER['PHP_SELF'].'" method="post" onclick="this.submit()">';
			echo '<INPUT class="input" type="hidden" name="neu" value="'.$wg.'">';
			echo '<INPUT class="input" type="hidden" name="Kordinaten" value="'.$coordX.'-'.$coordY.'">';
			echo $record['F_artid'].str_repeat('&nbsp;', 5);
			echo '</form>';
			$fetch = true;
		} else {
			echo '<td>'.str_repeat('&nbsp;', 5);
		}
		echo '</td>';
	}
	echo '</tr>';
}
 
Ich habe den Algorithmus doch gerade geändert, damit eben nicht jedes Mal alle Datensätze durchlaufen werden müssen. Deswegen werden doch die Datensätze bereits anhand ihrer in der Tabelle auftretenden Position sortiert, sodass der nächste Datensatz der Ergebnismenge auch der nächste Datensatz ist, der in der Tabelle ausgegeben werden soll.

Hi habe deine Methode gestern getest und dabei festgestellt das next_record(); immer wieder von vorne anfängt also nur immer den 1 Datensatzt ausliest und so die Tabele nicht richtig aufbaut.

Weiter hab ich raus gefunden das bei php while schleifen zu 60% schneller sind als for einen bericht im netz zufolge http://lists.phpbar.de/archive/php_infosoc1/msg01935.html

Auch bei mir im Test war while schneller.

Ich konnte das ganze noch etwas verschnellern und habs momentan so gelöst:

sql sortieren nach v h // Wichitg zuerst V dann H Vertikal wegen der späteren abfrage
alle Daten sätze ins Array ablegen // ist schneller als jedes mal die Db zu kontaktieren

Dadurch das nun sortiert ist zufolge der arry[0] werd auch der kleinste daher
beginnt er erst die Schleife wenn arry[0] kleiner oder gleich der Zeile V ist (vertikal)
Dadürch läuft er nicht mehr die schleifen durch wo keine werte in der Db sind.
Stellt dafür aber ein leere Formula feld zu verfügung mit der Aktuellen position (das ist gewohlt damit man nur drauf klicken braucht später beim erstellen der Map)

Im besten fall hab ich damit ca 2 sekunden aufbau geschaff aber es schwank nun zwischen 2 sekunden und 5 sekunden warscheinlich je nach cpu auslastung.

Das ganze sieht nun so im Code aus:

PHP:
<?
include_once ("../inc/db.php");
$db = new db($fehler);

$V=(integer)($_POST['V']); 
$H=(integer)($_POST['H']); 

$count = 0;
$coV = 0;
//echo $count;
$Kord=($_POST['Kordinaten']);
$neu=($_POST['neu']); // weg n j
$Art=($_POST['Art']); // hinderniss oder weg
$Bild=($_POST['Bild']);// Grafik id
echo "Bild ".$Bild;
echo " Art ".$Art;

echo " ".$Kord.$neu;
$Kor = explode("-", $Kord);
echo "v".$Kor[0];
echo "h".$Kor[1]."<br>";

if ($neu !="" and $Kor[0] !="" and $Kor[1] !=""){
	//update
$Sqlup=sprintf("Update map1 set F_artid='%d',Weg='%s' where H='%d' and V='%d'ORDER BY `H`,`V`;",($Bild),($Art),($Kor[1] ),($Kor[0]));
echo $Sqlup;
$db->query($Sqlup);	
}
if ($neu =="" and $Kor[0] !="" and $Kor[1] !=""){
	//insert
$Sqlstr=sprintf("INSERT INTO `map1` (`H`, `V`, `F_artid`, `Weg`) VALUES (%d, %d, %d, '%s');",($Kor[1] ),($Kor[0]),($Bild),($Art));
echo $Sqlstr;
$db->query($Sqlstr);
}

$Sql_bild="Select Mapgrafik_id,Grafik_art from map_grafik "; // Grafik art laden

unset($Mh);unset($Mv);unset($Mweg);unset($Mf_artid); //Dim Var löschen
$Sql_allmap="Select V,H,F_artid,Weg from map1 order by V,H"; 
$db->query($Sql_allmap);

while ($db->next_record()) {
	$Mv[]=$db->r("V");
	$Mh[]=$db->r("H");
	$Mweg[]=$db->r("Weg");
	$Mf_artid[]=$db->r("F_artid");
	$daten++;
}	

echo "Test".$daten;
?>
<html>
<body>
<style type="text/css">
<!--
a:link {text-decoration:none; }
a:visited {text-decoration:none; }
a:hover {text-decoration:none;}
a:active{text-decoration:none;}	
-->
</style>

<table cellspacing="5" cellpadding="0" border =0>
	<tr>
		<td>
<form action="<? echo $_SERVER['PHP_SELF']; ?>" method="post" >	
<table cellspacing="0" cellpadding="0">
	<tr>
		<td>V
			<INPUT type="text" size=2 name="V" value=""/>
			/
			<INPUT type="text" size=2 name="H" value=""/>H			
		</td>
		<td>
			<input style="border:none;background:none" type=submit name="Button" value="Erstellen" />	
		</td>
	</tr>
</table>	
</form>	
		</td>
		<td>
<form action="<? echo $_SERVER['PHP_SELF']; ?>" method="post" >	
<table cellspacing="0" cellpadding="0">
	<tr>
		<td>
			<select name="Bild" size="1">
				<? $db->query($Sql_bild);
					while ($db->next_record()) { ?>
					<option  value="<?=$db->r("Mapgrafik_id");?>"><?=$db->r("Grafik_art");?></option>
        <? } ?>
    	</select>

		</td>	
		<td>
			<? if($Art=='j'){$c1="checked";}
				 if($Art=='n'){$c2="checked";}	?>
			<input name="Art" type="radio" value="n" <?=$c2;?> >Hindernis	
			<input name="Art" type="radio" value="j" <?=$c1;?> >Weg	
		</td>
		<td>
			<INPUT class="input" type="hidden" name="V" value="<?=$V;?>" >
			<INPUT class="input" type="hidden" name="H" value="<?=$H;?>" >	
			<input style="border:none;background:none" type=submit name="Button" value="Wählen" />	
		</td>
	</tr>
</table>			
</form>
		</td>
		<td>
<form action="<? echo $_SERVER['PHP_SELF']; ?>" method="post" >	
<table cellspacing="0" cellpadding="0">
	<tr>
		<td>
			<select name="Map" size="1">
				<option>Map1</option>
      	<option>Map2</option>
    	</select>
		</td>		
		<td>
			<INPUT class="input" type="hidden" name="V" value="<?=$V;?>" >
			<INPUT class="input" type="hidden" name="H" value="<?=$H;?>" >	
			<input style="border:none;background:none" type=submit name="Button" value="Laden" />
		</td>	
	</tr>
</table>
</form>	
		</td>			
	</tr>
</table>
<table cellspacing="0" cellpadding="0" align="center" border=1>
	<? while($coV < $V){
				$coV++; ?>	
	<tr>
		<? while($count < $H){
				$count++; ?>
		<form id="Feld<?=$coV."-".$count;?>" action="<? echo $_SERVER['PHP_SELF']; ?>" method="post" >		
<?
	
		 $i=0;
		 $Gefunden='';//zurücksetzen
		while ($Mv[$i] <= $coV){
			//echo"I".$i." Cov".$coV." Mv".$Mv[$i]." "." Mh".$Mh[$i]." H".$count." ";
			if ($i > $daten) break; 
			if ($Mv[$i]==$coV and $Mh[$i]==$count){
			$Gefunden='True';	
					break; 
			}
			$i++; }
				
			
		if($Gefunden=='True' and $Mweg[$i]=='n'){$Farbe='gray';	}
		elseif($Gefunden=='True' and $Mweg[$i]=='j'){$Farbe='yellow';	}
		else{$Farbe="";}
		
		if($Gefunden=='True')	{$ausgabe=$Mf_artid[$i];
			//array verkleinern
			unset($Mv[$i]);unset($Mh[$i]);unset($Mf_artid[$i]);
			//echo "G".$Mv[$i];
			}
		else{$ausgabe="";}
		?>		
		<td width="15" height="15" bgcolor="<?=$Farbe;?>" style=" font-size:9">
		<INPUT class="input" type="hidden" name="Bild" value="<?=$Bild;?>" >
		<INPUT class="input" type="hidden" name="Art" value="<?=$Art;?>" >
		<INPUT class="input" type="hidden" name="V" value="<?=$V;?>" >
		<INPUT class="input" type="hidden" name="H" value="<?=$H;?>" >		
		<INPUT class="input" type="hidden" name="neu" value="<?=$Mweg[$i];?>" >	
		<INPUT class="input" type="hidden" name="Kordinaten" value="<?=$coV.'-'.$count;?>" >
		<a href="javascript:document.getElementById('Feld<?=$coV.'-'.$count;;?>').submit();"> <?=$ausgabe.str_repeat('&nbsp;',5);?></a>
		</td>
		</form>
		<? };$count=0;   ?>
		
	</tr>
<? } ?>
	
		
<table>


Wie gesagt es ist gewohlt das ein leers Feld formula auch erstellt wird nicht nur wie in deinem bsp ein leere td tag bwz tr
 
Zuletzt bearbeitet:
Sind die sortierten Daten erst einmal in einem Array gespeichert, dauert mein Algorithmus gerade mal 0,0016 Sekunden.
PHP:
$H = 50;
$V = 50;
$records = array(
	array(
		'H'       => 1,
		'V'       => 1,
		'Weg'     => 'foo',
		'F_artid' => 'bar',
	),
	array(
		'H'       => 1,
		'V'       => 2,
		'Weg'     => 'foo',
		'F_artid' => 'bar',
	),
	array(
		'H'       => 10,
		'V'       => 10,
		'Weg'     => 'foo',
		'F_artid' => 'bar',
	),
	array(
		'H'       => 10,
		'V'       => 12,
		'Weg'     => 'foo',
		'F_artid' => 'bar',
	),
);
$wg = 'wg';

$start = microtime(true);

$fetch = true;
echo '<table border="1">';
for( $coordY=0; $coordY<$H; $coordY++ ) {
	echo '<tr>';
	for( $coordX=0; $coordX<$V; $coordX++ ) {
		if( $fetch ) {
			$record = array_shift($records);
			$fetch = false;
		}
		if( $record['H'] == $coordY && $record['V'] == $coordX ) {
			echo '<td style="color:' . ($record['Weg'] === 'j' ? 'yellow' : 'gray') . '">';
			echo '<form id="Feld'.$coordX.'-'.$coordY.'" action="'.$_SERVER['PHP_SELF'].'" method="post" onclick="this.submit()">';
			echo '<INPUT class="input" type="hidden" name="neu" value="'.$wg.'">';
			echo '<INPUT class="input" type="hidden" name="Kordinaten" value="'.$coordX.'-'.$coordY.'">';
			echo $record['F_artid'];
			echo '</form>';
			$fetch = true;
		} else {
			echo '<td>';
		}
		echo '</td>';
	}
	echo '</tr>';
}
echo '</table>';

echo '<p>'.(microtime(true)-$start).'</p>';
Wenn du möchtest, kannst du diesen immer noch auf while-Kontrollkonstrukte umstellen.

Formatieren kannst du die Tabelle übrigens später besser mit CSS.
 
Du hast dabei was übersehen.Du baust nur die werte in der array auf in der Tabelle.
Zudem ist klar je mehr daten im Array sind um so langsamer geht es.

Kurze Zusammenfassung es wird ein Gittermuster 50 *50 aufgebaut unabhängig ob die nun gefüllt sind oder nicht.
Von diesen Mustervorlage werden nun die daten aus dem Array eingetragen.

Du trägst dagen nur die Daten aus dem array ein.Was dazu führt das es eine Map vorschau wird aber kein Editor der einen neue Map erstellen kann.

Setzt ich die Map kleiner gehts bei mir auch schneller Logisch wenn die Map nur 10*10 groß ist ergibt 100 Felder.

Mein Beispiel bezieht sich aber auch eine Map 50*50 ergibt 2500 felder davon gerade mal 690 felder im Array stehen.Nun gilt es dieses Array in die Map 50*50 einzutragen.
Wenn ich das mit 5 oder 10 Daten mach geht das auch bei mir sau schnell.

;)

Hier mal einen screen von einer leeren Map damit man sich das besser vorstellen kann.
Die ist 25*25 groß also 625 felder
http://kabon.kilu2.de/Game/Disign/Bilder/Vorschau/Editor.gif
 
Zuletzt bearbeitet:
Selbst wenn für jede Zelle ein Datensatz existiert, dauert das Ganze immer noch schneller. Denn es muss nicht jedes Mal das Array der Datensätze nach dem passenden Datensatz durchsucht werden, da das jeweils erste Element immer das nächste ist, das auch ausgegeben werden muss.

Ich hab’s jetzt sogar auf 0,018 Sekunden reduzieren können:
PHP:
$H = 50;
$V = 50;
$wg = 'wg';
$template = <<<HTML
<td style="color:%s"><form id="Feld%s" action="{$_SERVER['PHP_SELF']}" method="post" onclick="this.submit()"><INPUT class="input" type="hidden" name="neu" value="{$wg}"><INPUT class="input" type="hidden" name="Kordinaten" value="%s">%s</form></td>
HTML;


// Beispieldaten werden generiert

$start = microtime(true);

$records = array();
for( $i=0; $i<$H; $i++ ) {
	for( $j=0; $j<$V; $j++ ) {
		$records[] = array(
			'H'       => $i,
			'V'       => $j,
			'Weg'     => 'foo',
			'F_artid' => substr(md5(rand()), 0, 3),
		);
	}
}

echo '<p>Beispieldaten generieren: '.(microtime(true)-$start).' Sekunden</p>';


// Spielfeld wird generiert

$start = microtime(true);

$fetch = true;
$i = 0;
echo '<table border="1">';
for( $coordY=0; $coordY<$H; $coordY++ ) {
	echo '<tr>';
	for( $coordX=0; $coordX<$V; $coordX++ ) {
		if( $fetch ) {
			$record = $records[$i++];
			$fetch = false;
		}
		if( $record['H'] == $coordY && $record['V'] == $coordX ) {
			printf(
				$template,
				($record['Weg'] === 'j' ? 'yellow' : 'gray'),
				$coordX.'-'.$coordY,
				$coordX.'-'.$coordY,
				$record['F_artid']
			);
			$fetch = true;
		} else {
			echo '<td></td>';
		}
	}
	echo '</tr>';
}
echo '</table>';

echo '<p>Spielfeld generieren: '.(microtime(true)-$start).' Sekunden</p>';
 
Zurück