ASP Tipp 13: Vermeiden das Neudimensionieren von Arrays

Vermeiden Sie nach Möglichkeit das Neudimensionieren von Arrays mit Redim. Wenn die physikalische Speichergröße Ihres Computer eingeschränkt ist, empfiehlt es sich in Bezug auf die Leistung, die Anfangsdimension des Arrays auf das schlimmste Szenario festzulegen. Sie können die Dimension auch für das optimale Szenario einstellen und bei Bedarf neu festlegen. Dies bedeutet nicht, dass Sie einfach ein paar Megabyte Arbeitsspeicher zuordnen sollen, wenn Sie wissen, dass er nicht gebraucht wird.

Dieser Code zeigt den unnötigen Gebrauch von Dim und Redim.

<%

Dim MyArray()

Redim MyArray(2)

MyArray(0) = „hello“

MyArray(1) = „good-bye“

MyArray(2) = „farewell“

‚ some other code where you end up needing more space happens, then …

Redim Preserve MyArray(5)

MyArray(3) = „more stuff“

MyArray(4) = „even more stuff“

MyArray(5) = „yet more stuff“

%>

Es ist wesentlich besser, das Feld anfangs mit Dim auf die richtige Größe einzustellen (in diesem Fall 5), und es dann mit Redim zu vergrößern. Dabei verschwenden Sie eventuell etwas Speicher (wenn Sie nicht alle Elemente verwenden), gewinnen aber an Geschwindigkeit.

ASP Tipp 14: Verwenden Sie den Antwortpuffer

Sie können eine ganze auszugebende Seite durch Aktivieren des „Antwortpuffers“ puffern. Dadurch wird die Anzahl der Schreibvorgänge im Browser reduziert und die Gesamtleistung gesteigert. Für jeden Schreibvorgang ist ein großer Aufwand nötig (sowohl in IIS und bezüglich der über die Leitung gesendeten Datenmengen), d. h. je weniger Leitungen, desto besser. TCP/IP funktioniert aufgrund seines langsamen Starts und der Nagling-Algorithmen (zum Minimieren von Netzwerkstaus) effizienter, wenn anstelle von vielen kleinen Datenblöcken wenige große Datenblöcke gesendet werden können.

Sie können den Antwortpuffer auf zwei Arten aktivieren. Einerseits können Sie den Antwortpuffer mit dem Internetdienste-Manager für die gesamte Anwendung aktivieren. Diese Methode wird empfohlen. Der Antwortpuffer wird in IIS 4.0 und IIS 5.0 standardmäßig für neue ASP-Anwendungen aktiviert. Andererseits können Sie den Antwortpuffer auf Seitenbasis aktivieren, indem Sie folgende Codezeile am oberen Rand der ASP-Seite positionieren.

<% Response.Buffer = True %>

Diese Codezeile muss ausgeführt werden, bevor Antwortdaten in den Browser geschrieben werden (d. h., bevor HTML im ASP-Skript angezeigt wird, und bevor Cookies mit der Response.Cookies-Auflistung festgelegt wurden). Im Allgemeinen sollten Sie den Antwortpuffer für die ganze Anwendung aktivieren. Damit ist die obige Codezeile auf jeder Seite überflüssig.

Response.Flush

Benutzer sind häufig der Meinung, dass die Antwortzeit von ASP-Seiten durch den Antwortpuffer langsamer ist (obwohl die Antwortzeit insgesamt verbessert ist), weil sie warten müssen, bis die gesamte Seite generiert wurde, bevor eine Anzeige erfolgt. Sie können den Antwortpuffer für lange Seiten deaktivieren, indem Sie Response.Buffer = False festlegen. Es gibt aber eine bessere Strategie: Verwenden Sie stattdessen die Response.Flush-Methode, bei der ASP den gesamten gezeichneten HTML-Inhalt im Browser anzeigt. Nachdem z. B. 100 Zeilen einer aus 1000 Zeilen bestehenden Tabelle gezeichnet wurden, kann ASP Response.Flush aufrufen, um die gezeichneten Ergebnisse im Browser anzuzeigen. Damit kann der Benutzer die ersten 100 Zeilen sehen, bevor die verbleibenden Zeilen fertig sind. Diese Methode bietet Ihnen das Beste aus beiden Bereichen: den Antwortpuffer in Kombination mit der allmählichen Präsentation der Daten im Browser.

