AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi JSONValue zu wenig Arbeitsspeicher bei Array von 100MB
Thema durchsuchen
Ansicht
Themen-Optionen

JSONValue zu wenig Arbeitsspeicher bei Array von 100MB

Ein Thema von stalkingwolf · begonnen am 16. Mär 2021 · letzter Beitrag vom 17. Mär 2021
Antwort Antwort
Seite 1 von 3  1 23      
stalkingwolf

Registriert seit: 6. Mai 2011
540 Beiträge
 
#1

JSONValue zu wenig Arbeitsspeicher bei Array von 100MB

  Alt 16. Mär 2021, 09:31
Folgendes Szenario. Wir fragen einen JSON Array mit Bildern ab, welcher teilweise über 100MB wird. z.b 20 Dateien a 5MB.

Wenn ich diesen auf Seiten meiner APP in FMX Anfrage wird der Array über 500MB und mit dem umwandeln von JSONValue in TJSONArray knallt mir das Programm mit der Meldung zu wenig Arbeitsspeicher weg ( 32Bit ca 1GB ist Ende ).

Auszug aus dem Quellcode :
Code:
var
RESTResponse  : TRESTResponse;
JSONArray      : TJSONArray;
jValue         : TJSONValue;
begin
.
.
jValue     := RESTResponse.JSONValue;
JSONArray  := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(jValue.ToString),0) as TJSONArray;
Beide Zeilen bei 100MB Input ca 500MB Speicher. und ich kann es auch nicht wirklich umgehen.
Wenn ich das ganze im RestClient in Firefox anstarte verbraucht Firefox 2,7GB!

Frage ist. Gehe ich falsch an das Thema dran?
Ich werde nun unsere Aufrufe und Anfragen ändern, so dass ich die Dateien in kleinen Paketen übergebe und nicht einen großen Array.
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.197 Beiträge
 
Delphi 10.4 Sydney
 
#2

AW: JSONValue zu wenig Arbeitsspeicher bei Array von 100MB

  Alt 16. Mär 2021, 09:47
Na dann kompilier doch mit 64-Bit.

Wenn man meint das man JSON-Daten mit 100 MB hat, dann muss man entweder "rumtrixen" um nicht für 100 MB-Text ein xfaches an Objekten zu haben
(Bei xml gäbes es ja Möglichkeiten "beim drüberlesen" nur relative wenige aktive Objektinstanzen zu haben.

Alternativ einfach ein 64-Bit Compilierung nehmen.
Dann braucht man halt viel RAM - Aber was solls. Dafür ist der RAM ja da.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#3

AW: JSONValue zu wenig Arbeitsspeicher bei Array von 100MB

  Alt 16. Mär 2021, 09:52
Effektiv bekommt man in Win32-Programmen (die standardmäßig nur 2 GB haben) ab etwa 700MB Probleme, wenn man versucht das als ein Block in den Arbeitsspeicher zu bekommen.
Denn der kleine Speicher ist fragmentiert ... überall liegen die EXE, DLLs und sonstwas rum.

Zusätzlich braucht man beim Laden von "Texten" vorübergehend bis zum 5-fachen als Speicher.

z.B.
* Datei laden (die Bytes) -> 1x (1 Byte pro Char)
* das in einen String konertieren t.B. Bytes mit ANSI drin in einen UnicodeString (TEncoding) -> 2x (2 Byte pro Char)
* und dann den String verarbeiten und die Inhalte in Einzelstrings kopieren -> 2x (2 Byte pro Char)
1+2+2 = 5
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: JSONValue zu wenig Arbeitsspeicher bei Array von 100MB

  Alt 16. Mär 2021, 10:01
Habt ihr Einfluss auf die Datenquelle?
Wenn ja, müsst ihr überlegen, ob das so gut ist, die großen Binary-Daten per Base64 in ein JSON zu packen.
Dafür war das eigentlich nicht gedacht. Sprich: Kann man so machen, aber dann ist es halt kacke.

Zum Weiterlesen:
https://stackoverflow.com/questions/...-a-json-object
  Mit Zitat antworten Zitat
Bbommel

Registriert seit: 27. Jun 2007
Ort: Köln
655 Beiträge
 
Delphi 12 Athens
 
#5

AW: JSONValue zu wenig Arbeitsspeicher bei Array von 100MB

  Alt 16. Mär 2021, 10:05
Code:
jValue     := RESTResponse.JSONValue;
JSONArray  := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(jValue.ToString),0) as TJSONArray;
Hm, nicht direkt die Antwort auf deine Frage, aber über folgendes bin ich auch noch gestolpert. Du hast in jValue vom RestResponse schon das ausgewertete JSON stehen, gibst das dann wieder als String aus, um es erneut zu interpretieren und dann als JSON-Array einzulesen. Das ist ein bisschen wie eine Word-Datei ausdrucken, um sie dann wieder als PDF einzuscannen. Oder hat das hier irgendeinen Hintergrund, weil sonst die Bilder nicht richtig rüberkommen?

Ggf. brauchst du dadurch auch schon doppelt so viele Ressourcen wie eigentlich nötig, insofern hätte es dann schon etwas mit deinem Problem zu tun. Eigentlich sollte ein...

Delphi-Quellcode:
jValue := RESTResponse.JSONValue;
if jValue is TJSONArray then begin
  JSONArray := TJSONArray(jValue);
  // weiteres Zeug hier..
end;
...völlig reichen und spart Rechenleistung und Speicher.
  Mit Zitat antworten Zitat
stalkingwolf

