Hjälp mig att optimera min PHP-kod!

Permalänk
Medlem

Hjälp mig att optimera min PHP-kod!

Hej!
Jag har skrivit om ett plugin till wordpress som gör att det är möjligt att hämta ut poster från Google kalender och skriva ut dessa i en kalender på min hemsida. Koden fungerar men den känns lååångt ifrån optimal och sidan är ganska seg, trots att det just nu bara finns fyra event i google-kalendern. Hoppas därför på att någon kan komma med tips på hur jag kan optimera koden för mitt plugin och göra det effektivare! Alla tips och tankar mottages tacksamt.

Här kommer all kod som jag modifierat och grejat med (finns en del metoder som sköter kommunikation med wordpress och dessa har jag inte ändrat något i så har inte med dessa här).

/*Håller info om event*/ class myEvent { public $title; public $fullday; public $startyear; public $startmonth; public $startday; public $starttime; public $endyear; public $endmonth; public $endday; public $endtime; public $location; public $description; } /***Den här metoden hämtar infon från google kalendern. ***/ private function fetch($calId, $count) { $url = $this->getCalendarUrl($calId, $count); $httpData = wp_remote_get($url); if(is_wp_error($httpData) || !is_array($httpData)) { echo 'Simple Google Calendar: ', $httpData->get_error_message(); return false; } $xml = new SimpleXmlElement($httpData['body']); if(!$xml) { return false; } $out = array(); $i = 0; foreach($xml->entry as $e) { $gd = $e->children('http://schemas.google.com/g/2005'); $event = new myEvent(); $when = $gd->when->attributes(); $where = $gd->where->attributes(); $event->title = (string)$e->title; $event->location = (string)$where->valueString; $event->description = (string)$e->content; $event->starttime = (string)$when->startTime; $timestamp = strtotime($when->startTime); $startdate = getdate($timestamp); $event->startyear = $startdate[year]; $event->startmonth = $startdate[mon]; $event->startday = $startdate[mday]; if($startdate[seconds] === 0 && $startdate[hours] === 0 && $startdate[hours] === 0 ){ $event->fullday = true; } else { $event->fullday = false; $event->starttime = date("H:i", $timestamp); } $endtimestamp = strtotime($when->endTime); $enddate = getdate($endtimestamp); $event->endyear = $enddate[year]; $event->endmonth = $enddate[mon]; $event->endday = $enddate[mday]; $event->endtime = date("H:i", $endtimestamp); $tist = strtotime($when->endTime); $d = getdate($tist); //HelperClass::debug_to_console($event); $out[$i] = $event; $i++; } return $out; } /**Den här metoden "hakar i" där widgeten ska skrivas ut och printar ut den. **/ public function widget($args, $instance) { $title = apply_filters('widget_title', $instance['title']); echo $args['before_widget']; if(isset($instance['title'])) { echo $args['before_title'], $instance['title'], $args['after_title']; } $data = $this->getData($instance); //Nedanstående rad gör utskriften. echo $this->draw_calendar(7, 2014, $data); echo $args['after_widget']; } /**Den här funktionen skapar html-koden som behövs för att skriva ut kalendern.**/ function draw_calendar($month, $year, $calendardata){ //Hämtar in de eventsen som finns den här månaden. $events = $this->currentMonthEvents($month, $calendardata); $calendar = '<table class="calendartable">'; $headings = array('Måndag','Tisdag','Onsdag','Torsdag','Fredag','Lördag','Söndag'); $calendar.= '<tr class="calendar-row"><td class="calendar-day-head">'.implode('</td><td class="calendar-day-head">',$headings).'</td></tr>'; /* Räknar ut hur många veckodagar som finns innan den första dagen i månaden, antalet "tomma" dagar i kalendern. */ $running_day = date('w',mktime(0,0,0,$month,0,$year)); /*Antalet dagar i den givna månaden*/ $days_in_month = date('t',mktime(0,0,0,$month,1,$year)); /*Inte helt hundra på vad dessa variabler gör...*/ $days_in_this_week = 1; $day_counter = 0; $dates_array = array(); /* Rad för vecka ett*/ $calendar.= '<tr class="calendar-row">'; /* Skriver tomma kalenderrutor fram till den 1a dagen i månaden. */ for($x = 0; $x < $running_day; $x++): $calendar.= '<td class="calendar-day-np"> </td>'; $days_in_this_week++; endfor; /* Fortsätter rita upp tabellceller för varje dag i månaden.*/ for($list_day = 1; $list_day <= $days_in_month; $list_day++): $calendar.= '<td class="calendar-day">'; /* Lägger in datumen i rutan */ $calendar.= '<div class="day-number">'.$list_day.'</div>'; /*Här tror jag mkt prestanda går åt - för varje dag går vi igenom eventen för att se om det är något event som ska skrivas ut den dagen. Om det finns - printa ut titeln på eventet bredvid datumet. */ foreach($events as $event) { if($event->startday == $list_day) { $calendar.= $event->title; } } //Inte helt hundra på den här heller... $calendar.= '</td>'; if($running_day == 6): $calendar.= '</tr>'; if(($day_counter+1) != $days_in_month): $calendar.= '<tr class="calendar-row">'; endif; $running_day = -1; $days_in_this_week = 0; endif; $days_in_this_week++; $running_day++; $day_counter++; endfor; /* Tomma dagar från den sista dagen i månaden till sista veckodagen på kalendern */ if($days_in_this_week < 8): for($x = 1; $x <= (8 - $days_in_this_week); $x++): $calendar.= '<td class="calendar-day-np"> </td>'; endfor; endif; $calendar.= '</tr>'; $calendar.= '</table>'; return $calendar; } function currentMonthEvents($currentmonth, $listofevents) { $eventsthismonth = array(); foreach($listofevents as $event) { if($currentmonth == $event->startmonth) { $eventsthismonth[] = $event; } } return $eventsthismonth; } }

Permalänk
Hedersmedlem

Steg 1 är att lista ut vad det är som tar tid: How can I measure the speed of code written in php? [SO].

Generella anmärkningar på kodstil snarare än prestanda i övrigt (innan du mätt och hittat vad det är som uppfattas långsamt så är det ofta onödigt att titta djupare på övriga delar):

  • "sats{…}"- och "sats: … endsats;"-stilarna blandas, vilket är lite märkligt inom en enda klass.

  • `foreach` kan enklare automatiskt skapa en räknare i stället för att själv hålla reda på `$i`:

    $ php -r 'foreach(["a", "b", "c"] as $ordning => $bokstav) echo $ordning." → ".$bokstav."\n";' 0 → a 1 → b 2 → c

  • Att förinitialisera en vektor med noll element och sedan låta den dynamiskt växa kan i vissa sammanhang vara betydligt långsammare än att antingen förinitialisera vektorn med rätt längd, eller i lägen som detta använda något liknande array_map() på invektorn och hoppas att exempelvis någon I/O-väntetid går att parallellisera. Jag skulle dock råda att avvakta tills du hittat eventuell flaskhals innan du tittar på det.

Visa signatur

Nu med kortare användarnamn, men fortfarande bedövande långa inlägg.

Permalänk
Medlem
Skrivet av phz:

Steg 1 är att lista ut vad det är som tar tid: How can I measure the speed of code written in php? [SO].

Generella anmärkningar på kodstil snarare än prestanda i övrigt (innan du mätt och hittat vad det är som uppfattas långsamt så är det ofta onödigt att titta djupare på övriga delar):

  • "sats{…}"- och "sats: … endsats;"-stilarna blandas, vilket är lite märkligt inom en enda klass.

  • `foreach` kan enklare automatiskt skapa en räknare i stället för att själv hålla reda på `$i`:

    $ php -r 'foreach(["a", "b", "c"] as $ordning => $bokstav) echo $ordning." → ".$bokstav."\n";' 0 → a 1 → b 2 → c

  • Att förinitialisera en vektor med noll element och sedan låta den dynamiskt växa kan i vissa sammanhang vara betydligt långsammare än att antingen förinitialisera vektorn med rätt längd, eller i lägen som detta använda något liknande array_map() på invektorn och hoppas att exempelvis någon I/O-väntetid går att parallellisera. Jag skulle dock råda att avvakta tills du hittat eventuell flaskhals innan du tittar på det.

Tack för svaret! Det låter som en väldigt smart idé att hitta flaskhalsen innan jag börjar ändra på koden. Intressant tråd på SO, har laddat hem xhprof nu och ska testa det!