Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi und 64-Bit Programme (https://www.delphipraxis.net/210261-delphi-und-64-bit-programme.html)

Harry Stahl 25. Mär 2022 18:27

Delphi und 64-Bit Programme
 
Bei einem aktuellen Thread zum importieren von großen XML-Dateien habe ich mich gewundert, dass das Lesen einer 1,6 GB großen Datei nicht möglich sein sollte (also zumindest unter 64 Bit).

Habe dann mal spaßeshalber unter Windows als 64-bit-Programm versucht eine ca. 2 GB csv-Textdatei in eine Stringlist zu laden (die "star2002-full.csv" Datei von dieser Quelle: https://sdm.lbl.gov/fastbit/data/samples.html) . Das scheitert aber schon alleine daran, dass Delphi einen Integerüberlauf in der Procedure TStrings.LoadFromstream meldet.

Tja und wenn man sieht, dass dort - und an vielen anderen Stellen in der System.classes Hilfsvariablen mit dem Typ Integer deklariert sind, wird schnell klar, das kann nicht funktionieren, wenn der Inhalt oder der Wert einer Variablen größer als 2GB ist.

In der System.classes (aber auch System.Generics.collections) sind in vielen Klassen Schleifenvariablen, Enumeratoren, Rückgabewerte oder Parameter als Integer definiert.

Letztlich funktionieren alle solche Klassen nicht, wenn ein Index > 2GB ist.

Ist das heutzutage noch zeitgemäß? Wo manche Rechner inzwischen 64 GB oder mehr Arbeitsspeicher haben? Müsste nicht zumindest für die 64-Bit-Plattform hier Int64 an allen diesen Stellen verwendet werden? Ich kann mir allerdings auch vorstellen, dass das dann ein ziemlicher (Um-) Bruch wäre und zu vielen Seiteneffekten bei bestehenden Programmen führen würde.

Was meint Ihr?

Union 25. Mär 2022 18:58

AW: Delphi und 64-Bit Programme
 
Natürlich wäre es besser int64 einzusetzen und durch bedingte Compilierung auch halbwegs kompatibel zu halten. Aber auch bei < 64 bit ist es aus meiner Sicht fatal, Integer einzusetzen statt Cardinal. Das war nötig weil der Index bei Listenfunktionen durch Rückgabe von -1 als "Fehlercode" missbraucht wird. Durch diese allgemein verbreitete Unsitte wird ja auch bereits die Hälfte des Wertebereichs verschenkt.

Daniel 26. Mär 2022 06:38

AW: Delphi und 64-Bit Programme
 
Ein Int32 mit Vorzeichen geht im positiven Zahlenbereich bummelig bis 2 Milliarden.
Möglicherweise war man der Ansicht, dass eine StringList für derartige und noch größere Datenmengen schlicht der falsche Container ist. 64 Bit hin oder her.
Die Stream-Klassen beispielsweise kommen mit entsprechenden Größenordnungen zurecht.

jaenicke 26. Mär 2022 07:23

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von Harry Stahl (Beitrag 1503932)
Tja und wenn man sieht, dass dort - und an vielen anderen Stellen in der System.classes Hilfsvariablen mit dem Typ Integer deklariert sind, wird schnell klar, das kann nicht funktionieren, wenn der Inhalt oder der Wert einer Variablen größer als 2GB ist.

Das Problem ist dort, dass der Inhalt des Streams in einen einzigen String geladen wird. Und ein String hat eine feste Struktur, so dass man den Längenzähler nicht einfach auf 64-Bit erweitern kann.

Man kann in eine Stringliste aber prinzipiell auch problemlos mehr Daten laden, wenn man das Problem der Stringlänge beim Laden umgeht:
Delphi-Quellcode:
type
  TMyStringList = class(TStringList)
  private
    FNoClear: Boolean;
  public
    procedure Clear; override;
    procedure LoadFromStream(Stream: TStream; Encoding: TEncoding); override;
  end;

{ TMyStringList }

procedure TMyStringList.Clear;
begin
  if not FNoClear then
    inherited;
end;

procedure TMyStringList.LoadFromStream(Stream: TStream; Encoding: TEncoding);
var
  Size, LengthToLastLineBreak: Integer;
  Buffer: TBytes;
begin
  BeginUpdate;
  try
    FNoClear := True;
    while True do
    begin
      Size := Min(Stream.Size - Stream.Position, 1073741814);
      if Size = 0 then
        break;
      SetLength(Buffer, Size);
      Stream.Read(Buffer, 0, Size);
      Size := TEncoding.GetBufferEncoding(Buffer, Encoding, DefaultEncoding);
      SetEncoding(Encoding); // Keep Encoding in case the stream is saved
      LengthToLastLineBreak := Length(Buffer);
      while (LengthToLastLineBreak > 0) and (Buffer[LengthToLastLineBreak - 1] <> 10) do
        Dec(LengthToLastLineBreak);
      Stream.Seek(LengthToLastLineBreak - Length(Buffer), TSeekOrigin.soCurrent);
      SetTextStr(Encoding.GetString(Buffer, Size, LengthToLastLineBreak - Size));
    end;
  finally
    FNoClear := False;
    EndUpdate;
  end;
end;
Das ist jetzt nur schnell hingeschludert und funktioniert nicht für alle Zeilenumbrüche.

Harry Stahl 26. Mär 2022 12:00

AW: Delphi und 64-Bit Programme
 
Danke für Euer Feedback.

Es ging mir jetzt nicht speziell um dieses StringList-Demo. Wie man die zitierte 2GB großte Text-Datei (mit 17,5 Mio Zeilen) trotzdem in eine Stringlist laden kann, weiß ich (Daniel hat es schon angedeutet, mit Hilfe eines Streamreaders)).

Es ging mir um die generelle Frage, ob man die Klassen (z.B. mit Überladungen) auf 64-Bit Nutzung umstellen bzw. erweitern sollte. Könnte mir vorstellen, z.B. bei größeren Simulationen, wo z.B. 5 Mrd. Werte wegen der Echtzeit-Anforderung im Arbeitsspeicher gehalten müssen, es u.U. doch in irgendeinem Zusammenhang auch hilfreich sein könnte, ein TDictionary zu verwenden. Aber auch das könnte ich nicht verwenden, da dort in der Klasse z.B. "FCount" und alle anderen relevanten Zahlenwerte Integer sind.

Mir ist schon klar, dass ist hier eine Diskussion von untergeordneter Relevanz und nichts was jetzt in Delphi vorrangig behandelt werden müsste (wenn überhaupt).

Mich hat es nur interessiert, ob irgendjemand hier auch schon mal an ähnliche Grenzen in Umgang mit sehr großen Datenmengen in Zusammenhang mit 32/64 Bit Implementierung der Standard-Delphi Klassen gestoßen ist und irgendwo Erweiterungsbedarf gesehen hätte.

jaenicke 26. Mär 2022 13:09

AW: Delphi und 64-Bit Programme
 
Sicher wäre es wünschenswert, wenn es weniger Grenzen geben würde. Allerdings sollte man dabei auch nicht vergessen, dass die vorhandenen Klassen für so große Datenmengen, wie Daniel auch schon angedeutet hat, schlicht nicht ausgelegt sind.

Es wäre daher sinnvoller für diesen Zweck nicht die vorhandenen Klassen zu erweitern, sondern komplett neue zu entwickeln, die intelligenter mit solchen Datenmengen umgehen. Zum Beispiel wäre es sinnvoll, wenn man mit mehreren Threads arbeiten könnte, um so die Lade- und Zugriffszeiten zu verkleinern.

Dafür wären aber ganz andere Ansätze erforderlich als sie aktuell in Delphi implementiert sind. In anderen Systemen gibt es dafür ja auch schon einiges.

jobo 27. Mär 2022 09:42

AW: Delphi und 64-Bit Programme
 
Da kann ich nur zustimmen. Schön wär's, wenn die alten Verfahren nur mit größeren Typen kompiliert werden müssten. Aber das ist nur ein Traum.

Dann also lieber neu, mit besseren Strategien. Es gibt (jenseits von XML) Datenformate, die extra für Streaming leicht verändert werden bzw. speziell für Streaming empfohlene Verfahren.

Hab mal zum Spaß 2GB XML in VS Code geöffnet. Ich hätte es ihm zugetraut, aber auch nach diversen Warnungen "starte mich neu mit 4GB Speicherreservierung" war da nichts zu machen. Was VS Code ganz nett macht, es schaltet mit einem Hinweis das Parsing bei großen Dateien ab, deswegen war ich auf die Idee gekommen, das einfach mal doof auszuprobieren. Anderswo wird also auch nur mit Wasser gekocht.

HRolle 27. Mär 2022 15:57

AW: Delphi und 64-Bit Programme
 
Für große Textdateien, natürlich auch für große XML-Dateien, würde ich Notepad++ (kann in der neuesten Version 8.3 mit Dateien > 2GB umgehen) oder PilotEdit (kann in der professionellen Variante bis zu 400GB große Dateien editieren) empfehlen. Beide Programme arbeiten offensichtlich mit Streaming, halten also nur eine bestimmte Teilmenge des Textes im Hauptspeicher.

Für große Datenfelder, wie gelegentlich bei Simulationsrechnungen notwendig, würde ich ebenfalls mit Streams oder einer Aufteilung eines Feldes von z.B. 5Mrd Double-Werten in mehrere Teilfelder arbeiten. Der Index im Stream ist bei Delphi die Position-Eigenschaft und die ist Int64.

hoika 27. Mär 2022 18:44

AW: Delphi und 64-Bit Programme
 
Hallo,
hier widerspreche ich mal Daniel.

Einer der oft propagierten Vorteile von 64Bit ist ja gerade der Zugriff auf mehr als 2 (?), 4 GB Speicher.
Hier müsste Embarcadero auch bei StringList nacharbeiten.

Andere mit 64Bit erzeugten Programme können das ja auch.

Wobei man ja nicht weiß, wie viel RAM ein Anwender wirklich in seinem Rechner hat.
Oft wird ja Chunking benutzt, also das Aufteilen der Datei in einzelne Bereiche.
Unter 64Bit könnten größere Bereiche oder mehr Bereiche geladen werden, in Abhängigkeit des tatsächlichen Speichers.

Ich hatte mal unter 32Bit mit StringList's in einer StringList gearbeitet, dass klappte sogar ...

Der schöne Günther 27. Mär 2022 20:06

AW: Delphi und 64-Bit Programme
 
Gibt es nicht ganz genau dafür den Typ NativeInt?

Zitat:

NativeInt repräsentiert eine Untermenge der Integer-Zahlen. Der Bereich von NativeInt ist von der aktuellen Plattform abhängig. Auf 32-Bit-Plattformen entspricht NativeInt dem Typ Integer. Auf 64-Bit-Plattformen entspricht NativeInt dem Typ Int64.
Meine Schleifenvariablen, Array-Indizes usw. sind auch immer vom Typ
Delphi-Quellcode:
NativeInt
.

Ist ja in anderen Sprachen genauso (size_t in C++, isize/usize in Rust, ...).

jaenicke 27. Mär 2022 21:09

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von hoika (Beitrag 1503987)
Hier müsste Embarcadero auch bei StringList nacharbeiten.

Andere mit 64Bit erzeugten Programme können das ja auch.

Die arbeiten dann aber auch nicht mit einer String-basierten Struktur wie einer TStringList. Denn auch z.B. in C# oder anderen .NET Sprachen können Strings nicht länger sein... das Limit ist ähnlich wie bei Delphi.

Wenn man geeignete Klassen wie eben einen Stream verwendet, kann man ja auch in Delphi problemlos mehrere GiB in den Speicher schaufeln.

Sinspin 28. Mär 2022 09:32

AW: Delphi und 64-Bit Programme
 
Ich dachte das Integer der generische Typ ist und automatisch zu Int64 wird, wenn man auf 64Bit als Zielpattform übersetzt.
Früher war das jedenfalls mal so das aus 16 Bit Integer 32 Bit wurden beim Umstieg auf ein neueres Delphi (incl schöner Probleme beim lesen von Binärdateien, bei denen man keinen Gedanke auf das Anpassen des Loaders verschwendet hatte)

TheDelphiCoder 28. Mär 2022 09:41

AW: Delphi und 64-Bit Programme
 
Das war wohl so beim Wechsel von Delphi 1 zu Delphi 2.
Integer bleibt aber tatsächlich bei 4 Byte. Wenn es automatisch gehen soll, dann brauchst NativeInt bzw. NativeUInt.

jaenicke 28. Mär 2022 09:43

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von Sinspin (Beitrag 1504022)
Ich dachte das Integer der generische Typ ist und automatisch zu Int64 wird, wenn man auf 64Bit als Zielpattform übersetzt.

Das hätte man erwarten können, aber da Intel und andere den generischen Integer-Typ bei 32-Bit belassen haben, blieb kaum etwas anderes übrig als dem auch mit Delphi zu folgen, so verwirrend und folgenschwer das auch war.

Uwe Raabe 28. Mär 2022 09:52

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von Sinspin (Beitrag 1504022)
Ich dachte das Integer der generische Typ ist und automatisch zu Int64 wird, wenn man auf 64Bit als Zielpattform übersetzt.

Das ist teilweise immer noch so: Platform-dependent integer types

LongInt entspricht bei 32-Bit und bei 64-Bit Windows einem 32-Bit Wert, bei 64-bit POSIX (incl. iOS und Linux) aber einem 64-Bit Wert. Wie Sebastian schon sagte, hat man sich da an den entsprechenden Vorgaben seitens Intel und Microsoft orientiert. In C# ist ein int halt immer ein 32-Bit Wert - in Objective C aber nicht.

dummzeuch 28. Mär 2022 13:25

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von TheDelphiCoder (Beitrag 1504024)
Das war wohl so beim Wechsel von Delphi 1 zu Delphi 2.
Integer bleibt aber tatsächlich bei 4 Byte. Wenn es automatisch gehen soll, dann brauchst NativeInt bzw. NativeUInt.

Außer man verwendet (auch) noch ein älteres Delphi, bei dem NativeInt auch für 32 Bit Programme als 64 Bit deklariert ist. Das gilt für Delphi 7 bis 2007.

hoika 28. Mär 2022 23:49

AW: Delphi und 64-Bit Programme
 
Hallo,
und ich bleibe dabei.
Ein TStringList sollte unter 64Bit mehr Daten verwalten können als unter 32Bit.

Auch Embarcadero bringt ja immer das "alter Code läuft wie bisher".
Ja, aber mit 64Bit muss auch der komplette 64Bit-Speicherbereich ausgenutzt werden!

Punkt!!!

Und jetzt macht mich rot ;)

