Seite 2 von 7

Re: Geschwindigkeit

Verfasst: 21.11.2012 10:59
von DrShrek
lite hat geschrieben:Ich weiss, ist echt schwer, darauf eine Anwort geben zu können.
Ohne Source und Testdaten auf jeden Fall.
Stell doch mal das ganze Scenario zur Verfügung.

Re: Geschwindigkeit

Verfasst: 21.11.2012 13:42
von PMV
lite hat geschrieben:Saß gestern 3 Stunden davor um das Problem zu finden.
Bin echt ratlos. Kann es an der Gui liegen ? Irgendwas bremst.
Benute XP Support und Unicode.
Ich weiss, ist echt schwer, darauf eine Anwort geben zu können.
Wir können nicht wissen, was du gemacht hast. Ohne den
ganzen Code kann dir niemand hier helfen. Ob du Fehler
gemacht hast oder ob dein Code total unausgereift ist,
oder ob Auto It tatsächlich einfach nur in diesem Scenario
besser optimiert ... ohne Code keine Antwort möglich. :wink:

MFG PMV

Re: Geschwindigkeit

Verfasst: 21.11.2012 15:01
von STARGÅTE
lite hat geschrieben:Hab das gestern getestet. Die Auswirkungen sind im Millisekunden bereich.
Als ich die Funktionen miteinander verglich und in eine For Next Schleife steckte, ca. 100 000 aufgerufen, hab.
Ergab sich ein Unterschied von 570 Ms zu 340 Ms für deine Funktion.
Schön, und genau daran erkenne ich, dass du es mit dem Debugger gestartet hast (so sieht es jedenfalls aus).

Wenn du mal folgenden Code ohne Debugger ausführst, erhalte ich ein Verhältnis von: 1326ms zu 94ms

Code: Alles auswählen

Procedure.s StringStrip(str$)
  ; stringstripleft (unicode)
  res$=""
  For x =0 To Len(str$)*2 Step 2
    uni=PeekU(@str$+x)
    If uni>32
      res$=Mid(str$,1+(x/2))
      Break
    EndIf
  Next
  ; stringstripright (unicode)
  str$=""
  res$= ReverseString(res$)
  For x =0 To Len(res$)*2 Step 2
    uni=PeekU(@res$+x)
    If uni>32
      str$=Mid(res$,1+(x/2))
      Break
    EndIf   
  Next
  str$= ReverseString(str$)
  ProcedureReturn str$
EndProcedure



Structure CharacterArray
   c.c[0]
EndStructure

Procedure.s StringStrip2(*Char.CharacterArray)
   Protected Length.i = MemoryStringLength(*Char)-1
   Protected Index.i = 0
   While *Char\c[Index] <= 32
      Index + 1
   Wend
   While *Char\c[Length] <= 32
      Length - 1
   Wend
   ProcedureReturn PeekS(@*Char\c[Index], Length-Index+1)
EndProcedure


#Size = 1000000
Define String.s = #TAB$+#TAB$+"  Tabs und Leerzeichen"+#TAB$+"  "


Time = ElapsedMilliseconds()
For n = 1 To #Size
	StringStrip(String)
Next
Time1 = ElapsedMilliseconds()-Time



Time = ElapsedMilliseconds()
For n = 1 To #Size
	StringStrip2(@String)
Next
Time2 = ElapsedMilliseconds()-Time


MessageRequester("Testergebnis", "Time1: "+Str(Time1)+Chr(10)+"Time2: "+Str(Time2))
Würde ich es mit Debugger laufen lassen, müsste ich #Size (also die schleifendurchläufe) verkleinern und komme dann auf ein ähnliches Verhältnis wie du: 218ms zu 94ms
lite hat geschrieben:Bin echt ratlos. Kann es an der Gui liegen ? Irgendwas bremst.
Wenn du mit GUI deine eigene Ausgabe während der Ausführung meinst, dannn ganz klar ja.
Debug(lins$) ist schon n Bremse, fallst du es mit Debugger startest.
Falls du SetGadgetText oder so benutzt kann es auch bremsen, wenn der Fensterinhalt aktualisiert wird.

Re: Geschwindigkeit

Verfasst: 21.11.2012 16:16
von matbal
Ich denke, ein weiteres großes Problem liegt beim StringField.

