Sind C # -Strings (und andere .NET-APIs) auf 2 GB beschränkt?

7

Heute habe ich bemerkt, dass die String-Klasse von C # die Länge einer Zeichenkette als Int zurückgibt. Da ein Int immer 32 Bits lang ist, bedeutet dies, unabhängig von der Architektur, dass ein String nur 2 GB oder weniger lang sein kann?

Eine 2GB-Zeichenfolge wäre sehr ungewöhnlich und würde viele Probleme mit sich bringen. Die meisten .NET-APIs verwenden jedoch "int", um Werte wie Länge und Anzahl zu übermitteln. Bedeutet dies, dass wir für immer auf die Größe von Sammlungen beschränkt sind, die in 32-Bit passen?

Scheint wie ein grundlegendes Problem mit den .NET-APIs. Ich hätte erwartet, dass Dinge wie Anzahl und Länge über das Äquivalent von 'size_t' zurückgegeben werden.

    
Andrew 24.06.2010, 02:52
quelle

8 Antworten

15
  

Scheint wie ein grundlegendes Problem mit   die .NET API ...

Ich weiß nicht, ob ich so weit gehen würde.

Betrachten Sie fast jede Auflistungsklasse in .NET. Wahrscheinlich ist es eine Count -Eigenschaft, die eine int zurückgibt. Dies legt nahe, dass die Klasse in einer Größe von int.MaxValue (2147483647) begrenzt ist. Das ist nicht wirklich ein Problem ; Es ist eine Einschränkung - und eine durchaus vernünftige, in der überwiegenden Mehrheit der Szenarien.

Wie auch immer, was wäre die Alternative? Es gibt uint - aber das ist nicht CLS-konform. Dann gibt es long ...

Was ist, wenn Length eine long zurückgegeben hat?

  1. Weitere 32 Bit Speicher wären erforderlich, wenn Sie die Länge eines Strings kennen möchten.
  2. Der Vorteil wäre: Wir könnten Strings haben, die Milliarden Gigabyte RAM aufnehmen. Hurra.

Stellen Sie sich die unglaublichen Kosten eines solchen Codes vor:

%Vor%

Grundsätzlich, wenn Sie an string als eine Datenstruktur denken, die eine unbegrenzte Menge an Text speichern soll, haben Sie unrealistische Erwartungen. Bei Objekten dieser Größe wird es fraglich, ob Sie sie überhaupt im Speicher halten müssen (im Gegensatz zur Festplatte).

    
Dan Tao 24.06.2010 03:01
quelle
5

Korrigieren Sie, die maximale Länge wäre die Größe von Int32, aber Sie werden wahrscheinlich zu anderen Speicherproblemen kommen, wenn Sie mit Strings arbeiten, die sowieso größer sind.

    
Evan Trimboli 24.06.2010 03:01
quelle
3

Bei einem Wert von String.length () von etwa 5MB ist es nicht wirklich praktisch, String zu verwenden. String ist für kurze Textabschnitte optimiert.

Denken Sie darüber nach, was passiert, wenn Sie es tun

%Vor%

Etwas wie:

System berechnet die Länge von myString plus die Länge von "more chars"

System weist diese Speichermenge zu

System kopiert myString an einen neuen Speicherort

Das System kopiert "mehr Zeichen" nach dem letzten kopierten myString char in den neuen Speicherbereich

Der ursprüngliche myString ist der Gnade des Garbage Collectors überlassen.

Während das für kleine Textabschnitte nett und ordentlich ist, ist es ein Albtraum für große Strings, nur 2 GB zusammenhängender Speicher zu finden ist wahrscheinlich ein Showstopper.

Wenn Sie also wissen, dass Sie mehr als ein paar MB an Zeichen verarbeiten, verwenden Sie eine der * Buffer-Klassen.

    
James Anderson 24.06.2010 03:04
quelle
1

Es ist ziemlich unwahrscheinlich, dass Sie mehr als zwei Milliarden Objekte in einer einzelnen Sammlung speichern müssen. Sie werden einige ziemlich schwerwiegende Leistungseinbußen erleiden, wenn Sie Aufzählungen und Nachschlagevorgänge durchführen, die die beiden Hauptziele von Sammlungen sind. Wenn Sie mit einem so großen Datensatz arbeiten, gibt es fast sicher eine andere Route, die Sie verwenden können, z. B. die Aufteilung Ihrer einzelnen Sammlung in viele kleinere Sammlungen, die Teile der gesamten Datenmenge enthalten, mit der Sie arbeiten.

Heeeey, warte eine Sekunde ... wir haben schon dieses Konzept - es heißt ein Wörterbuch !

Wenn Sie beispielsweise 5 Milliarden englische Zeichenfolgen speichern müssen, verwenden Sie diesen Typ:

%Vor%

Nehmen wir an, dass die Schlüsselzeichenfolge die ersten beiden Zeichen der Zeichenfolge repräsentiert. Dann schreibe eine Erweiterungsmethode wie folgt:

%Vor%

und fügen Sie dann Elemente zu bigStringContainer wie folgt hinzu:

%Vor%

und nenne es einen Tag. (Es gibt offensichtlich effizientere Möglichkeiten, dies zu tun, aber dies ist nur ein Beispiel)

Oh, und wenn Sie wirklich wirklich in der Lage sein müssen, ein beliebiges Objekt nach dem absoluten Index zu suchen, verwenden Sie Array anstelle einer Sammlung. Okay, yeah, du verwendest eine Art Sicherheit, aber du kannst Array-Elemente mit einem long indexieren.

    
Warren Rumak 24.06.2010 04:05
quelle
1

Die Tatsache, dass das Framework Int32 für Count / Length Eigenschaften, Indexer usw. verwendet, ist ein bisschen wie ein Ablenkungsmanöver. Das eigentliche Problem ist, dass die CLR derzeit eine maximale Objektgrößenbeschränkung von 2 GB hat.

So kann ein string - oder jedes andere einzelne Objekt - niemals größer als 2GB sein.

Das Ändern der Eigenschaft Length des Typs string , um long , ulong oder sogar BigInteger zurückzugeben, wäre sinnlos, da Sie niemals mehr als ca. 2 ^ 30 Zeichen haben könnten (max. 2 GB und 2 Bytes pro Zeichen.)

Auch wegen der Begrenzung von 2 GB wären die einzigen Arrays, die sogar 2 ^ 31 Elemente haben könnten, bool[] oder byte[] Arrays, die nur 1 Byte pro Element verwenden.

Natürlich gibt es nichts, was Sie daran hindert, eigene Composite-Typen zu erstellen, um die Beschränkung von 2 GB zu umgehen.

(Beachten Sie, dass die obigen Ausführungen für die aktuelle Implementierung von Microsoft gelten und sich in zukünftigen Versionen sehr wohl ändern könnten. Ich bin mir nicht sicher, ob Mono ähnliche Grenzen hat.)

    
LukeH 24.06.2010 07:24
quelle
1

In Versionen von .NET vor 4.5 beträgt die maximale Objektgröße 2 GB. Ab 4.5 können Sie größere Objekte zuweisen, wenn gcAllowVeryLargeObjects aktiviert ist . Beachten Sie, dass das Limit für string nicht betroffen ist, aber "Arrays" sollten auch "Listen" abdecken, da Listen von Arrays unterstützt werden.

    
Marc Gravell 26.06.2012 06:47
quelle
0

Selbst in x64-Versionen von Windows wurde ich von .Net getroffen, die jedes Objekt auf 2GB beschränkten.

2GB ist ziemlich klein für ein medizinisches Bild. 2GB ist sogar klein für ein Visual Studio-Download-Image.

    
Windows programmer 24.06.2010 03:11
quelle
-1

Wenn Sie mit einer Datei mit 2 GB arbeiten, bedeutet dies, dass Sie wahrscheinlich viel RAM verwenden werden und die Leistung sehr langsam ist.

Verwenden Sie stattdessen für sehr große Dateien eine MemoryMappedFile (siehe: Ссылка ). Mit dieser Methode können Sie mit einer Datei von nahezu unbegrenzter Größe arbeiten, ohne das Ganze im Speicher zu laden.

    
Robert Seder 24.06.2010 04:52
quelle

Tags und Links