jaenicke 29. Mär 2022 00:13

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von hoika (Beitrag 1504058)
Ein TStringList sollte unter 64Bit mehr Daten verwalten können als unter 32Bit.

Dann würde mich interessieren wie du dir das konkret vorstellst? Sollen Strings deshalb eine andere interne Struktur bekommen?

Uwe Raabe 29. Mär 2022 08:46

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von hoika (Beitrag 1504058)
Ja, aber mit 64Bit muss auch der komplette 64Bit-Speicherbereich ausgenutzt werden!

Das fände ich jetzt aber sehr unfair gegenüber den anderen Anwendungen.

Sinspin 29. Mär 2022 08:58

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von jaenicke (Beitrag 1504059)
Zitat:

Zitat von hoika (Beitrag 1504058)
Ein TStringList sollte unter 64Bit mehr Daten verwalten können als unter 32Bit.

Dann würde mich interessieren wie du dir das konkret vorstellst? Sollen Strings deshalb eine andere interne Struktur bekommen?

Ja, natürlich! Wen juckt das überhaupt wie der intern aufgebaut ist? Früher war es ein Byte am Anfang und maximal 255 Bytes dahinter.
Jetzt ist es was? ...und in Zukunft? Wollen wir ehwig gestrig bleiben? Rostig? Alt?

