Open Source im professionellen Einsatz
Linux-Magazin 12/2008
© Michael Hirschka, Pixelio

© Michael Hirschka, Pixelio

Profiler identifizieren Flaschenhälse in Perl-Programmen

Laufzeit-Tacho

Statt hochgezüchteter Prozessoren helfen oft schon simple Tricks, um Programme zu beschleunigen. Profiler können Engpässe entdecken, in die es sich lohnt, Entwicklungszeit zu investieren.

682

Wer nicht den ganzen Tag mit Videospielen verplempert, kommt auch ohne die allerschnellste CPU klar und spart so nicht nur Hardwarekosten, sondern auch noch Strom und schont die Umwelt. Sollte ein Perl-Programm dann doch zu betulich zu Werke gehen, lässt es sich meist mit geringem Aufwand durch Optimierung des Code an entscheidenden Stellen beschleunigen. Meist reichen ein, zwei gezielte Eingriffe, um 90 Prozent der überhaupt möglichen Verbesserungen zu erzielen. Die restlichen 10 Prozent erfordern oft weitreichende architektonische Umbauarbeiten, die zehnmal so lange dauern und anschließend die Wartung erschweren, sodass erfahrene Entwickler dankend abwinken.

Flaschenhälse zuerst

Die Bottlenecks oder Hot Spots finden Profiler. Sie zeigen, wo ein Programm die meiste Zeit verbringt, und erlauben es dem Entwickler, solche Bereiche gezielt zu verbessern. Perl hat etliche Tools für diesen Zweck in seiner Werkzeugkiste. Setzt ein Modul beispielsweise das Logging-Framework Log4perl ein, ist es einfach, verstrichene Sekunden zusammen mit den Lognachrichten anzuzeigen und so einen zeitlichen Überblick zu erhalten.

Das simple Testskript »amzntest« (Listing 1) holt zum Beispiel mit Hilfe des CPAN-Moduls Net::Amazon Buchinformationen über das Web-API bei Amazon ab. (Sofern im Skript ein gültiges Token eingetragen ist, das es bei [2] gibt.) Ein Request dauert ungefähr eine Sekunde. Aber wo genau verbrät das Skript diese Zeit? Schon beim Einholen der Daten oder erst während der anschließenden XML-Analyse? Ein am Kopf des Skripts eingefügtes

use Log::Log4perl;
Log::Log4perl->init("timer.l4p");

aktiviert das in Net::Amazon eingebettete Log4perl-Framework und lädt die Konfigurationsdatei »timer.l4p«, derzufolge zu jeder geloggten Nachricht auch noch das Datum (»%d«) sowie die Zahl der verstrichenen Millisekunden seit dem Programmstart (»%r«) auszugeben ist. Da der Loglevel mit »DEBUG« relativ hoch und damit die ausgegebenen Nachrichten recht lang sein können, definiert Listing 2 auch noch einen so genannten Custom Cspec mit dem Kürzel »%S«.

Dieser erscheint dann statt des sonst üblichen »%m« (für die Lognachricht) im Layout und schickt eine auf 25 Zeichen verkürzte Nachricht an den Screen-Appender. Das Layout schließt mit einem plattformunabhängigen Newline-Zeichen ab, das als »%n« erscheint.

Abbildung 1: Log4perl gibt die Uhrzeit und die verstrichenen Millisekunden seit dem Programmstart an.

Abbildung 2: Bei einem eingesetzten Webcache entfällt der Webrequest für Wiederholer, das reduziert die Laufzeit um 75 Prozent.

Abbildung 1 zeigt, dass Net::Amazon bereits 79 Millisekunden nach dem Programmstart einen Webrequest an Amazon absetzt, der XML-Parser aber erst zum Zeitpunkt 739 Millisekunden seine Arbeit beginnt. Von den insgesamt vom Skript verbrauchten 800 Millisekunden nimmt also 75 Prozent der Webrequest in Anspruch.

Listing 1:
»amzntest«