(Beachten Sie, dass viele Browser beim oben dargestellten Beispiel einer aus 1000 Zeilen bestehenden Tabelle die Tabelle erst anzeigen, wenn sie das schließende Kennzeichen </table> sehen. Präfen Sie, ob die gewünschten Browser die teilweise Anzeige unterstützen. Sie können dieses Problem umgehen, indem Sie die Tabelle in mehrere Tabellen mit einer geringeren Anzahl von Zeilen aufteilen und nach jeder Tabelle Response.Flush aufrufen. Neuere Versionen von Internet Explorer zeigen Tabellen an, bevor sie vollständig gedownloadet wurden, und die Anzeige erfolgt besonders schnell, wenn sie die Spaltenbreiten der Tabelle festlegen. Dadurch braucht Internet Explorer die Spaltenbreiten nicht durch Messen des Inhalts jeder einzelnen Zelle zu berechnen.)  

Benutzer beschweren sich beim Antwortpuffer außerdem darüber, dass er beim Generieren sehr großer Seiten sehr viel Serverspeicher verbraucht. Ohne hier Weisheiten über das Generieren von sehr großen Seiten abzugeben, lässt sich dieses Problem ebenfalls mithilfe von Response.Flush beheben.

 

ASP Tipp 15: Stapeln Sie Inlineskripts und Response.Write-Anweisungen

Die VBScript-Syntax <% = expression %> schreibt die Werte von „expression“ in den ASP-Ausgabestrom. Wenn der Antwortpuffer nicht aktiviert ist, schreiben alle diese Anweisungen Daten in vielen kleinen Paketen über das Netzwerk in den Browser. Dies geht nur langsam vonstatten. Außerdem führt das Abwechseln von kleinen Skript- und HTML-Mengen zu einem Wechsel zwischen dem Skriptmodul und HTML, was sich ebenfalls negativ auf die Leistung auswirkt. Halten Sie sich daher an folgenden Tipp: Ersetzen Sie eng gepackte Inlineanweisungen durch einen Aufruf von Response.Write. Im folgenden Beispiel erfolgt pro Feld und Zeile ein Schreibvorgang im Antwortstrom, und pro Zeile finden viele Wechsel zwischen VBScript und HTML statt.

<table>

<% For Each fld in rs.Fields %>

<th><% = fld.Name %></th>

<%

Next

While Not rs.EOF

%>

<tr>

<% For Each fld in rs.Fields %>

<td><% = fld.Value %></td>

<% Next

</tr>

<% rs.MoveNext

Wend %>

</table>

Im effizienteren Code weiter unten erfolgt pro Zeile ein Schreibvorgang im Antwortstrom. Der gesamte Code ist in einem VBScript-Block enthalten:

<table>

<%

For each fld in rs.Fields

Response.Write („<th>“ & fld.Name & „</th>“ & vbCrLf)

Next

While Not rs.EOF

Response.Write („<tr>“)

For Each fld in rs.Fields %>

Response.Write(„<td>“ & fld.Value & „</td>“ & vbCrLf)

Next

Response.Write „</tr>“

Wend

%>

</table>

Dieser Tipp hat wesentlich stärkere Auswirkungen, wenn der Antwortpuffer deaktiviert ist. Es empfiehlt sich, den Antwortpuffer zu aktivieren, und auszuprobieren, ob die Leistung durch Stapelverarbeitung von Response.Write verbessert werden kann.

(In diesem speziellen Beispiel kann die verschachtelte Schleife, die den Tabellenkörper erstellt (While Not rs.EOF…), durch einen gut durchdachten Aufruf von GetString), ersetzt werden.)

ASP Tipp 16: Vermeiden Sie lange Wartezeiten durch Verwendung von Response.IsClientConnected

Wenn Benutzer ungeduldig werden, brechen sie Ihre ASP-Seite möglicherweise ab, bevor Sie mit dem Ausführen ihrer Anfrage beginnen können. Wenn sie auf Aktualisieren klicken oder auf Ihrem Server auf eine andere Seite wechseln, befindet sich eine neue Anfrage am Ende der ASP-Anfragewarteschlange und eine abgetrennte Anfrage in der Mitte der Warteschlange. Dies geschieht häufig bei einem stark belasteten Server (die Anfragewarteschlange ist in diesem Fall sehr lang und bringt ebenso lange Antwortzeiten mit sich) und führt zu einer Verschlimmerung der Situation. Es ergibt keinen Sinn, eine ASP-Seite (und insbesondere eine langsame, umfangreiche ASP-Seite) auszuführen, wenn der Benutzer nicht mehr verbunden ist. Sie können dies mit der Response.IsClientConnected-Eigenschaft überprüfen. Wenn sie False zurückgibt, sollten Sie Response.End aufrufen und den Rest der Seite abbrechen. Dieses Verhalten ist in IIS 5.0 im Code enthalten, d. h. wenn ASP im Begriff ist, eine neue Anfrage auszuführen, prüft es zuerst, wie lange die Anfrage sich schon in der Warteschlange befindet. Befindet sie sich schon seit mehr als 3 Sekunden in der Warteschlange, prüft ASP, ob der Client noch angeschlossen ist und bricht die Anfrage sofort ab, wenn dies nicht der Fall ist. Sie können diese Zeitüberschreibung in der Metabasis mit der AspQueueConnectionTestTime-Einstellung ändern.  

Bei einer Seite, deren Ausführung sehr lange dauert, sollten Sie außerdem Response.IsClientConnected in regelmäßigen Abständen prüfen. Wenn der Antwortpuffer aktiviert ist, empfiehlt es sich, Response.Flush in regelmäßigen Abständen auszuführen, damit der Benutzer den Eindruck hat, dass etwas passiert.

Anmerkung In IIS 4.0 funktioniert Response.IsClientConnected nicht ordnungsgemää, wenn Sie nicht zuerst eineResponse.Write-Anweisung ausführen. Wenn der Antwortpuffer aktiviert ist, können Sie auch eine Response.Flush-Anweisung ausführen. In IIS 5.0 ist dies nicht nötigt; Response.IsClientConnected funktioniert problemlos. Response.IsClientConnected ist in jedem Fall mit einigen Kosten verbunden. Verwenden Sie diese Anweisung daher nur vor einem Vorgang, der mindestens 500 Millisekunden dauert (das ist eine lange Zeit, wenn Sie versuchen, einen Durchsatz von mehreren Dutzenden von Seiten pro Sekunde zu erreichen). Als Faustregel gilt, diese Anweisung nicht bei jeder Wiederholung einer engen Schleife, wie z. B. beim Zeichnen der Zeilen einer Tabelle, sondern sie eher alle 20 oder 50 Tabellenzeilen aufzurufen.

ASP Tipp 17: Erstellen Sie Objekte mit dem „OBJECT“-Kennzeichen

Wenn Sie auf Objekte verweisen müssen, die möglicherweise nicht in allen Codepfaden verwendet wurden (insbesondere Objekte im Gültigkeitsbereich des Session- oder Application-Objekts), deklarieren Sie diese mit dem Kennzeichen <object runat=server id=objname> in der Datei Global.asa, anstatt die Server.CreateObject-Methode zu verwenden. Server.CreateObject erstellt das Objekt sofort. Wenn das Objekt später nicht verwendet wird, verschwenden Sie damit Ressourcen. Das Kennzeichen <object id=objname> deklariert objname, aber objname wird erst erstellt, wenn eine seiner Methoden oder Eigenschaften zum ersten Mal verwendet werden.

Dies ist ein anderes Beispiel für eine verzögerte Auswertung.

 

ASP Tipp 18: Verwenden Sie die TypeLib-Bindung mit ADO- und anderen Komponenten

Beim Verwenden von ADO nehmen Entwickler oft adovbs.txt auf, um auf die verschiedenen Konstanten von ADO zugreifen zu können. Diese Datei muss auf jeder Seite hinzugefügt werden, die die Konstanten verwenden möchte. Sie ist verhältnismäßig umfangreich und erhöht den Aufwand bei der Kompilierungszeit und Skriptgröße jeder ASP-Seite.

In IIS 5.0 gibt es erstmals die Möglichkeit der Bindung an die Typbibliothek einer Komponente. Dadurch können Sie einmal auf die Typbibliothek verweisen und sie auf jeder ASP-Seite verwenden, ohne dass alle Seiten unter der Kompilierung der Konstantendatei leiden, und Entwickler brauchen keine VBScript #include-Dateien für ASP zu erstellen.

Positionieren Sie folgende Anweisungen in der Datei Global.asa, um auf die ADO-TypeLib zuzugreifen.

<!– METADATA NAME=„Microsoft ActiveX Data Objects 2.5 Library“

TYPE=„TypeLib“ UUID=„{00000205-0000-0010-8000-00AA006D2EA4}“ –>

oder

<!– METADATA TYPE=„TypeLib“

FILE=„C:\Program Files\Common Files\system\ado\msado15.dll“ –>

ASP Tipp 19: Profitieren Sie von den Gültigkeitsfunktionen Ihres Browsers

Moderne Browser verfügen über erweiterte Unterstützung für Funktionen wie XML, DHTML, Java-Applets und Remote Data Service. Nutzen Sie die Vorteile dieser Funktionen wann immer möglich. Alle diese Technologien sparen Anfragen beim und Antworten durch den Webserver, denn sie nehmen eine Überprüfung des Clients sowie das Zwischenspeichern von Daten vor. Wenn Sie einen intelligenten Browser verwenden, kann dieser einen Teil der Überprüfung für Sie übernehmen (und z. B. prüfen, ob eine Kreditkarte über eine gültige Prüfsumme verfügt, bevor POST ausgeführt wird). Nutzen Sie auch dies wann immer möglich. Durch Reduzieren der Client-Server-Anfragen werden die Belastung des Webservers und der Netzwerkverkehr verringert (obwohl die erste an den Browser gesendete Seite möglicherweise umfangreicher ist) sowie die Back-End-Ressourcen, auf die der Server zugreift, reduziert. Darüber hinaus muss der Benutzer neue Seiten nicht mehr so häufig abrufen und macht somit positivere Erfahrungen. Dies bedeutet aber nicht, dass eine Überprüfung auf dem Server unnötig ist. Sie sollten diese auf jeden Fall immer durchführen, denn sie schätzt vor schädlichen Daten, die aus irgendeinem Grund (z. B. von Hackern) vom Client oder von Browsern gesendet werden, die keine Überprüfung des Clients durchführen.

Es wurde viel Wind um die Erstellung von „browserunabhängigem“ HTML-Code gemacht. Dieses Anliegen hält Entwickler häufig davon ab, sich gängige Browserfunktionen zu Nutze zu machen, die sich günstig auf die Leistung auswirken können. Für echte Hochleistungssites, bei denen die Browserreichweite eine Rolle spielt, empfiehlt es sich, Seiten für die gängigen Browser zu optimieren. Browserfunktionen lassen sich in ASP einfach mit der Komponente für Browserfähigkeiten feststellen. Programme, wie z. B. Microsoft FrontPage, sind beim Entwerfen von Code behilflich, der sowohl für die Browser als auch die HTML-Versionen funktioniert. Weitere Informationen finden Sie im Artikel „When is Better Worse? Weighing the Technology Trade-Offs“.

 

ASP Tipp 20: Vermeiden Sie die Zeichenfolgenverkettung in Schleifen

