29
Jun

Profiling mit MySQL

categories Computer, MySQL, Tutorials    

Manchmal begegnet man einer SQL-Abfrage, welche langsamer ist als erwartet. Man weiß genau, alles wurde getan, dass die Tabellen optimiert und sauber indexiert sind. Und dennoch ist die Abfrage zu langsam.

Hier hilft Profiling.

MySQL verfügt über einen eingebauten Profiler, der es ermöglicht, sehr detailliert zu tracen, für welchen Bestandteil einer Abfrage die Datenbank wie lange genau gebraucht hat.

Um den Profiler zu verwenden, geht man wie folgt vor:

(1) Einschalten des Profilers.

Per Default ist der Profiler deaktiviert, daher muss man ihn erst starten.

SET profiling = 1;

(2) Ausführen der eigentlichen Abfrage.

(3) Identifizieren der Abfrage-ID.

SHOW PROFILES;

Dieses Kommando wird in etwa folgendes zeigen:

    Query_ID |  Duration | Query
    ---------+-----------+-----------------------
      ...    | ...       | ...    
       29    | 0.0006200 | SHOW STATUS
       30    | 0.3600000 | SELECT (your query here)
      ...    | ...       | ...

Jetzt weiß man, die Abfrage-ID ist 30.

(4) Profiling der Abfrage.

SHOW PROFILE FOR QUERY 30;   // example 

Dies zeigt die Details der Abfrage.

    Status                          | Duration
    --------------------------------+-------------------
    starting                        | 0.000010
    checking query cache for query  | 0.000078
    Opening tables                  | 0.000051
    System lock                     | 0.000003
    Table lock                      | 0.000008
    init                            | 0.000036
    optimizing                      | 0.000020
    statistics                      | 0.000013
    preparing                       | 0.000015
    Creating tmp table              | 0.000028
    executing                       | 0.000602
    Copying to tmp table            | 0.000176
    Sorting result                  | 0.000043
    Sending data                    | 0.080032
    end                             | 0.000004
    removing tmp table              | 0.000024
    end                             | 0.000006
    query end                       | 0.000003
    freeing items                   | 0.000148
    removing tmp table              | 0.000019
    closing tables                  | 0.000005
    logging slow query              | 0.000003
    cleaning up                     | 0.000004

In diesem Beispiel wurde die meiste Zeit der Abfrage damit verbracht, das Ergebnis an den Client zurückzusenden. Vielleicht sollte man die Ergebnismenge reduzieren, oder ggf. den Query Cache erhöhen. Vielleicht geht man aber auch ganz anders vor, hier sollte man von Fall zu Fall prüfen, was sinnvoll und möglich ist.

Aber dank dem Profiling weiß man nun, wo man suchen muß!

4
Apr

Firebug: Logfunktionen

categories Computer, Tutorials    

Viele Entwickler betrachten Firebug als die Mutter aller Web-Tools. Diese Ansicht ist durchaus begründet, denn Firebug umfassst mächtige Werkzeuge, mit welchen man so ziemlich alles machen kann, was man als Webentwickler so täglich braucht, angefangen von kleineren CSS-Experimenten bishin zum Debuggen von komplexen JScript-Anwendungen sowie dem Profiling von Webseiten.

Was nicht ganz so bekannt ist, man kann sogar über den Firebug aus JScript heraus Debug-Logs generieren.

Beispielsweise gibt…

console.log('Hallo Welt!');

…genau diesen Text in der Konsole aus.

Das kann man noch etwas verfeinern, denn schließlich unterscheidet man Infos, Warnings, Errors und Debugs!

console.debug('Debug');
console.info('Information');
console.warn('Warnung');
console.error('Fehler');

Und auch die Ausgabe von Variablen kommt nicht zu kurz:

var banane = 1.234;
var orange = "Test";
console.log("Mein %a hat den Wert %d", orange, banane);

Ästheten können auch Gruppen bilden, welche in der Konsole sauber dargestellt werden:

console.group('meine Gruppe');
    console.info('Info1');
    console.debug('Was ich wissen wollte...');
console.groupEnd();

Über noch mehr Möglichkeiten dieser Funktionen, wie z.B. Zeitwerte, Stacks u.s.w kann man sich hier auf der Seite von Firebug informieren.

Übrigens:
Die meisten dieser Funktionen sind mittlerweile auch im Debugger des Google Chrome verfügbar!

19
Mär

kreatives WAIT-Kommando für DOS

categories Computer, Tutorials    

Vielleicht standen Sie auch mal vor dieser Thematik: Es gibt keinen direkten Weg, ein einfaches WAIT-Kommando in DOS zu stricken. Während ich an einer Lösung für eine kleine Aufgabe arbeitete, stolperte ich über einen sehr kreativen Weg, dies zu lösen:

PING 1.1.1.1 -n 1 -w 25000 >nul

Ja, genau. Das PING-Kommando kann als WAIT-Alternative verwendet werden!

Ein paar ergänzende Erklärungen:

Natürlich versuche ich immer, WAIT-Operationen in Programmen und Scripts zu vermeiden, aber manchmal hilft es doch, gerade beim Testen. Außerdem ist dies kein sehr exakter Ansatz, hier sollte man also nicht mit einer Atomuhr nachmessen. Dennoch ist dieser kreative Ansatz eine kleine, aber feine Lösung, falls man doch mal um ein WAIT nicht herumkommt…!

28
Sep

Visualisierung von Sortierverfahren

categories Fundstücke, Tutorials    