Der Typ String ist noch immer ein reserviertes Wort im Quelltext, also Compilermagic.
Dass man die realen String Typen vieleicht besser um eine 64Bit Variante erweitert, sollte klar sein.
Aber String ist jetzt schon dynamisch das was man eingestellt hat. Warum dann unter 64Bit nicht auch 64Bit tauglich?

Dass man beim übersetzen in 64Bit den Kopf angeschaltet lassen muss sollte jedem klar sein. Bestimmte Sachen, wie einen String in eine Binärdatei schreiben oder daraus lesen ohne eine Wrapper zu verwenden der sich um 32Bit / 64Bit unterschiede kümmert ist dann halt als Dummheit zu verbuchen.

Bernhard Geyer 29. Mär 2022 09:40

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1504071)
Zitat:

Zitat von hoika (Beitrag 1504058)
Ja, aber mit 64Bit muss auch der komplette 64Bit-Speicherbereich ausgenutzt werden!

Das fände ich jetzt aber sehr unfair gegenüber den anderen Anwendungen.

:lol::lol::lol::lol::lol:

Uwe Raabe 29. Mär 2022 10:22

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von Sinspin (Beitrag 1504073)
Wen juckt das überhaupt wie der intern aufgebaut ist?

Da ist in der Tat was dran. Rein von der Speicherstruktur sehe ich da kein wirkliches Hindernis. Allerdings gibt es etliche Stellen im Source, bei denen implizit eine String-Länge und auch die Indizierung mit 32-Bit angenommen wird. Das ist ein nicht zu unterschätzender Aufwand, unweigerlich begleitet von potentiell signifikanten Fehlerquellen.