01 #!/usr/bin/perl
02 use warnings;
03 use strict;
04 use Net::Amazon;
05 use Net::Amazon::Request::ASIN;
06 
07 my $asin = "0132396556";
08 
09 my $ua = Net::Amazon->new(
10     token => 'XXXXXXXXXXXXXXX',
11 );
12 
13 my $req = Net::Amazon::Request::ASIN->new(
14     asin  => $asin,
15 );
16 
17 my $resp = $ua->request($req);
18 
19 if($resp->is_success()) {
20     print $resp->as_string(), "n";
21 } else {
22     print "Error: ",
23           $resp->message(), "n";
24 }

Listing 2:
»timer.l4p«

1 log4perl.logger          = DEBUG, App
2 log4perl.appender.App    = Log::Log4perl::Appender::Screen
3 log4perl.appender.App.layout = PatternLayout
4 log4perl.appender.App.layout.ConversionPattern = %d %r %S%n
5 log4perl.PatternLayout.cspec.S = sub { substr($_[1], 0, 25) }

Schneller Fix

Folglich bietet es sich an, für häufig eingeholte ASIN-Nummern einen Cache einzusetzen, den Net::Amazon - wie Listing »amzncache« (Listing 3) zeigt - standardmäßig unterstützt. In der Tat reduziert sich die Skriptlaufzeit mit File::Cache als persistentem Zwischenspeicher bei Wiederholern auf 180 Millisekunden, wie in Abbildung 2 zu sehen.

Listing 3:
»amzncache«

01 use Cache::File;
02 my $cache = Cache::File->new(
03    cache_root        => '/tmp/mycache',
04    default_expires   => '30 min',
05 );
06 
07 my $ua = Net::Amazon->new(
08     token => 'XXXXXXXXXXXXXXX',
09     cache => $cache,
10 );

Listing 4:
»l4ptest«

01 #!/usr/local/bin/perl -w
02 use strict;
03 
04 use Log::Log4perl qw(:easy);
05 Log::Log4perl->easy_init($INFO);
06 
07 for(1..100_000) {
08     DEBUG "waah!";
09 }

Nun lässt sich freilich argumentieren, dass derlei Tricks nicht immer möglich sind. Aber entscheidend ist doch, dass fünf Zeilen Code und eine Minute Nachdenken eine Geschwindigkeitsverbesserung um den Faktor 4 erzielen.

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • In eigener Sache: Bundle "Perl-Snapshot" für Perlensammler

    Michael Schilli skriptet in diesen dreißig Programmier-Artikeln vieles - vom Twitter-Agenten bis zur Spamlandkarte. Die Homestory "Ich denke in Perl" zum zehnjährigen Jubiläum 2007 geht voran. Auch dabei: Perl-Fallen für Lernende, aus den Erfahrungen unseres Perl-Professors des Professorenmagazins 01/2009.

  • Bitparade

    Für Perl-Entwickler gibt es ausgefeilte Plugins für Texteditoren, aber auch für ausgewachsene IDEs. Ob der Einsatz solcher Plugins oder Anwendungen tatsächlich beim Skripte-Programmieren hilft, lotet die aktuelle Bitparade anhand des Editors Vim, der Perl-IDE Padre sowie des Eclipse-Plugins Epic aus.

  • Amazon-As

    Dem Beispiel des famosen Suchdienstes Google folgend, bietet nun auch das virtuelle Kaufhaus Amazon.com seinen Produktkatalog per XML und Webservice an. Perl-Programmierer nutzen dies und suchen gezielt nach Produkten und Preisen.

  • Geiz ist geil

    Ein Perl-Skript verfolgt für Schnäppchenjäger die Preisentwicklung auf Amazon und schlägt per E-Mail freudig Alarm, falls sich überwachte Produkte plötzlich verbilligen.

  • Perl-Snapshot Linux-Magazin 2012/05

    "Perlmeister" Michael Schilli hat seinen Snapshot mit dem Magazin 2012/04 als Screencast verarbeitet.

comments powered by Disqus

Ausgabe 08/2016

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.