Viele Benutzer erstellen eine Zeichenfolge in einer Schleife wie folgt:

s = „<table>“ & vbCrLf

For Each fld in rs.Fields

s = s & „<th>“ & fld.Name & „</th>“

Next

While Not rs.EOF

s = s & vbCrLf & „<tr>“

For Each fld in rs.Fields

s = s & „<td>“ & fld.Value & „</td>“

Next

s = s & „</tr>“

rs.MoveNext

Wend

s = s & vbCrLf & „</table>“ & vbCrLf

Response.Write s

Bei dieser Methode gibt es mehrere Probleme. Als Erstes wird beim wiederholten Verketten von Zeichenfolgen quadratische Zeit gebraucht, d. h. die Zeit zum Ausführen dieser Schleife ist proportional zum Quadrat der Anzahl der Datensätze mal der Anzahl der Felder. Ein einfacheres Beispiel müsste dies deutlich machen.

s = „“

For i = Asc(„A“) to Asc(„Z“)

s = s & Chr(i)

Next

Bei der ersten Wiederholung erhalten Sie eine aus einem Zeichen bestehende Zeichenfolge, „A“. Bei der zweiten Wiederholung muss VBScript die Zeichenfolge neu zuweisen und zwei Zeichen („AB“) nach s kopieren. Bei der dritten Wiederholung muss s erneut zugewiesen und drei Zeichen nach s kopiert werden. Bei der Nten (26.) Wiederholung müssen N Zeichen neu zugewiesen und nach s kopiert werden. Dies ergibt eine Summe von 1+2+3+…+N und entspricht N*(N+1)/2 Kopiervorgängen.

Im oben dargestellten Beispiel für ein Recordset würde die innere Schleife bei 100 Datensätzen und 5 Feldern 100*5 = 500 mal ausgeführt werden, und die für alle Kopiervorgänge und Neuzuweisungen benötigte Zeit wäre proportional zu 500*500 = 250,000. Das sind für ein Recordset von mäßiger Größe recht viele Kopiervorgänge.

In diesem Beispiel könnte der Code verbessert werden, wenn die Zeichenfolgenverkettung durch Response.Write() oder Inlineskript (<% = fld.Value %>) ersetzt würde. Wenn der Antwortpuffer (wie empfohlen) aktiviert wird, ist dieser Code schnell, da Response.Write die Daten einfach am Ende des Antwortpuffers anhängt. Hierbei ist keine Neuzuweisung notwendig, und der Code ist sehr effizient.

In dem Sonderfall beim Transformieren eines ADO-Recordsets in eine HTML-Tabelle sollten Sie die Verwendung von GetRows oder GetString in Betracht ziehen.

Wenn Sie Zeichenfolgen in JScript verketten, wird dringend empfohlen, dass Sie den +=-Operator verwenden, d. h. verwenden Sie s += „some string“, und nicht s = s + „some string“.

ASP Tipp 21: Aktivieren Sie Browser- und Proxyzwischenspeicherung

ASP deaktiviert das Zwischenspeichern in Browsern und Proxys automatisch. Dies ist sinnvoll, da eine ASP-Seite von Natur aus dynamisch ist und potenziell zeitempfindliche Informationen enthält. Wenn eine Seite beim Anzeigen nicht jedes Mal aktualisiert werden muss, sollten Sie die Browser- und Proxyzwischenspeicherung aktivieren. Dadurch können Browser und Proxys eine „zwischengespeicherte“ Kopie einer Seite für einen bestimmten, von Ihnen festgelegten Zeitraum verwenden. Durch Zwischenspeichern wird die Belastung des Servers drastisch reduziert, und Benutzer machen positivere Erfahrungen.

Welche dynamischen Seiten eignen sich zum Zwischenspeichern? Hierzu einige Beispiele:

  1. Eine Wetterseite, auf der das Wetter nur alle fünf Minuten aktualisiert wird.
  2. Eine Homepage mit Nachrichten oder Pressemitteilungen, die nur zweimal täglich aktualisiert wird.
  3. Ein Liste mit der Leistung von Fonds, deren Statistiken nur alle paar Stunden aktualisiert werden.

Beachten Sie, dass bei der Browser- oder Proxyzwischenspeicherung auf Ihrem Webserver weniger Treffer verzeichnet werden. Wenn Sie versuchen, alle Seitenansichten genau zu messen oder Werbung auf einer Website zu platzieren, machen Sie mit der Browser- oder Proxyzwischenspeicherung möglicherweise keine guten Erfahrungen.

Die Browserzwischenspeicherung wird vom HTTP-Header Expires gesteuert, der von einem Webserver an einen Browser gesendet wird. ASP stellt zwei einfache Mechanismen zum Senden dieses Headers bereit. Sie können die Seite so konfigurieren, dass sie nach einer bestimmten Anzahl von Minuten abläuft. Legen Sie dazu die Response.Expires-Eigenschaft fest. In folgendem Beispiel wird dem Browser mitgeteilt, dass der Inhalt nach 10 Minuten abläuft.

<% Response.Expires = 10 %>

Wenn Sie für Response.Expires eine negative Zahl oder Null festlegen, wird das Zwischenspeichern deaktiviert. Verwenden Sie auf jeden Fall eine große negative Zahl, z. B. -1000 (etwas mehr als ein Tag), um Unterschiede zwischen den Uhren auf dem Server und den Browsern zum umgehen. Eine zweite Eigenschaft, Response.ExpiresAbsolute, ermöglicht das Festlegen einer bestimmten Uhrzeit, zu der der Inhalt abläuft.

<% Response.ExpiresAbsolute = #May 31,2001 13:30:15# %>

Statt den Ablauf mit dem Response-Objekt festzulegen, können Sie ein <META>-Kennzeichen in HTML (normalerweise im Abschnitt <HEAD> der HTML-Datei) schreiben. Einige Browser respektieren diese Anweisung, Proxys jedoch nicht.

<META HTTP-EQUIV=„Expires“ VALUE=„May 31,2001 13:30:15“>

Zum Schluss können Sie noch angeben, ob der Inhalt für eine Zwischenspeicherung in einem HTTP-Proxy gültig ist. Verwenden Sie dazu die Response.CacheControl-Eigenschaft, und legen Sie sie auf Public fest, um Proxys das Zwischenspeichern des Inhalts zu ermöglichen.

<% Response.CacheControl = „Public“ %>

Diese Eigenschaft ist standardmäßig auf Private festgelegt. Beachten Sie, dass die Proxyzwischenspeicherung nicht für Seiten aktiviert werden sollte, die benutzerspezifische Daten anzeigen, da der Proxy möglicherweise Seiten anzeigt, die anderen Benutzern gehören.

ASP Tipp 22: Verwenden Sie, wenn möglich, Server.Transfer anstelle von Response.Redirect

Response.Redirect teilt dem Browser mit, eine andere Seite anzufordern. Diese Funktion wird häufig verwendet, um Benutzer zu einer Anmeldungs- oder Fehlerseite umzuleiten. Da eine Umleitung eine neue Seitenanforderung erzwingt, muss der Browser zwei Anfragen an den Webserver senden, und der Webserver muss eine zusätzliche Anfrage bewältigen. IIS 5.0 führt die neue Funktion Server.Transfer ein, die die Ausführung auf eine andere ASP-Seite auf dem gleichen Server überträgt. Dadurch wird die zusätzliche Anfrage des Browsers beim Server vermieden. Das Resultat ist eine insgesamt bessere Systemleistung, und Benutzer profitieren von besseren Antwortzeiten. Schlagen Sie in der Artikelreihe „New Directions in Redirection“ nach, in der Server.Transfer und Server.Execute behandelt werden.

Schlagen Sie außerdem in „Leveraging ASP in IIS 5.0“ nach. Dort erhalten Sie eine ausführliche Liste der neuen Funktionen in IIS 5.0 und ASP 3.0.