Übrigens ist WideString auch keine Alternative (eigentlich sogar ein Rückschritt), da das interne Datenformat auch hier 4 Bytes für die Länge reserviert - dummerweise diesmal in Bytes, so dass ein WideString nur halb so lang werden darf wie ein string.

TigerLilly 29. Mär 2022 16:35

AW: Delphi und 64-Bit Programme
 
Hmm. Egal, ob ich Code für 64 Bit oder 32 Bit kompiliere, ich gehe davon aus, dass der Code - nur für sich genommen - funktioniert. Schnittstellen, Dateien etc sind außen vor, das ist bei UniCode ja auch so. Dass ich mir beim Compilieren für 64 Bit überlegen muss, ob mein Code per se funktioniert, ist nicht so toll. Woher weiß ich denn, was in der RTL nicht funktionieren würde?

Uwe Raabe 29. Mär 2022 16:58

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von TigerLilly (Beitrag 1504084)
Woher weiß ich denn, was in der RTL nicht funktionieren würde?

Wenn du dich hierauf beziehst:
Zitat:

Zitat von Uwe Raabe (Beitrag 1504078)
Das ist ein nicht zu unterschätzender Aufwand, unweigerlich begleitet von potentiell signifikanten Fehlerquellen.

dann betrifft dieser Aufwand natürlich Embarcadero, sollten sie irgendwann mal 64-Bit-Strings unterstützen wollen. Für den Anwender (also uns) sollte das weitestgehend transparent sein.