Das Einlesen einer INI-Datei als ganzes beschleunigt minimal die Dateioperation.
Das Extrahieren der einzelnen Zeilen mit StringField bremst aber extrem, da die Funktion ja jede Zeile neu aus dem großen Text heraussuchen muß.

Ich habe für den Vergleich eine ähnliche Prozedur geschrieben.

Code: Alles auswählen

EnableExplicit

Define File$ = "d:\Dateiman\TotalCmd\wincmd.ini"
Define Section$ = "user"
#anzahl = 100

; ----------------------------------------------------------

Procedure ReadSection1(File$, Section$)
   Protected Text$, l, *mem, fmt
   
   If ReadFile(0, File$)
      l = Lof(0)
      If l 
         *mem = AllocateMemory(l + 2)
         If *mem
            fmt = ReadStringFormat(0)
            ReadData(0, *mem, l)
            Text$ = PeekS(*mem, -1, fmt)
            FreeMemory(*mem)
         EndIf
      EndIf
      CloseFile(0)
   EndIf
   
   
   Protected n, i, zeile$, sec
   
   
   If Text$
      Section$ = LCase("[" + Section$ + "]")
      
      n = CountString(Text$, #LF$) + 1
      For i = 1 To n
         zeile$ = StringField(Text$, i, #LF$)
         If Left(zeile$, 1) = "["
            zeile$ = LCase(Trim(zeile$, #CR$))
            If zeile$ = Section$
               sec = 1
            Else
               sec = 0
            EndIf
         ElseIf sec = 1
            zeile$ = Trim(zeile$, #CR$)
            Debug zeile$
         EndIf
      Next i
   EndIf
   
EndProcedure

; ----------------------------------------------------------

Procedure ReadSection2(File$, Section$)
   Protected fmt, zeile$, sec, res$
   
   Section$ = "[" + LCase(Section$) + "]"
   
   If ReadFile(0, File$)
      fmt = ReadStringFormat(0)
      While Not Eof(0)
         zeile$ = ReadString(0, fmt)
         If Asc(zeile$) = '['
            zeile$ = LCase(zeile$)
            If zeile$ = Section$
               sec = 1
            Else
               sec = 0
            EndIf
         ElseIf sec = 1
            Debug zeile$
         EndIf
      Wend
      CloseFile(0)
   EndIf
   
EndProcedure

; ----------------------------------------------------------

Define i
OpenConsole()


; ----------------------------------------------------------
Debug "-------"
; Ini-Datei als String Einladen und mit Stringfield Zeilen lesen

Define t = ElapsedMilliseconds()
For i = 0 To #anzahl
   ReadSection1(File$, Section$)
Next i
PrintN(Str(ElapsedMilliseconds() - t))

; ----------------------------------------------------------
Debug "-------"
; Ini-Datei Zeilenweise lesen
Define t = ElapsedMilliseconds()
For i = 0 To #anzahl
   ReadSection2(File$, Section$)
Next i
PrintN(Str(ElapsedMilliseconds() - t))



Input()





Zum Testen braucht ihr eine relativ große Ini, und die gesuchte Sektion sollte nicht am Anfang sein.

Ich habe den Test mit der Wincmd.ini vom TotalCommander gemacht und 100 Mal nach der Sektion "user" suchen lassen.
Das dauert mit mit der "falsch-optimierten" Methode bei mir 7,4 Sekunden, mit ganz billigem zeilenweisen Einlesen aber nur 0,11 Sekunden.

Re: Geschwindigkeit

Verfasst: 21.11.2012 21:26
von bobobo
Such mal in der Hilfe nach Preference
PB kann von sich aus mit üblichen ini-Dateien umgehen

Re: Geschwindigkeit

Verfasst: 21.11.2012 22:09
von matbal
bobobo hat geschrieben:Such mal in der Hilfe nach Preference
PB kann von sich aus mit üblichen ini-Dateien umgehen
Ich weiß.

Ich habe meinen Demo-Code in Anlehnung an lites Code erstellt (auf der erste Seite im Faden - AutoIt gegen PB).

Seine Dateien scheinen nicht gleich, sondern nur ähnlich aufgebaut zu sein wie die Preference oder INI-Dateien von Windows. Meine erste Prozedur arbeitet ähnlich wie die von lite, aber seine ganzen Spezialbehandlungen fehlen. (Trimmen, Kommentare und Leerzeilen weglassen, mehrzeilige Einträge zusammenfassen...)

Re: Geschwindigkeit

Verfasst: 22.11.2012 10:56
von lite
Hallo bobobo,

die standart Preference nützt nix, da sie kein unicode verarbeiten kann.
Hab gestern nochmals alle sämtliche Funktionen durchgetest, über 4 Stunden.
Das Ergebnis, wie schon beschrieben. PureBasic ist wesentlich schneller.

Mittlerweile hab ich den Fehler gefunden. Es lag an den Shellexecute+wait aufrufen.
Die Shellexecute hatte einen Timeout mit Delay(300) drin, und bei 20 * aufrufen macht sich die Sache bemerkbar.

Da es mein erstes großes Programm mit PureBAsic ist, bei dem es auf Zeit ankommt,
hatte ich überhaupt keine Vorstellung, Wie schnell PureBasic überhaupt ist.

Auf jeden Fall vielen Dank für die Mühen.

Grüße
Lite

Re: Geschwindigkeit

Verfasst: 22.11.2012 13:30
von bobobo
lite hat geschrieben:Hallo bobobo,

die standart Preference nützt nix, da sie kein unicode verarbeiten kann.
na sowas ..

Code: Alles auswählen

;Compileroptionen "Unicode Executable erstellen" gesetzt
;IDE-compiler :"Text des Quellcodes" UTF-8
OpenPreferences("d:\fat.ini")
PreferenceGroup("Texte")
WritePreferenceString("ClemensVonBrentano","Das Märchen von dem Schulmeister Klopfstock und seinen fünf Söhnen")
ClosePreferences()

ReadFile(0,"D:\Fat.ini")
Select ReadStringFormat(0)
Case    #PB_Ascii  : Debug "Kein BOM gefunden. Dies kennzeichnet üblicherweise eine normale Textdatei."
  Case #PB_UTF8   : Debug "UTF-8 BOM gefunden."
  Case #PB_Unicode: Debug "UTF-16 (Little Endian) BOM gefunden."

  Case #PB_UTF16BE: Debug "UTF-16 (Big Endian) BOM gefunden."
  Case #PB_UTF32  : Debug "UTF-32 (Little Endian) BOM gefunden."
  Case #PB_UTF32BE: Debug "UTF-32 (Big Endian) BOM gefunden."
EndSelect
CloseFile(0)
bei mir ist das dann utf-8 und das ist eigentlich schon unicode
Aber vermutlich meinst Du ein anderes UniCodeformat
außer mit utf8 und utf32 geht da nichts mit unicode-inidateien


ist das eigentlich normal oder eher ein Bug oder ein fehlende Option ?

eigentich könnte zumindest das Lesen der PreferenceDateien
die PB bekannten Unicodereien beinhalten.

Re: Geschwindigkeit

Verfasst: 22.11.2012 13:58
von PMV
Wenn du ne alternative zu den Preference-Befehlen suchst,
weil diese im Unicodemodus nur UTF-8 lesen und schreiben kann,
dann könnteste vielleicht damit was anfangen:
http://forums.purebasic.com/german/view ... =8&t=12117

@bobobo
eine gewünschte nicht unterstützte Funktionalität nennt man
nicht Bug-Report sondern Feature Request. :wink:

MFG PMV

Re: Geschwindigkeit

Verfasst: 22.11.2012 14:26
von bobobo
da oben steht ja auch u.a. "fehlende Option"

und vom Report bin ich meilenweit entfernt

Bei Preferences sollte es sich ja ohnehin nicht um einen riesigen Datenumfang handeln.
Für "dickere" Daten gibt's wohl andere bessere Möglichkeiten (datenbank und so)

Das Einlesen einer unicode-ini-Datei im Umfang von 18.5 MB mit anschließendem Umwandeln
in utf8 dauert hier (laptop T5250 = eigentlich mittlerweile eine olle Krücke ) auch "nur" 250msec.
Der Weiterverarbeitung steht da nicht mehr viel im Wege.