Die Entwicklung von Sortierverfahren mag zwar für Nicht-Entwickler etwas wie schwarze Magie wirken, ist aber für einen Entwickler Grundwissen.

Eine gute, Coffescript-basierte Seite, welche dieses doch manchmal relativ abstrakte Thema on-thy-fly visualisiert, kann hier gefunden werden:

http://visualsort.appspot.com

23
Mär

Modultests mit PHPUnit

categories Computer, PHP, Tutorials    

Eine kleine private Exkursion in die Tiefen einer OpenSource-Gemeinde hat mir mal wieder vor Augen gehalten, wie man sich das Coder-Dasein durch die Verwendung von Modultests („UnitTests“) vereinfachen kann. Nicht jeder benutzt sie, jeder sollte. In der PHP-Programmierung ist die ideale Software hierfür PHPUnit.

Die Software wird im GitHub verteilt, ist gut dokumentiert, weit verbreitet (guckt mal in viele größere Klassen rein, man stolpert oft über den einen oder anderen Testordner) und genießt hohes Ansehen bei Entwicklern. Die Software ist auch im PEAR und kann darüber installiert werden (ein paar Dependencies gibt es für zusätzliche Funktionen).

An einem einfachen Beispiel möchte ich die grundsätzliche Verfahrensweise demonstrieren. Angenommen, in einem PHP-Projekt gibt es irgendwo eine Funktion, welche den Ostersonntag eines Jahres bestimmt. Der Einfachheit halber nennen wir sie easter($jahr). So eine Funktion könnte beispielsweise eingebunden sein, wenn es um die Errechnung von verschiedenen Feiertage geht – somit könnte sie eine gewisse Kritikalität im Projekt innehaben. Wie testet man nun so eine Funktion mit PHPUnit?

Ich steige hier mal mitten in PHPUnit ein:

require_once 'includes/functions.php';
 
class EasterTest extends PHPUnit_Framework_TestCase {
  public function testEasterOk() {
    $easter2011 = easter(2011);
    $this->assertEquals($easter2011, gmmktime(0,0,0,4,24,2011));
  }
 
  public function testEasterFalse() {
    $easter2011 = easter(2011);
    $this->assertNotEquals($easter2011, gmmktime(0,0,0,12,24,2011));
  }
} 

Zuerst habe einen Verweis auf das PHP-Script (hier: functions.php), in welcher die Funktion easter($Jahr) enthalten ist. Dann generiere ich eine Klasse („EasterTest“), welche PHPUnit erweitert. In dieser Klasse sind zwei Tests abgelegt:

Jetzt kommt der trockene theoretische Teil…
Hier geht es nicht etwa darum, das Ergebnis zu finden – das hat man ohnehin schneller mit einem Blick auf dem Kalender. Vielmehr ist es Ziel, das Ergebnis der Funktion mit einem definierten „Wunschergebnis“ zu vergleichen. Ich weiß, dass der 24.04. dieses Jahr der Ostersonntag ist… und ich weiß, dass es der 24.12. definitiv nicht ist.

PHPUnit – wie auch fast alle andere Software in diesem Umfeld – arbeitet mit „Assertions“ (Behauptungen). Es gibt eine Sammlung von einfachen Funktionen, welche solche Assertions in verschiedenen Konstrukten ermöglichen – angefangen von Vergleichsoperationen wie die im Beispiel verwendeten assertEquals und assertNotEquals über False/True-Varianten, Array-Prüfern und einigem anderen.

Ist dies viel Arbeit?
Bitte urteilt selbst.. ein einfacher Test ist fix geschrieben. Nicht schwer, oder?

Zurück zur Praxis.
Wie kann man nun die Tests auswerten? Am einfachsten über die Shell. Und hier ist es nun wirklich egal, ob man sich in einer Dosbox, Bash oder wo auch immer aufhält.

D:\htdocs\>phpunit EasterTest.php
PHPUnit 3.5.11 by Sebastian Bergmann.

..
 
Time: 0 seconds, Memory: 3.75Mb
 
OK (2 tests, 2 assertions)

PHPUnit kann auch andere Output-Formate, beispielsweise das TAP-Format („Test Anything Protocol“), JSON, XML und andere.

D:\htdocs\>phpunit --tap EasterTest.php
TAP version 13
ok 1 - EasterTest::testEasterOk
ok 2 - EasterTest::testEasterFalse
1..2

Wenn ich nun in einem Test einen Fehler habe, sieht das so aus (ich habe hierfür den Test 1 so verändert, dass die Behauptung lautet, der 23.04.2011 wäre Ostersonntag – ist aber in Wirklichkeit der Samstag davor):

D:\htdocs\>phpunit --tap EasterTest.php
TAP version 13
not ok 1 - Failure: EasterTest::testEasterOk
  ---
  message: 'Failed asserting that <integer:1303516800> matches expected <integer:1303603200>.'
  severity: fail
  data:
    got: 1303516800
    expected: 1303603200
  ...
ok 2 - EasterTest::testEasterFalse
1..2

Wenn ich nun – wann und warum auch immer – an der eigentlichen Funktion wieder mal arbeite, dann habe ich weiterhin meine gespeicherten Tests. Wenn diese mir also Mist zurückgeben, ist entweder mein Test falsch (eher unwahrscheinlich), oder meine veränderte Funktion ist nicht ok… und genau darum geht es hier. Modultests wie dieser hier machen den Code deutlich stabiler und nachträgliche Arbeiten, Erweiterungen etc. erheblich einfacher.

Und wenn es mal Bugs gibt… schreibt einen Test und fixt dann den Bug!

Next Page →