jziersch 30. Mär 2022 08:24

AW: Delphi und 64-Bit Programme
 
Braucht man wirklich Strings mit Int64 Länge? Was soll das bringen.

Für grosse Daten gibts ja MemoryStreams - die haben auch nicht das Problem, dass zwischen irgendwelchen codepages hin und her gewandelt wird. Viele moderne Speicherformate verwenden nur 8 Bit, also RTF, XML, HTML ... da strings mit seinen WideChar zeichen auch nicht aussreicht alle Zeichen zu codieren. Die Speicherung solcher Daten in einen "string" fürhrt dann regelmässig zu 00nn00nn00nn00nn.

Dass ein Integer 32 bit hat, auch unter 64 bit war meiner Ansicht nach die genau richtige Entscheidung, da der Entwickler so explizit die Möglichkeit hat zu entscheiden, ob der große Typ erforderlich ist, oder nicht und "alte" Programme 1:1 laufen.

Wichtig ist es aber IntPtr zu verwenden für alle Integer die auch Speicheradressen sein können- typischerweise für die Übergabe an SendMessage u.ä.

jaenicke 30. Mär 2022 09:02

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von jziersch (Beitrag 1504097)
Für grosse Daten gibts ja MemoryStreams

Ein Memorystream ist ja nicht so recht vergleichbar. Aber auch ein TArray ist nicht auf MaxInt als Länge beschränkt und eignet sich für große Datenmengen deutlich besser als ein String.

Uwe Raabe 30. Mär 2022 09:10

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von jziersch (Beitrag 1504097)
Braucht man wirklich Strings mit Int64 Länge?

Die Frage wollte ich eigentlich auch stellen. Allein schon das Hantieren mit 2GB Strings ist schon heikel genug. Bei jedem Copy-on-Write werden da mal eben weitere 2GB am Stück belegt. Einige Dinge sollte man mit so großen Strings einfach nicht machen. 64-Bit hin oder her, das ist einfach Verschwendung und schreit schon wegen der Performance nach einem anderen Ansatz. Computer sind zwar bekanntermaßen schnell, aber bei zu vielen Daten brauchen sie halt auch ihre Zeit. Mit einem effizienteren Algorithmus wird es dann meist nicht nur schneller, sondern braucht häufig auch weniger Speicher.

Man stelle sich nur mal vor, man würde eine 32GB Textdatei in einen solchen 64-Bit String einlesen. Ist die Datei UTF-8 codiert, kommen da ca. 64GB Speicherverbrauch zusammen. Da käme so manches handelsübliche Notebook schon an seine RAM-Grenzen und müsste Speicher auslagern, der dann später wieder eingelesen werden muss. Effizient geht anders.

Ich wäre als wirklich an konkreten Beispielen interessiert, wo Strings mit mehr als 2^30 Zeichen notwendig oder hilfreich (bequemer zählt nicht) wären.

Sinspin 30. Mär 2022 12:16

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1504100)
Allein schon das Hantieren mit 2GB Strings ist schon heikel genug. Bei jedem Copy-on-Write werden da mal eben weitere 2GB am Stück belegt. Einige Dinge sollte man mit so großen Strings einfach nicht machen. 64-Bit hin oder her, das ist einfach Verschwendung und schreit schon wegen der Performance nach einem anderen Ansatz.

Es geht ja nicht um die Realität, sondern um die theoretische Fähigkeit es tuen zu können ohne das es knallt.

Allerdings ging es garnicht um String sondern um TStrings (
Delphi-Quellcode:
System.Classes.TStrings
).
Zitat:

Zitat von Uwe Raabe (Beitrag 1504100)
Man stelle sich nur mal vor, man würde eine 32GB Textdatei in einen solchen 64-Bit String einlesen.

Genau um sowas, eine Datei die etwas größer ist, in
Delphi-Quellcode:
TStrings
zu laden.
Also ein Zeilenweises array of String. Das sollte doch gehen?
Interessant ist die Frage, was passiert bei den Properties CommaText und Text, denn die sind
Delphi-Quellcode:
String
.

jaenicke 30. Mär 2022 12:58

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von Sinspin (Beitrag 1504107)
Genau um sowas, eine Datei die etwas größer ist, in
Delphi-Quellcode:
TStrings
zu laden.
Also ein Zeilenweises array of String. Das sollte doch gehen?
Interessant ist die Frage, was passiert bei den Properties CommaText und Text, denn die sind
Delphi-Quellcode:
String
.

Genau deshalb klappt das ja nicht. Die Implementierung könnte man (abgesehen von diesen Properties) relativ einfach anpassen, damit Dateioperationen möglich wären.

Aber mit TFileStream usw. gibt es ja sinnvolle Möglichkeiten für große Dateien.

