HBUMNMapServer ger Capter Performance

= Performance =
In diesem kurzen Kapitel möchte ich meine eigenen Erfahrungen mit MapServer-Anwendungen verstärkt einfließen lassen. Da mein Arbeitgeber MapServer-Dienst\-leistungen vertreibt, müssen wir uns natürlich Argumente einfallen lassen, was uns gegenüber u.a. proprietärer Software abhebt. Ein häufig genannter Vorteil ist die Performance von MapServer.
Performance kommt nicht aus dem Nichts, sondern muß durch Optimierungen und Anpassungen an den jeweiligen Anwendungsfall herbeigerufen werden. MapServer ist nicht per se und bei allem performant. Man muß wissen, an welchen Stellen man wofür drehen muß. Dafür muß man natürlich erst einmal wissen, was man eigentlich will.
Der größte Wunsch ist auch der offensichtlichste: eine möglichst kurze Antwortzeit pro Karte. Danach folgt natürlich die Frage, wieviele Anfragen MapServer parallel bearbeiten kann.
Wir möchten uns an dieser Stelle vor allen Dingen um die erste Frage kümmern, also wie man die Produktionszeit einer einzelnen Karte möglichst kurz hält. Die zweite Frag ist zu technisch, als dass sie von einem Handbuch dieser Art beantwortet werden sollte.
Dennoch lassen sich einige allgemeine Ratschläge erteilen, wie Sie MapServer-Anwen\-dungen performanter gestalten können. Die wichtigsten sollen im folgenden aufgelistet werden.
=Vermeiden Sie unnötige Funktionalität=
Ein CGI-Programm wird bei jedem Aufruf neu geladen\footnote{Das stimmt nicht ganz, ist aber für die Argumentation hilfreich.}. Je kleiner das Programm ist, und je weniger Bibliotheksabhängigkeiten das Programm hat, desto geringer fällt der Overhead aus, den Funktionalitäten produzieren, die Sie niemals nutzen werden. Unterstützung für JPEG-Bilder ist hübsch; aber was sollen Sie damit, wenn Sie nur PNG ausliefern wollen? Shockwave Flash und PDF erstellen zu können, kann schick sein, aber Sie müssen sich die Frage stellen, ob Sie das wirklich brauchen . Zu Testzwecken möchte man das auf einem Entwicklersystem durchaus haben, auf einem Produktionssystem ist es unnötiger Ballast.
Hier kommt der Vorteil von MapServer ins Spiel, dass er in den Quellen verfügbar ist. Dadurch können Sie sich ein CGI erstellen, das genau auf Ihre Bedürfnisse zugeschnitten ist. Dabei gehe ich natürlich davon aus, dass Sie nicht zwei Wochen später sagen 'Ach, das und das will ich aber auch noch haben'. Vorausplanung ist ein wichtiger Faktor für die Performance eines fertigen Systems, und dazu gehört, dass Sie wissen, was Sie eigentlich haben wollen.
Desweiteren sollten Sie darauf achten, dass Ihr Server, der MapServer zur Verfügung steht, auch möglichst nichts anderes tut als Karten auszuliefern. Solche Dinge wie FTP-Server, Mailserver und solcherlei gehören nicht auf ein System, das rechenintensiven Aufgaben übernimmt. Insbesondere ein X-Windows-System mit KDE und Office-Applikationen für eine graphische Benutzeroberfläche ist eine vollkommen sinnlose Verschwendung von Resourcen.
=Nutzen Sie MINSCALE und MAXSCALE=
Große, detaillierte Datensätze -- insbesondere Rasterdaten -- sind schön anzusehen, in der Darstellung aber leider sehr rechenintensiv. Stellen Sie sich eine hydrogeologische Karte Ihres Bundeslandes vor, in 100 Kacheln. Und nun zoomt jemand von der Landeshauptstadt auf einen Ausschnitt der gesamten Bundesrepublik heraus. Die Folge wäre, dass alle Kacheln angezeigt werden müssen, jede einzelne aber nur ein kleiner Farbfleck auf der Karte ist. Und jeder dieser Farbflecken braucht die Berechnungszeit einer ganzen Kachel.
Sie müssen also dafür sorgen, dass bestimmte Layer in bestimmten Maßstäben nicht mehr angezeigt werden. Genau das leisten die Parameter =MINSCALE= und =MAXSCALE= , mit denen Sie Scale-Werte angeben können, zwischen denen ein Layer ein- bzw. wieder ausgeblendet wird.
Der Scale-Wert entspricht grob dem Maßstab einer angezeigten Karte. Details zu diesem Wert, und Maßstäben auf dem Bildschirm im allgemeinen, finden Sie auf Seite~\pageref{text:mapfile:scale}. Sie können sich den Scale des aktuellen Kartenausschnitts anzeigen lassen, indem Sie den MapServer-Tag =[scale]= in Ihr Template einfügen.
Leider gibt es keine allgemeingültigen Richtlinien, welche Art von Daten in welchem Scale (und bei welcher Kartengröße) angezeigt werden sollte. Dafür müssen Sie ein eigenes Gespür entwickeln. Lassen Sie sich den Scale-Wert anzeigen und zoomen Sie heraus bzw. hinein. Notieren Sie sich die Werte, bei denen Sie die Darstellung nicht mehr nötig finden und runden Sie die Werte ab bzw. auf. Übernehmen Sie diese Werte dann in Ihr Mapfile.
=Legen Sie Indizes an=(2)
Bei jedem Aufruf von MapServer stellt sie die Software die Frage, welche Features denn eigentlich dargestellt werden müssen. Im ungünstigsten Fall der Suche müssen alle vorhandenen Features der Reihe darauf geprüft werden, ob sie angezeigt werden. Um das zu verhindern, legt man Indizes an.
Ein Index ist, abstrakt gesprochen, eine Einrichtung, die das Suchen beschleunigt. In der Informatik spielen solche Beschleunigungen eine erhebliche Rolle, und erfüllen die verschidensten Zwecke. Für den MapServer ist der Zweck, so schnell wie möglich die darzustellenden Features zu bestimmen. Je größer die Datenmengen, desto offensichtlicher ist der Nutzen einer solchen Einrichtung.
\subsection*{Indizes für Shapefiles}
Shapes in einem Shapfiles sind prinzipiell nicht sortiert\footnote{Beziehungsweise es gibt keinen Weg herauszufinden, ob ein Shape sortiert ist, ohne dass man alle Shapes prüft.}, und können sich vor allen Dingen auch überlappen. Von daher ist es nötig, dass man alle Shapes betrachtet, um herauszufinden, ob sie dargestellt werden müssen oder nicht.
MapServer kann allerdings Indizes für Shapedateien nach dem sogenannten Quadtree-Schema benutzen, wodurch sich die Anzahl der zu betrachtenden Shapefiles drastisch verringern kann. Die Optimierung greift nur, wenn Sie Teile des gesamten Shapes zeigen, und ist nutzlos, wenn Sie das ganze Shape darstellen.
Ein Index für Shapefiles besteht für MapServer aus einer zusätzlichen Datei mit der Endung =.qix= , die sich mit dem Wekzeug =shptree= erzeugen läßt, das Bestandteil des MapServer-Quellcodes ist.
Die Datei wird folgendermaßen konstruiert. Zuerst wird das gesamte Gebiet virtuell in vier Teile zerlegt. Diese Teile werden in sich wiederum zerlegt, wobei die Zerlegungsstrategie darauf hinausläuft, kleine Flächen zu erzeugen, wo mehr Shapes zu finden sind.
Welchen Sinn hat das? Sobald der anzuzeigende Ausschnitt feststeht, prüft MapServer, ob und wie der Ausschnitt eine der Flächen im Index schneidet. Ist das nicht der Fall, werden die entsprechenden Shapes in dieser Fläche nicht beachtet. Damit reduziert sich die Anzahl der Shapes, die geprüft werden müssen, drastisch.
Die genaue Verwendung von =shptree= ist in Anhang~\ref{text:tools:shptree} bei den MapServer-Werkzeugen beschrieben. Für ein Shapefile, nennen wir es =postleitzahlen.shp= , genügt für gewöhnlich der Aufruf:
# shptree postleitzahlen.shp
Hinweis : Das Konglomerat 'Shapefile' besteht aus der eigentlichen Shapedatei, einer DBF-Datei sowie einer Indexdatei mit der Endung =.shx= . Diese Datei ist jedoch kein Index in unserem Sinne, sondern ist lediglich eine Liste der Positionen in der Shapedatei, an der die einzelnen Shapes beginnen. Die Shapedatei beinhaltet nämlich lediglich der Reihe nach die Koordinaten der Shapes, aber keine Markierung für deren Anfang oder Ende.
\subsection*{Indizes für PostGIS-Datenbanken}
Auch Datenbanken wollen indiziert werden, um Suchvorgänge zu beschleunigen. Bei 'normalen' Datenbanken ergibt das nur ab einer bestimmten Datenmenge Sinn; die Verarbeitungsgeschwindigkeit Ihres Adreßbuches mit 50 Einträgen wird sich mit oder ohne Index kaum unterscheiden.
In unserem Fall geht es bei Datenbanken jedoch, genau wie bei Shapefiles, nicht um eine gewöhnliche Suche beispielsweise in einer Liste, sondern um eine räumliche Suche. Die Indizes sind dabei anders aufgebaut. Glücklicherweise ist die Erstellung von Indizes auf einen einzigen Befehl beschränkt, den man gleich durchführen sollte, nachdem man Daten in eine PostGIS-Tabelle eingespielt hat. Der genaue Vorgang ist in Abschnitt~\ref{text:database:postgis:loader} beschrieben, und sieht für eine Tabelle namens =postleitzahlen= ungefähr so aus:
CREATE INDEX plz_idx ON postleitzahlen
 USING GIST (the_geom GIST_GEOMETRY_OPS);
