© photocase.com
Workshop: Python-Programme optimieren
Gut gezielt
von Stefan Schwarzer
Erschienen im Linux-Magazin
2006/12
Jeder wünscht sich Programme, mit denen er flink arbeiten kann. Schnelle Software entsteht aber nicht durch flächendeckende, sondern durch wenig Optimierung - an den richtigen Stellen. Dieser Workshop zeigt, wie Sie bei Python-Programmen ins Schwarze treffen.
Die Optimierung von Programmen will in erster Linie Laufzeit sparen. Die Software soll sich zügiger anfühlen, ihre Rechenergebnisse schneller präsentieren und so fort. Doch leider verlängert Optimierung die Entwicklungszeit. Der entstehende Quelltext ist normalerweise komplizierter als vorher, was den Aufwand zum Testen und zur Fehlersuche steigert. Doch das ist noch nicht alles: Durch die gestiegene Komplexität des Code werden auch dessen Wartung und zum Beispiel nachträgliche Erweiterungen schwieriger. Das kostet weitere Entwicklungszeit, was oft übersehen wird, weil sie mitunter erst lange nach der Optimierung fällig sind.
Deshalb ist es falsch, schon beim Schreiben jeder Funktion oder Methode darüber nachzudenken, wie sie am schnellsten arbeiten könnte. Diese Einstellung bringt C. A. R. Hoare - obwohl der Satz häufig Donald Knuth zugeschrieben wird - mit "Premature optimization is the root of all evil" auf den Punkt. Das ist der Fall: Der Programmierer sollte die Laufzeitoptimierung erst angehen, wenn das Programm fehlerfrei läuft.
Wo optimieren?
Ein Programm ist aus Sicht des Entwicklers nie durchweg langsam oder durchweg schnell. Für träges Verhalten ist normalerweise nur ein kleiner Teil des Code verantwortlich, die so genannten Flaschenhälse (Bottlenecks). Bevor Sie anfangen, auf Verdacht Codeteile zu beschleunigen, sollten Sie messen, wo es genau klemmt. Im ersten Schritt ist festzustellen, ob die Software beim Ausführen einer bestimmten Funktion durch die CPU oder das EA-Subsystem behindert wird. So ist es sinnlos, einen Algorithmus auf ein Hundertstel seiner ursprünglichen Rechenzeit zu bringen, wenn tatsächlich die Festplatten oder das Netzwerk die Software bremsen.
Um zu ermitteln, ob der langsame Prozessor, die Festplatte oder andere Hardware die Schuldigen sind, helfen Ihnen grafische Werkzeuge wie Xosview [1] oder Gkrellm [2]. Daneben gibt es Tools wie Dstat [3], die beispielsweise den Datentransfer von und zu einer bestimmten Partition in Zahlen wiederspiegeln. Um plausibel zu messen, dürfen allerdings möglichst keine anderen Prozesse laufen, die den Rechner auslasten. Alternativ liefern »top« oder »ps« einzelne Leistungsdaten von Prozessen.
Die Abbildungen 1 bis 3 zeigen Screenshots von Gkrellm und Dstat für einen durch die CPU und einen durch Datentransfer begrenzten Prozess. Der zweite Fall ist schwieriger zu erkennen als die CPU-Begrenzung, da es keine Hardware-unabhängige Obergrenze gibt. Ermitteln Sie entsprechende Grenzwerte am besten durch Hardware-Spezifikationen oder Benchmarks. Bedenken Sie, dass Datentransfer sich nicht nur wie hier auf ein CD-ROM-Laufwerk beziehen kann, sondern auch auf Netzwerk-Schnittstellen, Tape-Wechsel-Roboter in Backup-Systemen und so weiter.
Wird die Software durch eine vollständige CPU-Auslastung gehemmt, müssen Sie die bremsenden Stellen im Code weiter eingrenzen. Dabei hilft das Python-Modul »cProfile« (bis Python 2.4 »profile«), dessen Ergebnisse das Modul »pstats« auswertet.

|
Abbildung 1: Links zeigt Gkrellm die hundertprozentige Prozessorauslastung für einen von der CPU-begrenzten Prozess. Rechts stellt das Programm den Datendurchsatz beim Kopieren einer CD-ROM dar.
|

|
Abbildung 2: Ausgabe von »dstat« für einen CPU-begrenzten Prozess. Die Summe der beiden ersten Spalten liegt bei 100 Prozent.
|

