PB 5.40 Beta 3: Erster Aufruf von ComposeJSON() sehr langsam

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Kiffi
Beiträge: 10719
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

PB 5.40 Beta 3: Erster Aufruf von ComposeJSON() sehr langsam

Beitrag von Kiffi »

Hallo,

ich baue ein einfaches JSON nach folgendem Schema zusammen:

Code: Alles auswählen

{
    "records": [
        { // erster Record
            "name1": "value1",
            "name2": "value2",
            "name3": "value3",
            "name4": "value4",
            "name5": "value5"
        },
        // nächste Records...
        // [...]
    ]
}
Ist also keine komplizierte Struktur; sind nur viele Records.

Hiernach lasse ich mir das JSON mit ComposeJSON() als String zurückgeben. Dabei ist mir aufgefallen, dass ComposeJSON() relativ langsam ist.

Aus diesem Grund habe ich mir einen kleinen Geschwindigkeitstest zusammengebaut:

Code: Alles auswählen

Procedure.s JsonTest(CountRows)
	
	Protected ReturnValue.s
	Protected j, jRoot, jRows, jRow, jArray, jCol
	Protected RowCounter, CountColumns, ColumnCounter
	
	j = CreateJSON(#PB_Any)
	
	If j
		
		jRoot  = SetJSONObject(JSONValue(j))
		jRows  = AddJSONMember(jRoot, "records")
		jArray = SetJSONArray(jRows)
		
		For RowCounter = 1 To CountRows
			jRow = SetJSONObject(AddJSONElement(jArray))
			For ColumnCounter = 1 To 5
				jCol = AddJSONMember(jRow, "name" + Str(ColumnCounter))
				SetJSONString(jCol, "value" + Str(ColumnCounter))
			Next
		Next
		
		ReturnValue = ComposeJSON(j)
		
		FreeJSON(j)
		
	EndIf
	
	ProcedureReturn ReturnValue
	
EndProcedure

Define z1,z2
Define CountRows
Define Result.s

For CountRows = 100000 To 110000 Step 1000
	z1=ElapsedMilliseconds()
	JsonTest(CountRows)
	z2=ElapsedMilliseconds()
	Result + "Anzahl Zeilen: " + Str(CountRows) + " / Zeit gesamt: " + Str(z2-z1) + " (" + StrF( (z2-z1) / CountRows) + " pro Zeile)" + #CRLF$
Next

MessageRequester("!", Result)
Mit diesem Code baue ich von 100.000 Records bis 110.000 Records in 1000er Schritten jeweils ein JSON zusammen und lasse mir das Ergebnis als String zurückgeben. Ich messe dabei die einzelnen Zeiten.

Zu meiner Verwunderung habe ich folgendes Ergebnis bekommen:
Anzahl Zeilen: 100000 / Zeit gesamt: 47838 (0.4783799946 pro Zeile)
Anzahl Zeilen: 101000 / Zeit gesamt: 1995 (0.0197524745 pro Zeile)
Anzahl Zeilen: 102000 / Zeit gesamt: 2026 (0.019862745 pro Zeile)
Anzahl Zeilen: 103000 / Zeit gesamt: 2044 (0.0198446605 pro Zeile)
Anzahl Zeilen: 104000 / Zeit gesamt: 2025 (0.0194711536 pro Zeile)
Anzahl Zeilen: 105000 / Zeit gesamt: 2070 (0.0197142866 pro Zeile)
Anzahl Zeilen: 106000 / Zeit gesamt: 2101 (0.0198207553 pro Zeile)
Anzahl Zeilen: 107000 / Zeit gesamt: 2096 (0.0195887852 pro Zeile)
Anzahl Zeilen: 108000 / Zeit gesamt: 2140 (0.0198148154 pro Zeile)
Anzahl Zeilen: 109000 / Zeit gesamt: 2174 (0.0199449547 pro Zeile)
Anzahl Zeilen: 110000 / Zeit gesamt: 2128 (0.0193454549 pro Zeile)
Sprich: Der erste Aufruf ist ca. 20 (!) mal langsamer als alle darauffolgenden.

Könnt Ihr das bei Euch nachvollziehen?

Grüße ... Peter
a²+b²=mc²
freak
PureBasic Team
Beiträge: 766
Registriert: 29.08.2004 00:20
Wohnort: Stuttgart

Re: PB 5.40 Beta 3: Erster Aufruf von ComposeJSON() sehr lan

Beitrag von freak »

Das JSON wird im Buffer für String-Operationen zusammengebaut. Dieser wird beim ersten mal zunächst schrittweise vergrößert bis entsprechend Platz ist. Das lässt sich beschleunigen in dem man mit einer entsprechenden String-Operation den Buffer auf die nötige Größe bringt:

Code: Alles auswählen

Space(100000000)
Damit hat man eine große Allokation anstatt vieler einzelner Vergrößerungen.
Benutzeravatar
Kiffi
Beiträge: 10719
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: PB 5.40 Beta 3: Erster Aufruf von ComposeJSON() sehr lan

Beitrag von Kiffi »

Sauber! Jetzt läuft's flott :allright: Danke für Deine schnelle Antwort!

Grüße ... Peter
a²+b²=mc²
Antworten