=Kacheln Sie Ihre Daten=
Das Öffnen einer großen Rasterdatei ist ein speicheraufwendiger Vorgang. MapServer öffnet die Datei und 'schneidet' sich den gewünschten Teil heraus. Passieren zehn MapServer-Aufrufe gleichzeitig, kann das erhebliche Probleme mit sich bringen.
Die Lösung ist, große Daten in kleinere Teile zu zerlegen und diese Kacheln dann in einem Bildkatalog zusammenzufassen. Anstatt ein Rasterbild mit 16000 mal 16000 Pixeln zu benutzen, sind 256 Kacheln mit 1000 mal 1000 Pixeln wesentlich erstrebenswerter. 
Hinweis : Sollten Sie die Zerlegung von großen Bildern durch eine Software Ihrer Wahl automatisieren, achten Sie auf die Farbpaletten der Bilder, die dabei generiert werden. Höchstwahrscheinlich werden für die neuen Bilder auch neue Paletten erzeugt, was dazu führen kann, dass Parameter wie =OFFSITE= nicht mehr die erwarteten Ergebnisse liefern.
Die Erstellung von Bildkatalogen für die Kacheln leistet dann das Werkzeug =gdaltindex= , dessen Verwendung in Abschnitt~\ref{text:tools:gdaltindex} beschrieben wird.
Im übrigen sollten Sie auch große Vektordatensätze kacheln. Das Werkzeug =tile4ms= , das dem MapServer-Quellcode beiliegt, leistet genau das.
Sie fragen sich natürlich, wie man in diesem Zusammenhang 'groß' definiert. Das läßt sich schwer sagen, denn es ist -- mal wieder -- von der Applikation abhängig und erschließt sich nur durch Experimentieren und Erfahrung.
=Kompression muß verstanden werden=
Ed McNiermy hat auf der MapServer-Mailingliste einen wichtigen Beitrag zum Thema Kompression von Rasterdaten geleistet. Die Theorie und die Implikationen sollen hier kurz zusammengefaßt werden.
Rasterformate wie zum Beispiel TIFF unterstützen interne Kompressionsformate, wie etwa LZW, ZIP und so weiter. Dabei behält die Datei ihre Endung bei -- also zum Beispiel =.tif= bei TIFF-Bildern --, aber innerhalb der Datenstrukturen der Datei werden die Bilder komprimiert. Die verarbeitende Software muß dann beim Lesen die Dekomprimierung vornehmen.
Der Platzgewinn bei komprimierten Daten kann enorm sein, insbesondere dann, wenn die Farbtiefe der Bilder gering ist. Daher scheint die Kompression hier automatisch eine gute Idee zu sein.
Allerdings wird der Zugewinn an Festplattenplatz zum einen mit einem gewissen Overhead erkauft: schließlich müssen die Daten jedesmal nicht nur eingelesen werden, sondern eben auch dekomprimiert, und das kostet Rechenzeit.
Das zweite Problem ist weniger offensichtlich. Wenn Sie einen Ausschnitt aus einem Rasterbild darstellen wollen, kommt es auf das verwendete Kompressionsverfahren an, ob nur ein Teil der Datei gelesen werden muß (der dann entpackt wird), oder ob ein Großteil der Datei -- oder gar das gesamte File -- dekomprimiert werden muß, um auf einen kleinen Ausschnitt im Bild zugreifen zu können. Letzteres wäre offensichtlich unschön.
Es ist daher anzuraten, dass Sie sich im Vorhinein mit den von Ihnen verwendeten Kompressionsverfahren auseinandersetzen und sich mit dem Verhalten von MapServer bei den diversen Methoden vertraut machen.
Und als Hinweis zum Schluß: Festplatten sind inzwischen ziemlich preiswert.
=Hardware=
Das Erstellen von Kartenansichten ist eine äußerst rechenintensive Angelegenheit. Die Hardware, die dafür zum Einsatz kommen soll, sollte daher in Hinblick auf die Anforderungen gewählt werden, die eine MapServer-Anwendung stellt. Daraus ergibt sich schon einmal die erste Regel: Kaufen Sie nicht von der Stange. Ein fertiges, unveränderliches Komplettsystem ist in den allermeisten Fällen nicht das, was Sie wollen.
Ein zentraler Bestandteil der Aufgaben von MapServer ist es, Daten von der Festplatte zu lesen. Offensichtlich möchte man die Geschwindigkeit in diesem Teil optimieren. Das geht zum einen durch den Einsatz schneller Festplatten; da häufig große Dateien gelesen werden sollen, ist eine hohe Datendurchsatzrate meistens erstrebenswerter als besonders schnelle Zugriffszeit oder hohe Umdrehungsgeschwindigkeit. Auch die Konfiguration eines RAID-Systems, das die Daten auf mehrere Festplatten verteilt und zusätzlich noch für erhöhte Ausfallsicherheit sorgen kann, sollte in Erwägung gezogen werden.
Wichtig ist auch Hauptspeicher. Die Empfehlung: möglichst viel davon. Mit viel Hauptspeicher können Daten, auf die häufig zugegriffen wird, vom Betriebssystem gecacht werden. Des weiteren wird Zugriff auf den Swapbereich vermieden, was die Performance arg in den Keller ziehen kann.
Machen Sie es sich auch zunutze, falls Sie jemanden zur Hand haben, der sich mit dem Zusammenspiel bestimmter Hardwarekomponenten und Betriebssystemen auskennt. Die richtige Auswahl der Hardware kann zu erstaunlichen Gewinnen in der Performance führen.
Auch im Bereich Hardware gilt allerdings, dass Erfahrungen erst gesammelt werden müssen. Ein überdimensioniertes System, dessen teure Resourcen die meiste Zeit brach liegen, wird Ihnen nicht viel Freude bereiten.
Und denken Sie schließlich daran, dass Ihnen schnelle Hardware genau gar nichts nützt, falls Sie die Organisation der Daten nicht sinnvoll betreiben. 
=Schließlich: Zeigen Sie nie alles auf einmal=
Wenn man einige Arbeit in ein Mapfile gesteckt und ein schönes Layout für seine Karte gemacht hat, ist man natürlich versucht, alles auf einmal darzustellen. Das ist keine gute Idee, denn damit würden Sie alle Maßnahmen, die bisher in diesem Kapitel besprochen worden sind, ad absurdum führen.
Die obengenannten Optimierungen ergeben nur bei Ausschnitten aus den Daten Sinn. Sobald Sie einen Datensatz komplett anzeigen, greift kein Index mehr, da sowieso alle Daten angezeigt werden, und eine Kachelung großer Datensätze ist ebenfalls wirkungslos.
Für einen Überblick während der Entwicklung ist es natürlich nötig, die gesamte Datenmenge im vollen Umfang im Auge zu haben. Sie sollten aber beispielsweise durch geeignete Werte von =MINSCALE= und =MAXSCALE= dafür sorgen, dass der Benutzer nur Ausschnitte zu sehen bekommt\footnote{Das sieht selbstverständlich anders aus, falls es der Zweck der Anwendung ist, das Gesamtbild zu erfassen. Für das ganze Kapitel gilt natürlich immer die Einschränkung, dass Sie die Hinweise immer gegen den Zweck Ihrer Anwendung abwägen müssen}. Und zwar nicht nur in lokalen Rasterlayern; auch Vektorlayer benötigen Rechenzeit. Von WMS-Layern einmal ganz zu schweigen.
\subsubsection*{Statische Einstiegskarten}
Andererseits ist es natürlich manchmal vonnöten, dem Benutzer einen Überblick zu verschaffen, was denn überhaupt alles an Daten zur Verfügung steht. Wenn Ihr Angebot beispielsweise nach Bundesländern strukturiert ist, muß der Benutzer zu Beginn ein Bundesland wählen können. Es ist allerdings offensichtlich nicht sehr sinnvoll, für diesen immer gleichen Einstieg den MapServer zu bemühen.
Daher sind statische Einstiegskarten ohne MapServer-Aufruf wesentlich sinnvoller. Von einer solchen Karte können Sie dann auf detailliertere Ausschnitte verweisen. In den meisten Fällen werden dazu so genannte image maps verwendet. Mit solch einer Image Map -- die übrigens in reinem HTML ohne jedes Scripting funktioniert -- können Sie mehrere Verweise in eine Karte einbauen. Das kann dann zum Beispiel so aussehen:
<map name="brdmap">
<area shape="rect" coords="5,15,10,20"
 href="/cgi-bin/mapserv?map=hamburg.map&...">
<area shape="rect" coords="15,20,45,65"
 href="/cgi-bin/mapserv?map=brandenburg.map&...">
</map>
...
<img src="brd.png" usemap="#brdmap">
Wenn Sie in dem Bild also einen Punkt im ersten Rechteck anklicken, wird die Karte für Hamburg aufgerufen, im zweiten Fall die Karte für Brandenburg.
Eine detaillierte Erklärung, wie Sie mit Image Maps in HTML umgehen, erhalten Sie beispielsweise auf der Website von SelfHTML~http:website:selfhtml.
Die Überschrift dieses Abschnitts trifft insbesondere auf große Datensätzen in Datenbanken zu. Wenn Sie kleine Ausschnitte aus großen Datensätzen anzeigen, werden Sie die Performancevorteile von PostGIS kennenlernen.
Category:UMN MapServer Handbuch