Registriert seit: 6. Mai 2011
540 Beiträge
 
#6

AW: JSONValue zu wenig Arbeitsspeicher bei Array von 100MB

  Alt 16. Mär 2021, 10:19
Danke für die ganzen Antworten.

Die Daten waren am Anfang nicht vorgesehen das sie so groß werden, allerdings pumpt uns nun ein Kunde 5MB JPGs rein und zwar nicht 4-5 sondern 20-50.
D.h wie haben nicht direkt Einfluss darauf.

Daher habe ich atm auch nur ein 32BIT SDK drauf und wollte vorher prüfen ob es Alternativen gibt.

bezüglich dem wandeln in JsonValue. Da war noch eine Abprüfung dazwischen
Code:
erg := copy(jValue.ToString,1,10);
if trim(erg) <> '[[null]]' then begin
das habe ich nun aber umgeschrieben und benötige weniger Speicher. Aber dennoch ist es bei mehr Dateien dann das gleiche Ergebnis.

Ich werde nun das ganze umschreiben auf Einzeldateien.
Wir haben schon Zugriff auf Script was sendet und das APP was empfängt.
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: JSONValue zu wenig Arbeitsspeicher bei Array von 100MB

  Alt 16. Mär 2021, 10:20
Davon abgesehen, kannst du ggf. ein paar Schritte sparen.
Das folgende gilt für die mir vorliegende Delphi Tokyo Version, kann in späteren Ausgaben also anders aussehen.

Du holst dir vom RestResponse per Property JSONValue den geparsten JSON-Text als TJSONValue-Instanz.
Wie wir sehen, wird dafür den Inhalt von TCustomRESTResponse.Content erstmal geparst und die TJSONValue-Instanz konstruiert.

Delphi-Quellcode:
function TCustomRESTResponse.GetJSONValue: TJsonValue;
var
  LTemp: Boolean;
begin
  Result := nil;
  if Content <> 'then
    try
      GetJSONResponse(Result, LTemp);
    except
      // This method ignores exceptions
    end;
end;
Das wird dann innerhalb von TCustomRESTResponse.GetJSONResponse und tiefer in TJSONObject.ParseJSONValue und TJSONObject.ParseValue entsprechend komplexer, aufwendiger und speicherintensiv.
Dann nimmst du die TJSONValue-Instanz und rufst die ToString Methode auf.
Also um das gerade geparste Objekt wieder zu einen String zu konvertieren (Moment, was?).
Ich nehme an, wir kommen da in TJSONArray.ToString raus und erzeugen uns hier per TStringBuilder den Rückgabe-String.

Ich schlage vor, du versuchst mal folgende zwei Möglichkeiten:

1) Direkte Nutzung von RESTResponse1.Content
Delphi-Quellcode:
var
  JSONArray: TJSONArray;
  JValueAsString: string;
  JValueAsBytes: TBytes;
begin
  JValueAsString := RESTResponse.Content;
  JValueAsBytes := TEncoding.UTF8.GetBytes(JValueAsString);
  JSONArray := TJSONObject.ParseJSONValue(JValueAsBytes, 0) as TJSONArray;
end;

2) Direkte Nutzung von RESTResponse1.RawBytes
Delphi-Quellcode:
var
  JSONArray: TJSONArray;
  JValueAsBytes: TBytes;
begin
  JValueAsBytes := RESTResponse1.RawBytes;
  JSONArray := TJSONObject.ParseJSONValue(JValueAsBytes, 0) as TJSONArray;
end;
Ich bin mir an der Stelle nicht sicher, wie sich das da mit dem Encoding verhält.
Ihr konvertiert ja nicht ohne Grund explizit nach UTF-8.
Aber so als Startpunkt für weitere Optimierung ist das vielleicht schon eine gute Ausgangsbasis.

Geändert von TiGü (16. Mär 2021 um 10:22 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.070 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: JSONValue zu wenig Arbeitsspeicher bei Array von 100MB

  Alt 16. Mär 2021, 10:26
Wir haben schon Zugriff auf Script was sendet und das APP was empfängt.
Dann so umändern, dass ihr da keine Base64-Binärdateien empfängt, sondern eine URL, mit der ihr später gesondert und einzeln die Bilder runterladen und verarbeiten könnt.
  Mit Zitat antworten Zitat
Benutzerbild von Union
Union

Registriert seit: 18. Mär 2004
Ort: Luxembourg
3.492 Beiträge
 
Delphi 7 Enterprise
 
#9

AW: JSONValue zu wenig Arbeitsspeicher bei Array von 100MB

  Alt 16. Mär 2021, 10:34
Du könntest auf TJSONTextReader umstellen und als Datenlieferant den Response-Stream verwenden.
Ibi fas ubi proxima merces
sudo /Developer/Library/uninstall-devtools --mode=all
  Mit Zitat antworten Zitat
stalkingwolf

Registriert seit: 6. Mai 2011
540 Beiträge
 
#10

AW: JSONValue zu wenig Arbeitsspeicher bei Array von 100MB

  Alt 16. Mär 2021, 10:41
Wir haben schon Zugriff auf Script was sendet und das APP was empfängt.
Dann so umändern, dass ihr da keine Base64-Binärdateien empfängt, sondern eine URL, mit der ihr später gesondert und einzeln die Bilder runterladen und verarbeiten könnt.
Das geht nicht. Der Content ist nicht von aussen erreichbar.
Aber vom Prinzip stelle ich das gerade auf einzeln um. Erst die Liste der Dateien und dann die Dateien einzeln.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:56 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz