Post on 21-Jan-2015
description
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 1
Feinabstimmung für Ihr Lotusscript
Jens-B. Augustiny, LIGONET GmbH
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 2
Who is who?
● Jens-B. Augustiny, LIGONET GmbHBiel, Schweiz / Sindelfingen
● Seit über 15 Jahren im Notes-Umfeld tätig● Entwicklung und Administration
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 3
Agenda
● Was denken Sie, ist langsam?– Wo tauchen Leistungsprobleme auf?
● Woher nur kommt das?– Tips und Werkzeuge, die Schwachstellen zu
erkennen● Nie mehr da durch!
– Tips zur Vermeidung von Leistungsschwächen
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 4
Was glauben Sie ist langsam?
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 5
Schlechte Leistung – was genau meinen wir eigentlich?
● Schlechtes Programm ....● Lieferzeiten statt Antwortzeiten● Unmöglich damit zu arbeiten!● Dieser Ablauf muss unbedingt
verbessert werden
● Wer hat diese Argumente nicht schon gehört?
● Stellen Sie sicher, dass Sie das richtige Problem angehen!
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 6
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 7
Leistung – wovon eigentlich?● Empfundene Leistung● Der Benutzer empfindet, dass die Applikation nicht das
gewünschte Resultat liefert.● Sehr schwer zu analysieren● Mögliche Lösungen:
● Bessere Ausbildung der Benutzer: Funktionalität erklären● Verbesserung der Wahrnehmung: Mehr Informationen während der
Verarbeitung oder der Dateneingabe● Den Workflow überarbeiten und verbessern
● Das Empfinden der Benutzer kann stark beeinflussen, wie die Leistung eingeschätzt wird: Frustrierende oder langwierige Eingaben können als schlechte Leistung angekreidet werden
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 8
Reale Leistung..... oder eher das Fehlen derselben ....
● Flaschenhälse, die durch Messung erkannt werden
● Fast unmöglich, diese vorauszusagen
● Unterschiede zwischen Test- und Produktionsumgebung
● Jede Aussage ohne Messung ist Spekulation
● Die Messung selbst kann das Resultat beeinflussen
● Enorm wichtig, Messdaten zu haben, bevor man etwas ändert. Genau wie bei den Endusern haben auch Entwickler ihre eigenen Ideen, welches die Ursache von Problemen sein könnte ...
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 9
Beispiel
● Viermal derselbe Code● 2 Variablen werden verändert: Die Loop-Logik und
die Art, wie auf die Datenbank-Eigenschaften zugegriffen wird.
● Fragen:– Welche der 4 Varianten ist die Schnellste?– Warum ist die von Ihnen gewählte Variante schnell?
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 10
Der BeispielcodeForall v In db.views
s = v.namePrint s
End Forall
u = Ubound(db.views)For i = 0 To u
s =db.Views(i).namePrint s
Next
tmpView = db.Views
Forall v In tmpView s = v.namePrint s
End Forall
tmpView = db.Views
u = Ubound(tmpView)For i = 0 To u
s =tmpView(i).namePrint s
Next
A
D
C
B
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 11
Resultate
Erster Lauf: B – D – A – C
Zweiter Lauf (caching): D – B – A – C
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 12
Folgerungen
● Ergebnisse können Ueberraschen● Messungen sollten in realistischer Umgebung
durchgeführt werden● Datenmenge und Datenstruktur sollte der Realität
entsprechen, die meisten Testumgebungen sind ungenüngend
● Die Analyse muss extrem systematisch durchgeführt werden, zB. systematische Eingrenzung
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 13
●Sie benötigen aktuelle Werte, um die Arbeit etwas aufzubessern zu begründen. Woher sollen die kommen?
Woher kommt das den alles?
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 14
Now für die Zeitmessung
● Beispiel:BaseTime = Now [.... Code hier ... ]Print “Time used: “ & Now – BaseTime
● Vorteil:– Einfach und billig
● Nachteile:– Veränderung des Codes– Platzierung ist kritisch– Ungenügende Auflösung
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 15
High Resolution Timing - GetThreadInfo()
● Von Brude Perry einst publizierter nicht dokumentierter Funktionsaufruf, mittlerweile gilt das Verfahren als legal:
● http://searchdomino.techtarget.com/tip/1,289483,sid4_gci895240,00.html?FromTaxonomy=%2Fpr%2F283841
stc = GetThreadInfo(LSI_THREAD_TICKS) ' get the starting tick count '[....the code you want To Time...]'get the final tick countftc = GetThreadInfo(LSI_THREAD_TICKS) 'get the ticks per secondtps = GetThreadInfo(LSI_THREAD_TICKS_PER_SEC) 'final tick count minus starting tick count divided by ticks per second yields duration.t = (ftc - stc) / tps
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 16
● Vorteile:– Einfache Implementierung– Bessere Auflösung als Now
● Nachteile:– Veränderung des Codes– Falsche Platzierung ergibt falsche Resultate– GetThreadInfo ist nicht garantiert vorhanden
GetThreadInfo
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 17
Wie bekommt man die Resultate?
● PRINT: Resultat in der Statusleiste (Client) oder in log.nsf (Server)
● Besser:– Ausgabe in ein Dokument– Ausgabe in ein Profile-Dokument– Ausgabe in eine Analyse-Datenbank .... ähhh … Anwendung
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 18
Beispiel: Man mache es wiederverwendbar
Class debugTimer Private Start As Variant
Private fnName As String
Sub New( fn As String ) Set Start = Now fnName = fn End Sub Sub Delete Print fnName & " benötigte " & Now-Start & " Sekunden." End SubEnd Class
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 19
Sub Initialize() Dim fnTime As New debugTimer( GetThreadInfo(LSI_THREAD_PROC) ) Dim i As Integer
While i < 1000 Print i i = i + 1 Wend
End Sub
Beispiel: Man mache es wiederverwendbar
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 20
Systemeigenes Profiling
● Eingeführt mit Lotus Notes / Domino 7● Nur für Agenten und Web Services● Java und LotusScript● Aktivierung in den Eigenschaften des Agenten/WS● Resultate durch Rechtsklick auf Agent oder WS● Es gibt nur Werte für reine Notes/Domino Objekte
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 21
Sub InitializeDim db As New NotesDatabase( "", "names.nsf" )i = 0Dim s As StringFor i = 0 To UBound(db.views)
s =db.Views(i).namePrint sNext
End Sub
Systemeigenes Profiling: Beispiel
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 22
Agent laufenlassen
Systemeigenes Profiling: Beispiel
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 23
Systemeigenes Profiling: Beispiel
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 24
Teamstudio Profiler● Messung eigener Funktionen und Routinen● Zeitangaben pro Zeile● Eine Menge an zusätzlichen Analysewerten● Server und Client● LotusScript only● Anwendung wird sehr stark verlangsamt● Kostenpflichtig
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 25
Teamstudio Profiler - Beispiel
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 26
Nein, ich will da nicht wieder durch
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 27
Häufige Probleme
● Hilfsmittel sind zwingend bei bestehenden Programmen und Leistungsproblemen. Besser ist jedoch, die Probleme von Anfang an zu vermeiden.
● Manche Probleme sind reale Fehler, andere häufig nur Sorglosigkeit
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 28
GetNthDocument()
● Durchlaufen einer Doc-Collection mit GetNThDocument(n) ist bedeutend langsamer als mit GetFirstDocument und GetNextDocument (doc)
● Viel wurde darüber schon gesagt, einiges ist online nachlesbar
● http://bobzblog.com/tuxedoguy.nsf/dx/getnth-revisited-helpful-function-or-spawn-of-the-devil
● http://www.lotusgeek.com/LotusGeek/LotusGeekBlog.nsf/d6plinks/ROLR-7HHPER
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 29
Ueberprüfen Sie Ihre Loops
found=False
Do Until (selected_doc Is Nothing)If (selected_doc.Form(0)="fa_Term") Then
found=True End IfSet selected_doc=term_collection.GetNextDocument(selected_doc)
LoopSet selected_doc=term_collection.GetFirstDocument()If Not(found=True) Then
MessageBox NO_TERM_DOCUMENTS_SELECTED_TO_DELETE, 16, DELETE_ERRORExit Sub
End If
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 30
found=False
Do Until (selected_doc Is Nothing)If (selected_doc.Form(0)="fa_Term") Then
found=True ' loop sollte hier abgebrochen werden!!
End IfSet selected_doc=term_collection.GetNextDocument(selected_doc)
LoopSet selected_doc=term_collection.GetFirstDocument()If Not(found=True) Then
MessageBox NO_TERM_DOCUMENTS_SELECTED_TO_DELETE, 16, DELETE_ERRORExit Sub
End If
… und korrigieren Sie die Fehler
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 31
Fehler beheben: Verrotteter Code
● Tatsache ist, dass Code sich verändert:man entdeckt bessere Wege
● Stellen Sie sicher, dass Codeänderungen zu Ende geführt werden, sonst kann die Leistung leiden.
Sub Queryopen(...)Dim session As New NotesSessionSet db = session.currentdatabaseSet view = db.getview("People")Set ProfileDoc = db.getprofiledocument("PickerView")
' ProfileDoc.Pview = "People"End Sub
● Die Variable “view” wird nirgends im Code verwendet. Db.Getview ist ein teurer Funktionsaufruf, speziell dann, wenn das Resultat nie verwendet wird.
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 32
Achtung mit verschachtelten IF
● Anders als Sprachen wie C und Java wird bei LotusScript immer die gesamte Bedingung ausgewertet
x = 1If x = 0 And checkresult( res ) = 0 Then 'do some stuffEnd If
● Checkresult() wird in jedem Fall ausgeführt, auch wenn x nicht 0 ist. Leistungsprobleme können sich in solch einfachen Anweisungen verstecken.
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 33
x = 1If x = 0 Then
If checkresult( res ) Then 'do some stuff
End IfEnd If
● Durch die Auflösung der Bedingung in zwei Aufrufe wirde Checkresult() nur noch aufgerufen, wenn die erste Bedingung True ergibt.
Achtung mit verschachtelten IF:die Lösung
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 34
Variablen – Variant ist langsamer● Abgesehen davon, dass Variants
allgemein häufig zu Fehlern führen, sind sie ausserdem sehr langsam.
● LotusScript muss bei jedem Zugriff den Typ bestimmen und eine Datenkonversion durchführen.
● Keine falsche Müdigkeit! Option Declare gehört in jedes LotusScript Programm
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 35
Loops – Es gibt schnellere und langsamere
●Forall ist viel schneller beim Durchlauf von Arrays●For ... Next ist schneller als Do ..... Loop oder While ..... Wend
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 36
Und was noch ....
● Zugriff auf ausgewählte Documente ist schneller mit Hilfe einer Ansicht als einer Document Collection
● Zugriff auf Notes Objecte ist schneller durch eine temporäre Variable als durch einen Direktzugriff – wenn man den Wert mehr als einmal benötigt.
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 37
Zusammenfassung● Es gibt technische und nicht technische Gründe für
fehlende Performance● Wenn es technische Gründe sind, ist jede Aussage ohne
Messung reine Spekulation● Es gibt keine zwei gleiche Fälle● Systematische Top down Analyse ist extrem wichtig● Manchmal ist ein Redesign die beste Lösung● Es gibt ein paar “best practices”
Entwicklercamp 2010 / LIGONET GmbH9. März 2010 38
Danke!
●Fragen?Vielleicht gibt es sogar Antworten ..... :-)
Jens-B. Augustiny - LIGONET GmbHaugustiny.j@ligonet.chwww.ligonet.ch