Seite 1 von 1
					
				StringField()-Alternative
				Verfasst: 10.07.2017 11:38
				von SBond
				Hallo Leute,
mir ist gerade aufgefallen, dass StringField nicht gerade effizient arbeitet. Bei Verdoppelung der Einträge in einem String, halbiert sich die Anzahl der geparsten Einträge pro Sekunde. Somit vervierfacht sich die Zeit, in dem ein String (mit doppelt so vielen Einträgen) geparst wird.
Code: Alles auswählen
myString.s = ""
entries.i = 16000
For x = 1 To entries
	myString + Str(x) + #CRLF$
Next
T1 = ElapsedMilliseconds()
For index = 1 To entries
	selLine.s = StringField(myString, index, #CRLF$)
Next
T2 = ElapsedMilliseconds()
Debug "Dauer: " + Str(T2-T1) + " ms"
Debug "Eintäge: " + Str(entries)
Debug "Einträge pro Sek: " + StrD(entries/((T2-T1)/1000),2)
; Eintäge: 1000  - Einträge pro Sek: 27777.78
; Eintäge: 2000  - Einträge pro Sek: 14492.75
; Eintäge: 4000  - Einträge pro Sek: 7272.73
; Eintäge: 8000  - Einträge pro Sek: 3576.22
; Eintäge: 16000 - Einträge pro Sek: 1780.75
Bei Strings mit vielen Einträgen (>10K) wird das sehr spürbar. Gibt es da eine schnellere Alternative oder muss ich mich  irgendwie über Speicheroperatoren durch den String hangeln? Letzteres würde ich lieber meiden, da ich wahrscheinlich ASCI/Unicode-Unterscheidungen machen müsste.
viele Grüße,
SBond
 
			 
			
					
				Re: StringField()-Alternative
				Verfasst: 10.07.2017 11:58
				von Kiffi
				das hier ist ein wenig schneller:
Code: Alles auswählen
Define myString.s = ""
Define entries = 16000
For x = 1 To entries
  myString + Str(x) + #CRLF$
Next
Define CrLf.s = #CRLF$
Define SelLine.s
Define Value.s
T1 = ElapsedMilliseconds()
! $.each( v_mystring.split(v_crlf) , function( index, v_value ) {
SelLine = Value
! });
T2 = ElapsedMilliseconds()
Debug "Dauer: " + Str(T2-T1) + " ms"
Debug "Einträge: " + Str(entries)
Debug "Einträge pro Sek: " + StrD(entries/((T2-T1)/1000),2)
Grüße ... Peter
 
			 
			
					
				Re: StringField()-Alternative
				Verfasst: 10.07.2017 12:02
				von NicTheQuick
				Das hat natürlich eine quadratische Laufzeit, weil jedes mal durch den kompletten String gelaufen wird um dann genau den Eintrag mit dem richtigen Index heraus zu nehmen.
Wenn man sowieso alle Einträge aus dem String braucht, splittet man ihn lieber direkt und packt ihn in einer Array oder eine LinkedList.
Ich habe da mal schnell etwas zusammen gebastelt, das alle Einträge eines so geteilten Strings in ein Array entpackt. Die Array-Größe wird dabei automatisch in O(1) angepasst.
Code: Alles auswählen
EnableExplicit
Procedure explode(in.s, Array out.s(1), sep.s = ",")
	Protected *i.Character = @in, *s.Character = @sep, *start = *i
	Protected index.i = 0, element.s
	
	Repeat
		If *i\c = *s\c Or *i\c = 0
			*s + SizeOf(Character)
			If *s\c = 0 Or *i\c = 0
				element =  PeekS(*start, ((*i - *start) - (*s - @sep)) / SizeOf(Character) + 1)
				If ArraySize(out()) < index
					ReDim out((ArraySize(out()) + 1) * 2 - 1)
				EndIf
				out(index) = element
				If *i\c = 0
					Break
				EndIf
				index + 1
				*start = *i + SizeOf(Character)
				*s = @sep
			EndIf
		EndIf
		*i + SizeOf(Character)
	ForEver
	
	ReDim out(index)
	
	ProcedureReturn index + 1
EndProcedure
Dim out.s(0)
Define found.i
found = explode(", hi, wie, geht,, es dir?, so", out(), ", ")
Debug "" + found + " Element gefunden."
Define i.i
For i = 0 To ArraySize(out())
	Debug "out(" + i + ") = '" + out(i) + "'"
Next
Edit: Ach Mist, das war ja schon wieder für Spiderbasic.  

 
			 
			
					
				Re: StringField()-Alternative
				Verfasst: 10.07.2017 12:55
				von SBond
				Kiffi hat geschrieben:das hier ist ein wenig schneller
 
 naja "ein wenig"?! Das geht ab wie ein Zäpfchen  
 
Ich sollte wohl mal ein Crash-Kurs in JS machen  
 
vielen Dank euch beiden  
 
viele Grüße,
Martin
 
			 
			
					
				Re: StringField()-Alternative
				Verfasst: 10.07.2017 13:24
				von Kiffi
				SBond hat geschrieben:Das geht ab wie ein Zäpfchen
es geht noch schneller (mit forEach):
Code: Alles auswählen
myString.s = ""
entries.i = 1000000
For x = 1 To entries
  myString + Str(x) + #CRLF$
Next
Define CrLf.s = #CRLF$
Define SelLine.s
Define Value.s
T1 = ElapsedMilliseconds()
! $.each( v_mystring.split(v_crlf) , function( index, v_value ) {
SelLine = Value
! });
T2 = ElapsedMilliseconds()
Debug "$.each()"
Debug "Dauer: " + Str(T2-T1) + " ms"
Debug "Einträge: " + Str(entries)
Debug "Einträge pro Sek: " + StrD(entries/((T2-T1)/1000),2)
Debug "------------------"
T1 = ElapsedMilliseconds()
! v_mystring.split(v_crlf).forEach( function( v_value, index ) {
SelLine = Value
! });
T2 = ElapsedMilliseconds()
Debug "().forEach"
Debug "Dauer: " + Str(T2-T1) + " ms"
Debug "Einträge: " + Str(entries)
Debug "Einträge pro Sek: " + StrD(entries/((T2-T1)/1000),2)
Debug "------------------"
Grüße ... Peter
 
			 
			
					
				Re: StringField()-Alternative
				Verfasst: 10.07.2017 14:35
				von SBond
				oh ha  
 
Ja da bin ich wunschlos glücklich 
Tja dann ist heute abend wohl Kalsarikännit angesagt  
viele Grüße,
Martin