große Strings/Dateien in EditorGadget laden

Hier könnt ihr alle Fragen zu SpiderBasic austauschen.
SBond
Beiträge: 266
Registriert: 22.05.2013 20:35
Computerausstattung: armseliger Laptop, mit wenig RAM und noch weniger CPU-Leistung. ...und die Grafikkarte.... ....naja.. da male ich doch lieber selber.
Wohnort: nahe Wolfsburg

große Strings/Dateien in EditorGadget laden

Beitrag von SBond »

Hallo Leute,

Ich stehe gerade vor dem Problem, dass das Einfügen von großen Inhalten in den Editorgadget sehr lange dauert und dieses anschließend nur noch sehr langsam reagiert.

Folgendes: Ich nutze SpiderBasic zur Überwachung von Messdaten auf einem Raspberry Pi.
Der Inhalt sieht so aus:

Code: Alles auswählen

Time [s]	Offset [ms]	Delay [ms]	Dispersion [ms]	Poll [Log2s]
1	2181.058691	5.524050	0.003832	2
2	2350.240706	5.753778	0.003832	2
3	2230.809869	5.078382	0.003832	2
4	2009.526000	5.929749	0.003832	2
5	1761.233782	5.510072	0.003832	2
6	1522.508577	5.669883	0.003832	2
7	1309.264120	5.374863	0.003832	2
8	1125.606571	5.415642	0.003832	2
9	970.654422	5.266202	0.003832	2
10	840.647550	5.478681	0.003832	2
11	732.227495	5.503962	0.003832	2
[...]
...Tab-Stop getrennte Messwerte, jedoch bis zu 500K Zeilen. Die Dateigröße liegt in diesem Fall bei ca. 20MB.
Die Messwerte werden über ein HTTP-Request angefordert und liegen anschließend in einer String-Variablen bereit.