Uwe Raabe 30. Mär 2022 13:14

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von Sinspin (Beitrag 1504107)
Genau um sowas, eine Datei die etwas größer ist, in
Delphi-Quellcode:
TStrings
zu laden.
Also ein Zeilenweises array of String. Das sollte doch gehen?

Das tut es ja jetzt schon, wenn man es entsprechend lädt. Also nicht mit Zuweisung von Text, CommaText oder LoadFromFile bzw. LoadFromStream. Die würden in der Tat 64-Bit Strings erfordern.

Zitat:

Zitat von Sinspin (Beitrag 1504107)
Interessant ist die Frage, was passiert bei den Properties CommaText und Text, denn die sind
Delphi-Quellcode:
String
.

Eben, das knallt dann halt. Das ist aber meiner Meinung nach durchaus OK. Es ist eigentlich nicht zu rechtfertigen, dass man, nur um solche Sonderfälle abzudecken, den ganzen Unterbau auf 64-Bit Verträglichkeit auslegt. Auch in 64-Bit sind die meisten TStrings Instanzen mit überschaubaren Inhalten versehen.

Aber wie Sebastian schon schreibt, spricht ja auch nichts dagegen eine Ableitung von TStringList zu schreiben, bei der die LoadFromStream/SaveToStream Implementierungen eben nicht über SetTextStr/GetTextStr laufen. Dann könnte man diese ja auch für größere Dateien verwenden.

Als Nebeneffekt würde auch der interne Buffer für das Encoding wegfallen. Da liegt nämlich auch noch ein Speicherfresser: Erst wird ein Buffer angelegt, der den kompletten Inhalt der Datei in den Speicher lädt. Dann wird daraus anhand des Encodings ein String gemacht, bevor dieser dann zeilenweise zerlegt in die interne Liste wandert. Das braucht dann temporär mal eben so etwa 5x soviel Speicher wie die Datei groß ist (danach dann 2x).

Wie man dann allerdings halbwegs performant mit so einer Monster-Stringliste umgehen soll steht auf einem anderen Blatt.

Stevie 30. Mär 2022 14:32

AW: Delphi und 64-Bit Programme
 
Wer ne 32GB Datei in eine TStringList läd, hat ganz andere Probleme als den Fakt, dass es bei mehr als (2^31)-1 Zeilen kracht.

Zitat:

Zitat von hoika (Beitrag 1504058)
Ein TStringList sollte unter 64Bit mehr Daten verwalten können als unter 32Bit.

Tut sie auch - eine 32bit Anwendung kann ohne large address aware 2GB Speicher verwalten, mit 3GB (32bit OS) bzw 4GB (64bit OS).

Wer sich mal die Mühe gemacht hat, in den Code von TStringList zu schauen, der wird gesehen haben, dass pro Eintrag 8 bzw 16 byte benötigt werden (TStringItemList).
D.h. dass selbst beim Eintragen von Leerstrings in eine TStringList bei einer non LAA Anwendung gerade mal Speicher für ca 268mio Einträge zur Verfügung steht.
Anders herum betrachtet heißt das, dass eine TStringList mit einer Capacity von MaxInt als 64bit Anwendung schon allein ca 32GB verbrauchen würde (MaxInt*16)! Und da sind noch gar keine Strings drin.

Mal kurz durchgerechnet, welche Mindestzeilenlänge die Datei haben müsste, wenn sie in UTF8 kodiert wäre und nur ASCII Chars enthalten würde - das wären 32GB Zeichen. Eine TStringList hat maximal Platz für 2^31-1 Einträge.
Somit müssten die Zeilen im Durchschnitt 16 Zeichen lang sein, das kommt mir doch schon sehr kurz vor für eine Datei, die man mit einer TStringList verarbeiten möchte.

Ich stand kürzlich selbst vor der Entscheidung, ob ich bei den Spring Collections auf NativeInt für Index umstellen soll oder nicht, aber da kommt man dann doch auf ganz andere Probleme, wie den Fakt, dass ein open Array auch unter 64bit seinen versteckten High Parameter nur als Int32 übergibt.