|
Abbildung 3: Dstat-Report für einen durch Datentransfer begrenzten Prozess (Kopieren einer CD-ROM). Wichtig sind die Werte der Spalte »disk/total/read«.
|
Profiling-Beispiel: Emerge
Als praktisches Beispiel für den Einsatz des Python-Profilers soll eine Suche in der Paket-Datenbank von Gentoo Linux dienen. Das entsprechende Tool »emerge« ist in Python geschrieben. Eine Suche mit »emerge --search python« läuft auf dem Rechner des Autors in einer akzeptablen Zeit von knapp 10 Sekunden. Eine Optimierung wäre also höchstens für langsamere Rechner sinnvoll, aber zunächst soll es hier ja nur um die Analyse gehen.
Die Ablaufstatistik mit Pythons C-Profile-Modul zu erzeugen ist etwas umständlich, da dessen Kommandozeilenschnittstelle nicht vorsieht, dem aufgerufenen Programm Parameter mitzugeben. Daher verwendet der Workshop den interaktiven Interpreter (Listing 1). Nach dem Importieren der Python-Module und der Vorbereitung der Parameter startet »cProfile.run()« den Testlauf. Das Modul »pstats« gibt dann die Laufzeitstatistik tabellarisch aus (Listing 2).
01 >>> import cProfile
01 >>> import sys
01 >>> sys.argv.append("--search")
01 >>> sys.argv.append("python")
01 >>> f = open("/usr/bin/emerge")
01 >>> ef = f.read()
01 >>> f.close()
01 >>> cProfile.run(ef, "emerge.stats")
01 Searching...
01 [ Results for search key : python ]
01 [ Applications found : 48 ]
01 ...
|
01 >>> import pstats
01 >>> s = pstats.Stats("emerge.stats")
01 >>> s.sort_stats('time')
01 <pstats.Stats instance at 0xb7d80eac>
01 >>> s.print_stats(10)
01 Sun Oct 1 23:12:36 2006 emerge.stats
01
01 602508 function calls (586701 primitive calls) in 9.052 CPU seconds
01
01 Ordered by: internal time
01 List reduced from 609 to 10 due to restriction <10>
01
01 ncalls tottime percall cumtime percall filename:lineno(function)
01 1240 1.022 0.001 1.022 0.001 {method 'readlines' of 'file' objects}
01 11387 0.849 0.000 0.849 0.000 {method 'flush' of 'file' objects}
01 1096 0.579 0.001 1.513 0.001 /usr/lib/portage/pym/portage.py:200(cacheddir)
01 14550/160 0.421 0.000 1.173 0.007 /home/schwa/python2.5/lib/python2.5/copy.py:144(deepcopy)
01 76352 0.359 0.000 0.359 0.000 {method 'append' of 'list' objects}
01 1 0.335 0.335 2.513 2.513 <string>:468(output)
01 66288/66173 0.316 0.000 0.317 0.000 {len}
01 11383 0.256 0.000 1.225 0.000 <string>:94(update_twirl)
01 36953 0.224 0.000 0.224 0.000 {method 'split' of 'str' objects}
01 1 0.213 0.213 3.629 3.629 <string>:408(execute)
|
Ein besonderer Flaschenhals fällt zwar nicht auf, dennoch sind ein paar Stellen zu erkennen, an denen eine Optimierung ansetzen könnte. So verbringt Emerge immerhin 1,2 von 9 Sekunden damit, die Fortschrittsanzeige (Methode »update_twirl«) zu aktualisieren (zu sehen in der Spalte »cumtime«, kumulative Zeit, in der achten Tabellenzeile). Allerdings gibt es bereits eine Emerge-Option, die diese Ausgabe abschaltet.
Etwa 1,2 Sekunden fallen für tiefe Kopien an (Spalte »cumtime« in der vierten Tabellenzeile). Tiefe Kopien werden von Programmierern manchmal einfach sicherheitshalber gemacht. Hier gibt es Einsparpotenzial, falls die tiefe Kopie nicht wirklich nötig ist.
Möglicherweise ließe sich der Code nach einer Umstrukturierung noch besser beschleunigen, da dann deutlicher zu erkennen wäre, wann welcher Code abläuft und welche algorithmischen Vereinfachungen möglich sind. Schließlich ist die Änderung von Algorithmen oft die wirksamste Laufzeitoptimierung.
| Whitepaper |
|
Open Source Datenintegration in der Praxis: Fallstudien und Anwendungsbeispiele
Über die letzten Jahre hinweg haben sich Open Source Lösungen als fester Bestandteil des gesamten Datenintegrationsmarktes etabliert. Viele Unternehmen haben bereits das Open Source Modell für Ihre Datenintegrationsprojekte aufgegriffen. Das vorliegende White Paper illustriert anhand ausgewählter Fallstudien und Anwendungsbeispiele die Implementierung von Open Source Datenintegration in der Praxis und benennt die daraus resultierenden Vorteile.
Download PDF (Registrierung erforderlich)
|
|
The Role of Open Source in Data Integration
Obwohl in den letzten Jahren viele technische Fortschritte erzielt werden konnten, verfügen die meisten Datenintegrationsprozesse nach wie vor nur über eine sehr begrenzte Automatisierung. Das vorliegende White Paper von dem Industry Analyst Mark Madson wird zunächst ein grundlegendes Verständnis von Daten Integration vermitteln, die Vorzüge von Open Source Lösungen für Daten Integration erläutern und Ihnen professionelle Empfehlungen geben, damit Sie Ihre Integrationsjobs noch einfacher und produktiver gestalten können.
Download PDF (Registrierung erforderlich)
|
Dieser Online-Artikel kann Links enthalten, die auf nicht mehr vorhandene Seiten verweisen. Wir ändern solche "broken links"
nur in wenigen Ausnahmefällen. Der Online-Artikel soll möglichst unverändert der gedrucken Fassung entsprechen.
|