Apa cara paling efisien untuk menggabungkan string?
c#
.net
string
optimization
jimmij
sumber
sumber
StringBuilder
kasus penggunaan dapat ditemukan di sini .String.Format
pada steroid. Yang mana, kinerja bijaksana, sedikit lebih lambat di satu liners daripada+
danString.Concat
, tetapi jauh lebih baik daripada itu, meskipun lebih lambat daripadaStringBuilder
, di beberapa panggilan. Secara praktis, perbedaan kinerja sedemikian rupa sehingga, jika saya harus memilih hanya satu cara untuk menggabungkan, saya akan memilih interpolasi string menggunakan$
... Jika dua cara, kemudian tambahkanStringBuilder
ke kotak alat saya. Dengan dua cara itu Anda sudah siap.String.Join
jawaban di bawah ini tidak melakukan+
keadilan dan, secara praktis, cara yang buruk untuk string concatenate, tetapi kinerja sangat cepat bijaksana. Jawabannya menarik.String.Concat
danString.Join
keduanya dapat bekerja pada array, tetapiString.Join
sebenarnya lebih cepat. Rupanya,String.Join
cukup canggih dan lebih dioptimalkan daripadaString.Concat
, sebagian karena beroperasi mirip denganStringBuilder
yang menghitung panjang string pertama dan kemudian membangun string yang diuntungkan dari pengetahuan ini menggunakan UnSafeCharBuffer.String.Join
juga membutuhkan membangun sebuah array yang tampaknya tidak efisien sumber daya kan? ... Ternyata itu+
danString.Concat
membangun array untuk konstituen mereka. Akibatnya, secara manual membuat array dan memberi makan ituString.Join
relatif lebih cepat ... namun,StringBuilder
masih mengungguliString.Join
dalam setiap cara praktis sementara$
hanya sedikit lebih lambat dan lebih cepat di string panjang ... belum lagi bahwa itu canggung dan jelek untuk digunakanString.Join
jika Anda memiliki untuk membuat array untuk itu di tempat.Jawaban:
The
StringBuilder.Append()
Metode jauh lebih baik daripada menggunakan+
operator. Tetapi saya telah menemukan bahwa, ketika menjalankan 1000 concatenations atau kurang,String.Join()
bahkan lebih efisien daripadaStringBuilder
.Satu-satunya masalah dengan
String.Join
adalah Anda harus menyatukan senar dengan pembatas umum.Sunting: seperti yang ditunjukkan @ryanversaw , Anda dapat membuat pembatas
string.Empty
.sumber
StringBuilder
memiliki biaya awal yang sangat besar, hanya efisien bila digunakan dengan string yang sangat besar, atau sangat banyak rangkaian. Bukan hal sepele untuk mencari tahu situasi apa pun. Jika kinerja bermasalah, membuat profil adalah teman Anda (periksa SEMUT).string.Concat
?Rico Mariani , guru .NET Performance, memiliki artikel tentang hal ini. Ini tidak sesederhana yang diduga. Saran dasar adalah ini:
Namun artikel lain untuk mendukung klaim ini berasal dari Eric Lippert di mana ia menggambarkan optimasi yang dilakukan pada satu baris
+
gabungan secara terperinci.sumber
Ada 6 jenis rangkaian string:
+
simbol ).string.Concat()
.string.Join()
.string.Format()
.string.Append()
.StringBuilder
.Dalam percobaan, telah terbukti bahwa itu
string.Concat()
adalah cara terbaik untuk mendekati jika kata-katanya kurang dari 1000 (kurang-lebih) dan jika kata-kata lebih dari 1000 makaStringBuilder
harus digunakan.Untuk informasi lebih lanjut, periksa situs ini .
sumber
+
sebenarnya 3 milidetik lebih cepat daripadastring.Concat()
, meskipun saya belum melihat ke dalam jumlah string yang diperlukan sebelumstring.Concat()
kehabisan+
.From Chinh Do - StringBuilder tidak selalu lebih cepat :
Aturan Jempol
Saat menggabungkan tiga nilai string dinamis atau kurang, gunakan gabungan string tradisional.
Saat menggabungkan lebih dari tiga nilai string dinamis, gunakan
StringBuilder
.Saat membuat string besar dari beberapa string literal, gunakan
@
string string literal atau inline +.Sebagian besar waktu
StringBuilder
adalah taruhan terbaik Anda, tetapi ada kasus-kasus seperti yang ditunjukkan dalam posting bahwa Anda setidaknya harus memikirkan setiap situasi.sumber
Jika Anda beroperasi dalam satu lingkaran,
StringBuilder
mungkin ini cara yang harus dilakukan; ini menghemat biaya pembuatan string baru secara teratur. Dalam kode yang hanya akan berjalan sekali,String.Concat
mungkin saja baik-baik saja.Namun, Rico Mariani (.NET optimisasi guru) membuat kuis di mana ia menyatakan pada akhirnya bahwa, dalam banyak kasus, ia merekomendasikan
String.Format
.sumber
Ini adalah metode tercepat yang telah saya kembangkan selama satu dekade untuk aplikasi NLP skala besar saya. Saya memiliki variasi untuk
IEnumerable<T>
dan tipe input lainnya, dengan dan tanpa pemisah dari tipe yang berbeda (Char
,String
), tetapi di sini saya menunjukkan kasus sederhana menggabungkan semua string dalam array menjadi string tunggal, tanpa pemisah. Versi terbaru di sini dikembangkan dan diuji unit pada C # 7 dan .NET 4.7 .Ada dua kunci untuk kinerja yang lebih tinggi; yang pertama adalah melakukan pra-perhitungan ukuran total persis yang dibutuhkan. Langkah ini sepele ketika input adalah array seperti yang ditunjukkan di sini. Untuk penanganan
IEnumerable<T>
sebagai gantinya, ada baiknya mengumpulkan string menjadi array sementara untuk menghitung total (Array diperlukan untuk menghindari memanggilToString()
lebih dari sekali per elemen karena secara teknis, mengingat kemungkinan efek samping, hal itu dapat mengubah semantik yang diharapkan. dari operasi 'string join').Selanjutnya, mengingat ukuran alokasi total string akhir, dorongan terbesar dalam kinerja diperoleh dengan membangun string hasil di tempat . Melakukan hal ini memerlukan teknik (mungkin kontroversial) untuk sementara menangguhkan ketidakmampuan baru
String
yang awalnya dialokasikan penuh dengan nol. Terlepas dari kontroversi semacam itu, bagaimanapun ...Kode lengkap:
Saya harus menyebutkan bahwa kode ini memiliki sedikit modifikasi dari apa yang saya gunakan sendiri. Dalam dokumen asli, saya memanggil instruksi cpblk IL dari C # untuk melakukan penyalinan yang sebenarnya. Untuk kesederhanaan dan portabilitas dalam kode di sini, saya menggantinya dengan P / Invoke
memcpy
, seperti yang Anda lihat. Untuk kinerja tertinggi pada x64 ( tapi mungkin bukan x86 ), Anda mungkin ingin menggunakan metode cpblk .sumber
string.Join
lakukan semua hal ini untuk Anda. Tidak perlu menulisnya sendiri. Itu menghitung ukuran string terakhir, membangun string ukuran itu, dan kemudian menulis ke array karakter yang mendasarinya. Bahkan memiliki bonus menggunakan nama variabel yang dapat dibaca dalam proses.String.Join
bisa efisien. Seperti yang saya sebutkan di intro, kode di sini hanyalah ilustrasi paling sederhana dari rangkaian fungsi yang saya gunakan untuk skenario yangString.Join
tidak ditangani (seperti mengoptimalkanChar
pemisah) atau tidak menangani dalam versi .NET sebelumnya. Saya kira saya seharusnya tidak mengambil ini sebagai contoh paling sederhana, karena ini adalah kasus yangString.Join
sudah menangani dengan baik, meskipun dengan "inefisiensi," kemungkinan tidak terukur, memproses pemisah yang kosong, yaitu.String.Empty
.Concat
, yang juga melakukan ini dengan benar. Bagaimanapun Anda tidak perlu menulis kode sendiri.String.Join
versus kode saya menggunakan test harness ini . Untuk 10 juta operasi penggabungan acak masing-masing hingga 100 string berukuran kata, kode yang ditunjukkan di atas secara konsisten 34% lebih cepat daripadaString.Join
pada rilis rilis x64 dengan .NET 4.7 . Karena OP secara eksplisit meminta metode "paling efisien", hasilnya menunjukkan bahwa jawaban saya berlaku. Jika ini mengatasi masalah Anda, saya mengundang Anda untuk mempertimbangkan kembali downvote Anda.Dari artikel MSDN ini :
Jadi, jika Anda mempercayai MSDN, gunakan StringBuilder jika Anda harus melakukan lebih dari 10 operasi string / gabungan - jika tidak, string string sederhana dengan '+' tidak masalah.
sumber
Penting juga untuk menunjukkan bahwa Anda harus menggunakan
+
operator jika Anda menggabungkan string string .How to: Concatenate Multiple Strings (Panduan Pemrograman C #)
sumber
Menambah jawaban lain, harap diingat bahwa StringBuilder dapat diberi tahu jumlah memori awal yang akan dialokasikan .
Berulang kali menambahkan ke StringBuilder yang belum dialokasikan sebelumnya dapat menghasilkan banyak alokasi yang tidak perlu seperti berulang kali merangkai string biasa.
Jika Anda tahu berapa lama string terakhir akan, dapat menghitungnya secara sepele, atau dapat membuat tebakan yang berpendidikan tentang kasus umum (mengalokasikan terlalu banyak tidak selalu merupakan hal yang buruk), Anda harus memberikan informasi ini kepada konstruktor atau Properti kapasitas . Terutama ketika menjalankan tes kinerja untuk membandingkan StringBuilder dengan metode lain seperti String.Concat, yang melakukan hal yang sama secara internal. Setiap tes yang Anda lihat online yang tidak termasuk pra-alokasi StringBuilder dalam perbandingannya salah.
Jika Anda tidak dapat menebak apa pun tentang ukuran, Anda mungkin menulis fungsi utilitas yang seharusnya memiliki argumen opsional sendiri untuk mengendalikan pra-alokasi.
sumber
Mengikuti mungkin merupakan satu solusi alternatif untuk menggabungkan beberapa string.
interpolasi string
sumber
String.Format
tetapi lebih mudah dibaca dan mudah digunakan. Bench-menandai itu, itu sedikit lebih lambat dari+
danString.Concat
pada satu baris gabungan tetapi jauh lebih baik daripada keduanya pada panggilan berulang membuatStringBuilder
kurang perlu.Yang paling efisien adalah menggunakan StringBuilder, seperti:
@jonezy: String.Compat baik-baik saja jika Anda memiliki beberapa hal kecil. Tetapi jika Anda menggabungkan megabita data, program Anda kemungkinan akan bertambah.
sumber
Coba 2 buah kode ini dan Anda akan menemukan solusinya.
Vs
Anda akan menemukan bahwa kode 1 akan berakhir sangat cepat dan memori akan dalam jumlah yang baik.
Kode kedua mungkin memori akan baik-baik saja, tetapi akan memakan waktu lebih lama ... lebih lama. Jadi jika Anda memiliki aplikasi untuk banyak pengguna dan Anda membutuhkan kecepatan, gunakan tanggal 1. Jika Anda memiliki aplikasi untuk aplikasi satu pengguna jangka pendek, mungkin Anda bisa menggunakan keduanya atau yang ke-2 akan lebih "alami" untuk pengembang.
Bersulang.
sumber
Untuk hanya dua string, Anda pasti tidak ingin menggunakan StringBuilder. Ada beberapa ambang di atas yang overhead StringBuilder kurang dari overhead mengalokasikan beberapa string.
Jadi, untuk lebih dari 2-3 string, gunakan kode DannySmurf . Jika tidak, cukup gunakan operator +.
sumber
System.String tidak dapat diubah. Ketika kita memodifikasi nilai variabel string maka memori baru dialokasikan ke nilai baru dan alokasi memori sebelumnya dirilis. System.StringBuilder dirancang untuk memiliki konsep string yang dapat berubah di mana berbagai operasi dapat dilakukan tanpa mengalokasikan lokasi memori yang terpisah untuk string yang dimodifikasi.
sumber
Solusi lain:
di dalam loop, gunakan List sebagai ganti string.
ini sangat sangat cepat.
sumber
Itu sangat tergantung pada pola penggunaan Anda. Patokan terperinci antara string.Gabung, string, Concat, dan string.Format dapat ditemukan di sini: String.Format Tidak Cocok untuk Pencatatan Intensif
(Ini sebenarnya jawaban yang sama yang saya berikan untuk pertanyaan ini )
sumber
Itu akan tergantung pada kode. StringBuilder umumnya lebih efisien, tetapi jika Anda hanya menggabungkan beberapa string dan melakukan semuanya dalam satu baris, optimasi kode kemungkinan akan mengaturnya untuk Anda. Sangat penting untuk memikirkan bagaimana kode terlihat juga: untuk set yang lebih besar, StringBuilder akan membuatnya lebih mudah dibaca, untuk yang kecil, StringBuilder hanya akan menambah kekacauan yang tidak perlu.
sumber