P.S. Ist auch schon eine ganze Weile lang "bekannt" (vermutlich inzwischen schon wieder vergessen worden, ist halt nicht einfach bei zig Tausend Issues in nem JIRA den Überblick zu behalten, woll)
https://quality.embarcadero.com/browse/RSP-12438

jaenicke 30. Mär 2022 17:12

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von Stevie (Beitrag 1504115)
aber da kommt man dann doch auf ganz andere Probleme, wie den Fakt, dass ein open Array auch unter 64bit seinen versteckten High Parameter nur als Int32 übergibt.

Ist nun im Hinterkopf gespeichert, gut zu wissen. :)

Sinspin 30. Mär 2022 17:45

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von Stevie (Beitrag 1504115)
Wer ne 32GB Datei in eine TStringList läd, hat ganz andere Probleme als den Fakt, dass es bei mehr als (2^31)-1 Zeilen kracht.

Ist ja alles hier auch nur theoretisch. Ich denke auch das man da an anderer Stelle schon was falsch gemacht hat wenn es soweit kommt.

Zitat:

Zitat von Stevie (Beitrag 1504115)
..., wie den Fakt, dass ein open Array auch unter 64bit seinen versteckten High Parameter nur als Int32 übergibt.

Int32 oder Cardinal? Selbst mit Int32 hat man schon ein bisschen Platz um was zu speichern.

Trotzdem gibt es Fälle in der Bildverarbeitung wo es mal eng werden kann.
Erst recht mit 32Bit Programmen. Daher lebt mein einziges 64Bit Programm unter Lazarus, da geht 64Bit schon ein bisschen länger und nicht erst seit die CE das auch erlaubt.

Stevie 30. Mär 2022 17:49

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von Sinspin (Beitrag 1504127)
Int32 oder Cardinal?

Rate doch mal

Delphi-Quellcode:
procedure Foo(const values: array of Integer);
begin
  Writeln(High(values));
end;

begin
  Foo([]);
end.

Stevie 30. Mär 2022 18:00

AW: Delphi und 64-Bit Programme
 
Zitat:

Zitat von Harry Stahl (Beitrag 1503932)
Habe dann mal spaßeshalber unter Windows als 64-bit-Programm versucht eine ca. 2 GB csv-Textdatei in eine Stringlist zu laden (die "star2002-full.csv" Datei von dieser Quelle: https://sdm.lbl.gov/fastbit/data/samples.html) . Das scheitert aber schon alleine daran, dass Delphi einen Integerüberlauf in der Procedure TStrings.LoadFromstream meldet.

Hab gerade mal in die Methode geschaut und mir ist ein bisschen :kotz: geworden. Es wird also ein buffer in der Größe des noch zu lesenden Streams erzeugt (2GB alloc). Dann wird über TEncoding ein string daraus generiert - je nach encoding des Streams also nochmal 2-4GB und der wird dann durch SetTextStr geprügelt, wo er anhand der LineBreak Eigenschaft zerpfückt wird - ein Meisterstück an Softwaredesign. :lol:

jaenicke 30. Mär 2022 18:39

AW: Delphi und 64-Bit Programme
 
So ging es mir auch, ja. Ich hatte ja schon einen Blick riskiert...

philipp.hofmann 30. Mär 2022 19:18

AW: Delphi und 64-Bit Programme
 
TStrings.LoadFromStream stört mich auch, weil dies beim Entpacken von ZIP-Dateien schon mal blöd ist.
Aber bei großen Dateien wird wahrscheinlich eh das folgende performanter sein (im ms (MemoryStream) liegt eine entpackte ZIP-Datei), weil ich theoretisch auch stückweise mit dem Ergebnis arbeiten kann:

Code:
  Result:=TStringList.Create(true);
  Result.BeginUpdate;
  reader:=TStreamReader.Create(ms);
  while (not reader.EndOfStream) do
    Result.Add(reader.ReadLine());
  Result.EndUpdate;
  Reader.Free;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:59 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz