Berapa panjang maksimum yang mungkin dari string .NET?

239

Apa string terpanjang yang bisa dibuat di .NET? Dokumen untuk Stringkelas diam tentang pertanyaan ini sejauh yang saya bisa lihat, jadi jawaban otoritatif mungkin memerlukan pengetahuan internal. Apakah perubahan maksimum pada sistem 64-bit?

[Ini diminta lebih karena rasa ingin tahu daripada untuk penggunaan praktis - Saya tidak bermaksud membuat kode apa pun yang menggunakan string raksasa!]

McKenzieG1
sumber

Jawaban:

346

Batas teoritis mungkin 2.147.483.647, tetapi batas praktis tidak dekat itu. Karena tidak ada objek tunggal dalam program .NET mungkin lebih dari 2GB dan tipe string menggunakan UTF-16 (2 byte untuk setiap karakter), yang terbaik yang bisa Anda lakukan adalah 1.073.741.823, tetapi Anda tidak akan pernah bisa mengalokasikan itu pada mesin 32-bit.

Ini adalah salah satu situasi di mana "Jika Anda harus bertanya, Anda mungkin melakukan sesuatu yang salah."

HitScan
sumber
8
Ini jawaban yang benar. Anda lebih mungkin kehabisan memori sebelum dapat mengalokasikan cukup untuk menghabiskan panjang string. Pada boot baru Anda mungkin dapat menarik alokasi 2GB (dengan karakter 1M) seperti yang disebutkan di sini, tapi hanya itu.
Stephen Deken
4
Dengan asumsi bahwa pernyataan "tidak ada objek tunggal Anda mungkin lebih dari 2Gb" adalah akurat, ini ADALAH batas teoritis dan juga praktis - batasan pada panjang String adalah ukuran objek total, bukan kapasitas bidang Panjang.
McKenzieG1
12
Jika ada yang tertarik dengan nilai pastinya, pada mesin 64-bit saya ini adalah 1.073.741.791 (1024 · 1024 · 1024 - 33) karakter. Lihat juga pertanyaan terkait saya tentang ukuran maks. Tepatbyte[] .
svick
4
Saya tergila-gila dengan jawaban yang berisi penjelasan singkat tetapi mendalam.
Mikayil Abdullayev
3
Ada opsi untuk memungkinkan objek .NET 4.5 (dan lebih baru) menjadi lebih besar dari 2GB pada mesin 64-bit. Periksa di sini
Anderson Matos
72

Berdasarkan eksperimen saya yang sangat ilmiah dan akurat, ini unggul di mesin saya jauh sebelum 1.000.000.000 karakter. (Saya masih menjalankan kode di bawah ini untuk mendapatkan pinpoint yang lebih baik).

PEMBARUAN: Setelah beberapa jam, saya menyerah. Hasil akhir: Dapat jauh lebih besar dari 100.000.000 karakter, langsung diberikan System.OutOfMemoryExceptionpada 1.000.000.000 karakter.

using System;
using System.Collections.Generic;

public class MyClass
{
    public static void Main()
    {
        int i = 100000000;
        try
        {
            for (i = i; i <= int.MaxValue; i += 5000)
            {
                string value = new string('x', i);
                //WL(i);
            }
        }
        catch (Exception exc)
        {
            WL(i);
            WL(exc);
        }
        WL(i);
        RL();
    }

    #region Helper methods

    private static void WL(object text, params object[] args)
    {
        Console.WriteLine(text.ToString(), args);   
    }

    private static void RL()
    {
        Console.ReadLine(); 
    }

    private static void Break() 
    {
        System.Diagnostics.Debugger.Break();
    }

    #endregion
}
bdukes
sumber
35
Menerapkan pencarian biner di sini mungkin akan membantu Anda menemukan jawaban ini jauh lebih cepat ...
Mario
49

Karena Lengthproperti System.Stringadalah Int32, saya akan menebak bahwa panjang maksimum akan menjadi 2.147.483.647 karakter ( Int32ukuran maks ). Jika dibiarkan lebih lama Anda tidak bisa memeriksa Panjang karena itu akan gagal.

Ryan Farley
sumber
2
@ m.edmondson: Sebenarnya saya tidak yakin. Sebuah Array untuk contoh memiliki LongLengthkegunaan juga dan sungai longsebagai panjang. Meskipun ini adalah jawaban yang valid, itu adalah cara yang akurat untuk mengukur ini.
Willem Van Onsem
1
Tetapi dua bit pertama digunakan untuk indikasi ASCII / non-ASCII seperti yang disebutkan dalam artikel ini , jadi seharusnya 2 ^ 30 = 1 073 741 824
Saito
28

Bagi siapa pun yang datang ke topik ini terlambat, saya dapat melihat bahwa hitscan "Anda mungkin tidak boleh melakukan itu" mungkin menyebabkan seseorang bertanya apa yang harus mereka lakukan ...

Kelas StringBuilder seringkali merupakan pengganti yang mudah. Pertimbangkan salah satu kelas berbasis aliran khususnya, jika data Anda berasal dari file.

Masalahnya s += "stuff"adalah bahwa ia harus mengalokasikan area yang benar-benar baru untuk menyimpan data dan kemudian menyalin semua data lama ke dalamnya plus hal-hal baru - SETIAP DAN SETIAP LOOP ITERASI. Jadi, menambahkan lima byte ke 1.000.000 dengan s += "stuff"sangat mahal. Jika yang Anda inginkan hanyalah menulis lima byte sampai akhir dan melanjutkan dengan program Anda, Anda harus memilih kelas yang menyisakan ruang untuk pertumbuhan:

StringBuilder sb = new StringBuilder(5000);
for (; ; )
    {
        sb.Append("stuff");
    }

StringBuilderakan tumbuh secara otomatis dengan menggandakan ketika batasnya tercapai. Jadi, Anda akan melihat pertumbuhan sakit sekali di awal, sekali di 5.000 byte, lagi di 10.000, lagi di 20.000. Menambahkan string akan menimbulkan rasa sakit setiap iterasi loop.

pengguna922020
sumber
4
Ini juga perlu dicatat bahwa StringBuilder memungkinkan Anda untuk mengatur ukuran awal. Berguna jika Anda tahu Anda akan menggunakan 10.000.000 entri sebelumnya, memungkinkan Anda untuk mengabaikan beberapa krisis.
Kyle Baran
3
+1 Untuk melihat pertanyaan dan menjawab desain yang bagus. Secara komparatif, "ini adalah seberapa besar string Anda sebelum dapat meledak", berbeda dengan, "jika Anda BENAR-BENAR perlu menyimpan banyak teks, gunakan ini ..."
StevoInco
8

Panjang maksimal string di mesin saya adalah 1.073.741.791 .

Anda lihat, String tidak dibatasi oleh integer seperti yang umum diyakini.

Selain pembatasan memori, Strings tidak boleh memiliki lebih dari 2 30 ( 1.073.741.824 ) karakter, karena batas 2GB diberlakukan oleh Microsoft CLR (Common Language Runtime). 33 lebih dari yang diizinkan komputer saya.

Sekarang, inilah sesuatu yang dapat Anda coba sendiri.

Buat aplikasi konsol C # baru di Visual Studio dan kemudian salin / tempel metode utama di sini:

static void Main(string[] args)
{
    Console.WriteLine("String test, by Nicholas John Joseph Taylor");

    Console.WriteLine("\nTheoretically, C# should support a string of int.MaxValue, but we run out of memory before then.");

    Console.WriteLine("\nThis is a quickish test to narrow down results to find the max supported length of a string.");

    Console.WriteLine("\nThe test starts ...now:\n");

    int Length = 0;

    string s = "";

    int Increment = 1000000000; // We know that s string with the length of 1000000000 causes an out of memory exception.

    LoopPoint:

    // Make a string appendage the length of the value of Increment

    StringBuilder StringAppendage = new StringBuilder();

    for (int CharacterPosition = 0; CharacterPosition < Increment; CharacterPosition++)
    {
        StringAppendage.Append("0");

    }

    // Repeatedly append string appendage until an out of memory exception is thrown.

    try
    {
        if (Increment > 0)
            while (Length < int.MaxValue)
            {
                Length += Increment;

                s += StringAppendage.ToString(); // Append string appendage the length of the value of Increment

                Console.WriteLine("s.Length = " + s.Length + " at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm"));

            }

    }
    catch (OutOfMemoryException ex) // Note: Any other exception will crash the program.
    {
        Console.WriteLine("\n" + ex.Message + " at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm") + ".");

        Length -= Increment;

        Increment /= 10;

        Console.WriteLine("After decimation, the value of Increment is " + Increment + ".");

    }
    catch (Exception ex2)
    {
        Console.WriteLine("\n" + ex2.Message + " at " + DateTime.Now.ToString("dd/MM/yyyy HH:mm") + ".");

        Console.WriteLine("Press a key to continue...");

        Console.ReadKey();

    }

    if (Increment > 0)
    {
        goto LoopPoint;

    }

    Console.WriteLine("Test complete.");

    Console.WriteLine("\nThe max length of a string is " + s.Length + ".");

    Console.WriteLine("\nPress any key to continue.");

    Console.ReadKey();

}

Hasil saya adalah sebagai berikut:

Tes string, oleh Nicholas John Joseph Taylor

Secara teoritis, C # harus mendukung string int.MaxValue, tetapi kami kehabisan memori sebelum itu.

Ini adalah tes cepat untuk mempersempit hasil untuk menemukan panjang string yang didukung maksimal.

Tes dimulai ... sekarang:

s.Length = 1000000000 pada 08/05/2019 12:06

Pengecualian jenis 'System.OutOfMemoryException' dilemparkan. pada 08/05/2019 12:06. Setelah penghancuran, nilai Peningkatan adalah 100000000.

Pengecualian jenis 'System.OutOfMemoryException' dilemparkan. pada 08/05/2019 12:06. Setelah penipisan, nilai Penambahan adalah 10000000. s.Panjang = 1010000000 pada 08/05/2019 12:06 s.Panjang = 1020000000 pada 08/05/2019 12:06 s. Panjang = 1030000000 pada 08/05/2019 12 : 06 s.Panjang = 1040000000 pada 08/05/2019 12:06 s.Panjang = 1050000000 pada 08/05/2019 12:06 s.Panjang = 1060000000 pada 08/05/2019 12:06 s.Panjang = 1070000000 di 08/05/2019 12:06

Pengecualian jenis 'System.OutOfMemoryException' dilemparkan. pada 08/05/2019 12:06. Setelah penipisan, nilai Penambahan adalah 1000000. d. Panjang = 1071000000 pada 08/05/2019 12:06 d. Panjang = 1072000000 pada 08/05/2019 12:06 d. Panjang = 1073000000 pada 08/05/2019 12 : 06

Pengecualian jenis 'System.OutOfMemoryException' dilemparkan. pada 08/05/2019 12:06. Setelah penipisan, nilai Penambahan adalah 100000. d. Panjang = 1073100000 pada 08/05/2019 12:06 d. Panjang = 1073200000 pada 08/05/2019 12:06 d. Panjang = 1073300000 pada 08/05/2019 12 : 06 s.Panjang = 1073400000 pada 08/05/2019 12:06 s.Panjang = 1073500000 pada 08/05/2019 12:06 s.Panjang = 1073600000 pada 08/05/2019 12:06 s.Panjang = 1073700000 di 08/05/2019 12:06

Pengecualian jenis 'System.OutOfMemoryException' dilemparkan. pada 08/05/2019 12:06. Setelah penipisan, nilai Penambahan adalah 10000. s.Panjang = 1073710000 pada 08/05/2019 12:06 s.Panjang = 1073720000 pada 08/05/2019 12:06 s. Panjang = 1073730000 pada 08/05/2019 12 : 06 s.Panjang = 1073740000 pada 08/05/2019 12:06

Pengecualian jenis 'System.OutOfMemoryException' dilemparkan. pada 08/05/2019 12:06. Setelah decimation, nilai Increment adalah 1000. s.Length = 1073741000 pada 08/05/2019 12:06

Pengecualian jenis 'System.OutOfMemoryException' dilemparkan. pada 08/05/2019 12:06. Setelah penipisan, nilai Increment adalah 100. s.Length = 1073741100 pada 08/05/2019 12:06 s.Length = 1073741200 pada 08/05/2019 12:06 s.Length = 1073741300 pada 08/05/2019 12 : 07 d.Panjang = 1073741400 pada 08/05/2019 12:07 d.Panjang = 1073741500 pada 08/05/2019 12:07 d.Panjang = 1073741600 pada 08/05/2019 12:07 d.Panjang = 1073741700 pada 08/05/2019 12:07

Pengecualian jenis 'System.OutOfMemoryException' dilemparkan. pada 08/05/2019 12:07. Setelah penipisan, nilai Penambahan adalah 10. d. Panjang = 1073741710 pada 08/05/2019 12:07 d. Panjang = 1073741720 pada 08/05/2019 12:07 d. Panjang = 1073741730 pada 08/05/2019 12 : 07 d.Panjang = 1073741740 pada 08/05/2019 12:07 d.Panjang = 1073741750 pada 08/05/2019 12:07 d.Panjang = 1073741760 pada 08/05/2019 12:07 d.Panjang = 1073741770 pada 08/05/2019 12:07 s.Length = 1073741780 pada 08/05/2019 12:07 s.Length = 1073741790 pada 08/05/2019 12:07

Pengecualian jenis 'System.OutOfMemoryException' dilemparkan. pada 08/05/2019 12:07. Setelah decimation, nilai Increment adalah 1. s.Length = 1073741791 pada 08/05/2019 12:07

Pengecualian jenis 'System.OutOfMemoryException' dilemparkan. pada 08/05/2019 12:07. Setelah decimation, nilai Increment adalah 0. Tes selesai.

Panjang maksimal string adalah 1073741791.

Tekan tombol apa saja untuk melanjutkan.

Panjang maksimal string pada mesin saya adalah 1073741791.

Saya akan sangat menghargai jika orang dapat memposting hasil mereka sebagai komentar di bawah ini.

Akan menarik untuk dipelajari jika orang mendapatkan hasil yang sama atau berbeda.

WonderWorker
sumber
"Kamu tahu, String tidak dibatasi oleh integer seperti yang dipercayai umum." -> integer di c # dapat naik ke 2.147.483.647 dan hasil Anda sangat dekat (32 byte kurang) dengan nilai ini dibagi dua, yang logis karena setiap karakter String disimpan sebagai Unicode pada dua byte. Jadi, bahkan jika batas tidak dikenakan oleh ukuran bilangan bulat, itu sangat dekat dengannya.
Ben
2

200 MB ... pada titik mana aplikasi Anda terhenti virtual, memiliki sekitar satu set memori yang bekerja, dan o / s mulai bertindak seperti Anda harus reboot.

static void Main(string[] args)
{
    string s = "hello world";
    for(;;)
    {
        s = s + s.Substring(0, s.Length/10);
        Console.WriteLine(s.Length);
    }
}

12
13
14
15
16
17
18
...
158905664
174796230
192275853
211503438
loudej
sumber
5
Saya tidak yakin perilaku yang Anda dapatkan dari membuat hanya satu string yang sangat besar sama dengan apa yang Anda lihat dengan mengalokasikan banyak dari mereka dan menggabungkannya.
Casey
2

Karena String.Lengthmerupakan bilangan bulat (alias untuk Int32), ukurannya terbatas pada Int32.MaxValuekarakter unicode. ;-)

VVS
sumber