» Optimera din kod

Författare: DavidF?
Skapad: 2007-05-12
Version: 1.0.0
Notera: Artikeln fokuserar på att introducera ämnet, inte beskriva det i sin helhet. Innehållet skildrar mina personliga reflektioner över ämnet.

Introduktion

"Målet är största möjliga beräkningskraft med minsta möjliga antalet instuktioner. Färre instuktioner innebär (oftast) att det tar kortare tid för programmet att klara uppgiften." [Wikipedia]

Vad innebär "optimering" i php?

Både php och sql är byggda för att kunna processera information snabbt och friktionsfritt, men varje operation som php utför kräver processorkraft till att utföra sin instruktion.

Eftersom varje operation som utförs i php kräver en viss tid att beräkna, så innebär det att processer som skulle kunna utföra samma uppgift på mindre tid (genom mer "optimal" kod) skapar "rendundanta" beräkningar, till ingen nytta.

Är det viktigt att optimera?

- Ja, och nej.

Vid tung belastning av en server, när php och databasen arbetar på högvarv så kan rendundant kod vara en ren mardröm. Varje sparad milisekund kan göra stor skillnad när den multipliceras med antalet aktiva användare.

Jag skulle nog rekomendera optimering, även vid skapandet av mindre belastade webbsidor, helt enkelt för att rendundant kod anses slarvigt och ofta otympligt.

Ett exempel i SQL

Ett av de vanligare exempel kan vara att man kör fler query's mot databasen än vad som behövs.

Exempel 1.
<?php
include 'dbclass.php';
$sql = 'SELECT value1 FROM _table_ WHERE id=1';
$db->sql_query($sql);
$row = $db->sql_query($sql);

if ($row['value1'] == 'some_value')
{
  $sql = 'SELECT value2 FROM _table_ WHERE id=1';
  $db->sql_query($sql);
  $row = $db->sql_query($sql);
  if ($row['value2'] == 'some_other_value')
  {
    $sql = 'SELECT value3 FROM _table_ WHERE id=1';
    $db->sql_query($sql);
    $row = $db->sql_query($sql);
    echo $row['value3'];
  }
  else
  {
    $sql = 'SELECT value4 FROM _table_ WHERE id=1';
    $db->sql_query($sql);
    $row = $db->sql_query($sql);
    echo $row['value4'];
  }
}
?>

Koden ovan är slarvigt utformad eftersom den utför flera sql queries i onödan.

Här nedan följer kod som utför samma funktion:

Exempel 2.
<?php
include 'dbclass.php';
$sql = 'SELECT value1, value2, value3, value4 FROM _table_ WHERE id=1';
$db->sql_query($sql);
$row = $db->sql_query($sql);

if ($row['value1'] == 'some_value')
  if ($row['value2'] == 'some_other_value')
    echo $row['value3'];
  else
    echo $row['value4'];
?>

Skillnaden ligger i att vi redan i förväg vet vilka värden vi kan tänkas behöva inhämta från databasen och kan samla allt i en och samma query.

Dilemmat

Den tidigare nämnda koden var ganska simpel att påpeka felaktigheterna, vilket det givetvis inte alltid är i dom verkliga situationerna.

Ibland kan det t ex. vara svårt att bedöma i förväg vilken storlek ett värde kan vara. Ifall du kollar på exempel 1 och 2 igen, och antar att 'value4' är en 4mb binär "blob", så är i teorin exempel 1 potentiellt mindre tidskrävande.

Ytterligare varianter av optimering

Ett annat vanligt exempel på rendundant kod är överflödiga kontroller ifall ett värde existerar.

Exempel 3.
<?php
function page_exists($pagename)
{
  $sql = 'SELECT uid FROM _table_ WHERE page_name="'.$pagename.'"';
  $result = $db->sql_query($sql);
  if ($db->sql_numrows($result) > 0)
    return true;
  else
    return false;
}
function page_add_counter($pagename)
{
  if (page_exists($pagename))
    // add counter+1 to record (psuedo)
}
function page_return_counter($pagename)
{
  if (page_exists($pagename))
    // return counter+1 from record (psuedo)
}
?>

I detta exemplet använder vi totalt 4 sql queries. Updatera, hämta och 2x för att kontrollera ifall record existerar.

Exempel 4.
<?php
function page_exists($pagename)
{
  global $page_exists_cache;

  if ($key = array_search(strtolower($page), $page_exists_cache))
    return $page_exists_cache[$key];

  $sql = 'SELECT uid FROM _table_ WHERE page_name="'.$pagename.'"';
  $result = $db->sql_query($sql);

  if ($db->sql_numrows($result) > 0)
    $retval = true;
  else
    $retval = false;

  $page_exists_history[strtolower($page)] = $retval;
  return $retval;
}
function page_add_counter($pagename)
{
  global $counter;
  if (page_exists($pagename))
  {
    // add counter+1 to record (psuedo)
    //$counter = counter+1 (psuedo)
  }
}
function page_return_counter($pagename)
{
  global $counter;
  if (page_exists($pagename))
  {
    if (!isset($counter))
      // return counter+1 from record (psuedo)
    else
      return $counter;
  }
}
?>

I jämförelse mellan exempel 3 och 4 så sparar den informationen om ifall den hittade "sidan" eller inte, och nästa gång en funktion försöker kontrollera ifall sidan existerar eller inte så kontrollerar funktionen page_exists ifall värdet redan har kollats upp eller inte, innan den kör en sql query.

På samma sätt kollar page_return_counter ifall vi scriptet redan beräknat värdet som vi (annars genom databasen) försöker komma åt.

Avslutning

Om optimering är viktig för din del är något som bara du själv kan svara på. Troligen behöver man inte gå till överdrift med det hela, men det är aldrig fel att hålla ögonen öppna efter bättre och smidigare sätt att utföra krångliga och otympliga operationer.

Om du ändrar något på den här sidan, glöm då inte att uppdatera versionsnumret som finns längst upp.

-- DavidF?
Wiki-navigering
Wiki Index
Wiki Artiklar
Wiki Skolan
Wiki Guider
Wiki FAQ
Webbhotell
Domänregistrering
Wiki-sökning
Sök:
Dokumentalternativ
Redigera dokumentet
Visa dokumenthistorien
Senaste wiki-ändringar
Visa ändringarna
Inställningar
Wiki inställningar
Bra att veta
Vad är en Wiki?
Våra förhållningsregler
Trivselregler
Att använda Wikin
Kontakta oss på adressen: info@phpportalen.net
Webbplatsen bygger i grunden på phpBB 2.0.4 © 2001, 2002 phpBB Group

Modifieringar har senare gjorts i systemet av PHPportalen
Sid och logotypdesign skapad av Daren Jularic