Gibt es irgendeine Möglichkeit das Laden zu beschleunigen? APIs scheinen hier ja nicht zu gehen und ein ListIconGadget wäre mit 500K Einträgen sogar noch langsamer. :(

viele Grüße,
SBond
41 6c 73 6f 20 77 65 6e 6e 20 64 75 20 73 6f 20 76 69 65 6c 20 4c 61 6e 67 65 77 65 69 6c 65 20 68 61 73 74 2c 20 64 61 6e 6e 20 6b 61 6e 6e 73 74 20 64 75 20 61 75 63 68 20 67 6c 65 69 63 68 20 7a 75 20 6d 69 72 20 6b 6f 6d 6d 65 6e 20 75 6e 64 20 61 62 77 61 73 63 68 65 6e 2e

:D
Benutzeravatar
Kiffi
Beiträge: 10620
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: große Strings/Dateien in EditorGadget laden

Beitrag von Kiffi »

Hallo SBond,

kannst Du mir / uns mal eine Beispiel-Datei zur Verfügung stellen?

Grüße ... Peter
Hygge
Benutzeravatar
Bisonte
Beiträge: 2425
Registriert: 01.04.2007 20:18

Re: große Strings/Dateien in EditorGadget laden

Beitrag von Bisonte »

Kommen die per Request in einem Rutsch ? Also alle auf einmal ?

Mit folgendem Test dauert es in einem ListIconGadget ca. 15 Sekunden (ohne Debugger)
wenn man das Redraw ausschaltet. Bei eingeschaltetem Redraw ca. 95 Sekunden.

Code: Alles auswählen

;: generiere 500k Zeilen für das ListIcon

NewList String.s()

TimeStart = ElapsedMilliseconds()
For i = 1 To 500000
  AddElement(String())
  String() = Str(i) + #LF$ + StrF(Random(3000,1), 6) + #LF$ + StrF(Random(3000,1), 6) + #LF$ + StrF(Random(3000,1), 6) + #LF$ + Str(Random(20))
Next

MessageRequester("", "Erstellen der Strings : " + Str(ElapsedMilliseconds() - TimeStart) )

OpenWindow(0, 0, 0, 640, 480, "Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)

ListIconGadget(0, 10, 40, 620, 430, "ID", 100)
AddGadgetColumn(0, 1, "Offset", 100)
AddGadgetColumn(0, 2, "Delay", 100)
AddGadgetColumn(0, 3, "Dispersion", 100)
AddGadgetColumn(0, 4, "Poll", 100)
ButtonGadget(1, 10, 0, 100, 20, "Los")

AddKeyboardShortcut(0, #PB_Shortcut_Escape, 59999)

Repeat
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_CloseWindow
      Quit = #True
      
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 1
          TimeStart = ElapsedMilliseconds()
          ; Für anderen test einfach die Sendmessagezeilen auskommentieren
          SendMessage_(GadgetID(0), #WM_SETREDRAW, 0, 0) ; Redraw aus
          ForEach String() : AddGadgetItem(0, -1, String()) : Next
          SendMessage_(GadgetID(0), #WM_SETREDRAW, 1, 0) ; Redraw an
          MessageRequester("", "Einfügen der Strings : " + Str(ElapsedMilliseconds() - TimeStart))
      EndSelect

  EndSelect
  
Until Quit
Edit: Ups :oops: kann ja mal passiern ;)
Zuletzt geändert von Bisonte am 22.06.2017 14:02, insgesamt 1-mal geändert.
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
Kiffi
Beiträge: 10620
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: große Strings/Dateien in EditorGadget laden

Beitrag von Kiffi »

@Bisonte: Falsches Forum ;-)
Hygge
SBond
Beiträge: 266
Registriert: 22.05.2013 20:35
Computerausstattung: armseliger Laptop, mit wenig RAM und noch weniger CPU-Leistung. ...und die Grafikkarte.... ....naja.. da male ich doch lieber selber.
Wohnort: nahe Wolfsburg

Re: große Strings/Dateien in EditorGadget laden

Beitrag von SBond »

Ja, die Daten kommen zumindest in diesem Fall in einem Rutsch. ist aber auch so gewollt, um alle Daten abzurufen. Habe noch ein live-logging modus wie 'tail -f' unter Linux, aber der ist hier erstmal nicht relevant.

@Bisonte: Der Code geht leider nicht unter SpiderBasic. Aber dennoch danke für die Tipps :mrgreen:


Hier mal eine einfache Code-Grundlage:

Code: Alles auswählen

Declare.i CloseWindowEvent()
Declare.i ReadFileCallback(Status, Filename$, File, SizeRead)

Enumeration
	#Window_Main
	#Gadget_Editor
	#File
EndEnumeration

; ========================================================================


OpenWindow   (#Window_Main, 0, 0, 600, 500, "slow EditorGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
EditorGadget (#Gadget_Editor, 10, 10, 580, 480)

BindEvent (#PB_Event_CloseWindow, @CloseWindowEvent())
ReadFile  (#File, "Testdatei3.txt", @ReadFileCallback())


; ========================================================================

Procedure CloseWindowEvent()
	CloseWindow(EventWindow())
EndProcedure


Procedure ReadFileCallback(Status, Filename$, File, SizeRead)
	
	Select Status
		Case #PB_Status_Loaded
			Debug "Dateigröße: " + StrD(SizeRead/1000) + " KBytes"
						
			T1 = ElapsedMilliseconds()
			fileContent.s = ReadString(#File, #PB_File_IgnoreEOL)
			CloseFile(#File)
			Debug "Datei laden: " + Str(ElapsedMilliseconds() - T1) + " ms"
			
			T1 = ElapsedMilliseconds()
 			SetGadgetText(#Gadget_Editor, fileContent)
			Debug "in EditorGadget einfügen: " + Str(ElapsedMilliseconds() - T1) + " ms"
			
			
		Case #PB_Status_Error
			Debug "File loading has failed"
	EndSelect
EndProcedure
Den HTTP-Request und alles andere habe ich mal rausgekürzt. Der Code lädt hier eine Datei und packt den Inhalt in den EditorGadget. Je größer die Datei wird, desto länger dauert das Einfügen und um so träger reagiert die ganze Oberfläche.

Bei einer Datei mit 200K Zeilen erhalte ich folgende Debugausgabe:

Code: Alles auswählen

Dateigröße: 7193.449 KBytes
Datei laden: 712 ms
in EditorGadget einfügen: 65 ms
Die untere Messung ist auch falsch... warum auch immer. Das Einfügen dauert ca. 9 Sekunden und die Oberfläche reagiert kaum noch. Keine Ahnung wie die 65 ms zustande kommen.

Edit: Das Ergebnis kannst du natürlich mit jeder belibigen Datei reproduzieren. <)
41 6c 73 6f 20 77 65 6e 6e 20 64 75 20 73 6f 20 76 69 65 6c 20 4c 61 6e 67 65 77 65 69 6c 65 20 68 61 73 74 2c 20 64 61 6e 6e 20 6b 61 6e 6e 73 74 20 64 75 20 61 75 63 68 20 67 6c 65 69 63 68 20 7a 75 20 6d 69 72 20 6b 6f 6d 6d 65 6e 20 75 6e 64 20 61 62 77 61 73 63 68 65 6e 2e

:D
Benutzeravatar
Kiffi
Beiträge: 10620
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: große Strings/Dateien in EditorGadget laden

Beitrag von Kiffi »

@SBond: Ich meinte eine Beispiel-Datei mit Messwerten (Hast Du vielleicht falsch verstanden).
Hygge
SBond
Beiträge: 266
Registriert: 22.05.2013 20:35
Computerausstattung: armseliger Laptop, mit wenig RAM und noch weniger CPU-Leistung. ...und die Grafikkarte.... ....naja.. da male ich doch lieber selber.
Wohnort: nahe Wolfsburg

Re: große Strings/Dateien in EditorGadget laden

Beitrag von SBond »

ok.

hier sind die Testdateien. Hatte ich mit Excel generiert.

https://www.dropbox.com/s/hzdsaopzxyjiy ... t.zip?dl=0

oder hier:

EGadget.zip
41 6c 73 6f 20 77 65 6e 6e 20 64 75 20 73 6f 20 76 69 65 6c 20 4c 61 6e 67 65 77 65 69 6c 65 20 68 61 73 74 2c 20 64 61 6e 6e 20 6b 61 6e 6e 73 74 20 64 75 20 61 75 63 68 20 67 6c 65 69 63 68 20 7a 75 20 6d 69 72 20 6b 6f 6d 6d 65 6e 20 75 6e 64 20 61 62 77 61 73 63 68 65 6e 2e

:D
Micha122
Beiträge: 248
Registriert: 02.10.2011 14:45
Wohnort: Sinzig
Kontaktdaten:

Re: große Strings/Dateien in EditorGadget laden

Beitrag von Micha122 »

Hallo,
also ich denke Deine Zeitmessung ist falsch.
Habe den Code etwas geändert.

Code: Alles auswählen

Procedure ReadFileCallback(Status, Filename$, File, SizeRead)
   
   Select Status
      Case #PB_Status_Loaded
         Debug "Dateigröße: " + StrD(SizeRead/1000) + " KBytes"
                  
         Start_Zeit =  ElapsedMilliseconds()
         fileContent.s = ReadString(#File, #PB_File_IgnoreEOL)
         CloseFile(#File)
         T1 = ElapsedMilliseconds()
         Debug "Datei laden: " + Str(T1 - Start_Zeit) + " ms"
         
         Start_Zeit =  ElapsedMilliseconds()
         SetGadgetText(#Gadget_Editor, fileContent)
         T2 = ElapsedMilliseconds()
         Debug "in EditorGadget einfügen: " + Str(T2 - Start_Zeit) + " ms"
         
         
      Case #PB_Status_Error
         Debug "File loading has failed"
   EndSelect
EndProcedure
Ich bekomme folgendes Ergebnis: (getestet mit Testdatei3.txt)
Laden 911 ms
Einfügen 309 ms

Grüße

Edit: Sorry meine Zeitmessung ist das selbe in Grün. Aber bei mir stimmen die Zeiten.

Leider lässt sich der Editor nicht benutzen, zeigt zwar Text aber reagiert nicht.
War da etwas voreilig. :oops:
Barcodes for PureBasic - http://micha122.bplaced.net/
Micha122
Beiträge: 248
Registriert: 02.10.2011 14:45
Wohnort: Sinzig
Kontaktdaten:

Re: große Strings/Dateien in EditorGadget laden

Beitrag von Micha122 »

Dein Thema hat mich nun nicht losgelassen.
Das Editor Gadget scheint mit der Datei Testdatei3 wirklich überfordert zu sein.

Hier mal Dein ReadFileCallback etwas anders. Der Code funktioniert in Echtzeit inklusive "lebenden" Editor.
Geladen wird die Datei komplett, es wird allerdings nur 1/10 in das Editor Gadget geschrieben. :oops:
Versuche ich grössere Datenmengen ins Gadget zu schreiben tritt der beschriebene Effekt nach und nach auf.

Code: Alles auswählen

Procedure ReadFileCallback(Status, Filename$, File, SizeRead)
 
  *Buffer = AllocateMemory(SizeRead)
   Select Status
      Case #PB_Status_Loaded
         Debug "Dateigröße: " + StrD(SizeRead/1000) + " KBytes"
                  
         Start_Zeit =  ElapsedMilliseconds()
         ReadData(#File, *Buffer,0, SizeRead)
         String.s = PeekS(*Buffer,0, SizeRead/10, #PB_UTF8)
         CloseFile(#File)
         T1 = ElapsedMilliseconds()
         Debug "Datei laden: " + Str(T1 - Start_Zeit) + " ms"
        
         Start_Zeit =  ElapsedMilliseconds()
         SetGadgetText(#Gadget_Editor, String)
         T2 = ElapsedMilliseconds()
         Debug "in EditorGadget einfügen: " + Str(T2 - Start_Zeit) + " ms"
         
         
      Case #PB_Status_Error
         Debug "File loading has failed"
   EndSelect
EndProcedure
Grüße, Micha
Barcodes for PureBasic - http://micha122.bplaced.net/
Benutzeravatar
Kiffi
Beiträge: 10620
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: große Strings/Dateien in EditorGadget laden

Beitrag von Kiffi »

Hallo SBond,

wie man es dreht und wendet: 20 MB sind für eine Webseite kein Pappenstiel. Und wie es aussieht wird diese Datenmenge in Zukunft wohl auch noch größer werden.

Folgendes musst Du bedenken:

* Die 20 MB werden bei jedem Aufruf der Seite von Deinem Server geladen: Hoher Traffic

* Die 20 MB müssen jedes mal in ein geeignetes Format gebracht werden, damit sie angezeigt werden können. Sei es durch die PB-String-Befehle (CountString(), StringField(), etc.) oder in irgendeiner anderen Art und Weise: Das dauert.

* 500.000+ Zeilen? Wer schaut sich die Daten denn allen ernstes an?

Wie dem auch sei: Ich habe verschiedene Tests mit DataGrid-Komponenten gemacht, von denen ich der Meinung bin, dass sie auch für große Datenmengen geeignet sind. Durch die Bank weg benötigt das Eintragen der Daten in diese Komponenten übermäßig viel Zeit, in der der Browser / Rechner dann aber auch kräftig arbeiten muss (im Gegensatz zum EditorGadget oder ListIconGadget sind die DataGrids danach allerdings noch bedienbar, wenigsten ein kleiner Trost).

Der für die Anzeige großer Datenmengen beste Weg ist es, die Daten bei Bedarf zu laden. Sprich: Es werden beispielsweise die ersten 100 Zeilen geladen und angezeigt und wenn der Benutzer scrollt, so werden die benötigten Daten im Hintergrund nachgeladen (lazy loading). Das geht recht flott, spart Resourcen und einige DataGrid-Komponenten bieten das 'von Haus aus' an. Allerdings müsstest Du Deine Daten vorher in ein geeignetes Format bringen (i.A. JSON).

Wenn Du daran Interesse hättest, könnte ich Dir ein kleines Beispiel basteln. Sag Bescheid.

Grüße ... Peter
Hygge
Antworten