Coba kode ini.
Ini adalah versi kode Anda yang sedikit dimodifikasi.
1. Saya menghapus Console.WriteLine karena mungkin beberapa perintah lebih lambat dari yang saya coba ukur.
2. Saya memulai Stopwatch sebelum loop dan menghentikannya tepat setelah ini, dengan cara ini saya tidak kehilangan presisi jika fungsinya mengambil 26,4 ticks untuk dijalankan.
3. Cara Anda membagi hasil dengan beberapa iterasi salah. Lihat apa yang terjadi jika Anda memiliki 1000 milidetik dan 100 milidetik. Dalam kedua situasi, Anda akan mendapatkan 0 ms setelah membaginya dengan 1000000.
Stopwatch s = new Stopwatch();
var p = new { FirstName = "Bill", LastName = "Gates" };
int n = 1000000;
long fElapsedMilliseconds = 0, fElapsedTicks = 0, cElapsedMilliseconds = 0, cElapsedTicks = 0;
string result;
s.Start();
for (var i = 0; i < n; i++)
result = (p.FirstName + " " + p.LastName);
s.Stop();
cElapsedMilliseconds = s.ElapsedMilliseconds;
cElapsedTicks = s.ElapsedTicks;
s.Reset();
s.Start();
for (var i = 0; i < n; i++)
result = string.Format("{0} {1}", p.FirstName, p.LastName);
s.Stop();
fElapsedMilliseconds = s.ElapsedMilliseconds;
fElapsedTicks = s.ElapsedTicks;
s.Reset();
Console.Clear();
Console.WriteLine(n.ToString()+" x result = string.Format(\"{0} {1}\", p.FirstName, p.LastName); took: " + (fElapsedMilliseconds) + "ms - " + (fElapsedTicks) + " ticks");
Console.WriteLine(n.ToString() + " x result = (p.FirstName + \" \" + p.LastName); took: " + (cElapsedMilliseconds) + "ms - " + (cElapsedTicks) + " ticks");
Thread.Sleep(4000);
Itulah hasil saya:
1000000 x hasil = string.Format ("{0} {1}", p.FirstName, p.LastName); mengambil: 618ms - 2213706 kutu
1000000 x hasil = (p.FirstName + "" + p.LastName); mengambil: 166ms - 595610 ticks
string.Format
yang tidak menggunakan fitur format komposit (yaitu hanya sederhana{0}
) dan menggantinya dengan rangkaian string yang jauh lebih cepat. Saya ingin tahu hal seperti itu dapat dicapai dengan IL rewriter yang sudah ada seperti PostSharp.Saya kagum bahwa begitu banyak orang segera ingin menemukan kode yang mengeksekusi tercepat. Jika SATU JUTAAN pengulangan MASIH membutuhkan waktu kurang dari satu detik untuk diproses, apakah ini akan ADA CARA APA yang terlihat oleh pengguna akhir? Sangat tidak mungkin.
Saya akan
String.Format
memilih, hanya karena itu paling masuk akal dari sudut pandang arsitektur. Saya tidak peduli tentang kinerja sampai menjadi masalah (dan jika itu terjadi, saya akan bertanya pada diri sendiri: Apakah saya perlu menggabungkan satu juta nama sekaligus? Tentunya mereka tidak akan cocok di layar ...)Pertimbangkan apakah pelanggan Anda kemudian ingin mengubahnya sehingga mereka dapat mengonfigurasi apakah akan menampilkan
"Firstname Lastname"
atau"Lastname, Firstname."
Dengan opsi Format, ini mudah - cukup tukar keluar string format. Dengan concat, Anda akan memerlukan kode tambahan. Tentu itu tidak terdengar seperti masalah besar dalam contoh khusus ini tetapi memperkirakan.sumber
Oh sayang - setelah membaca salah satu balasan saya mencoba membalik urutan operasi - jadi melakukan penggabungan terlebih dahulu, kemudian String.
Jadi urutan operasi membuat perbedaan BESAR, atau lebih tepatnya operasi pertama SELALU jauh lebih lambat.
Berikut ini adalah hasil dari proses di mana operasi diselesaikan lebih dari satu kali. Saya telah mencoba mengubah pesanan tetapi umumnya mengikuti aturan yang sama, setelah hasil pertama diabaikan:
Seperti yang Anda lihat selanjutnya menjalankan metode yang sama (saya refactored kode menjadi 3 metode) secara bertahap lebih cepat. Yang tercepat tampaknya adalah metode Console.WriteLine (String.Concat (...)), diikuti oleh penggabungan normal, dan kemudian operasi yang diformat.
Penundaan awal dalam startup kemungkinan merupakan inisialisasi Stream Konsol, seperti menempatkan Console.Writeline ("Mulai!") Sebelum operasi pertama membawa semua waktu kembali ke jalurnya.
sumber
String tidak dapat diubah, ini berarti bagian memori yang sama digunakan berulang kali dalam kode Anda. Menambahkan dua string yang sama bersamaan dan membuat string baru yang sama berulang kali tidak memengaruhi memori. Net cukup pintar hanya untuk menggunakan referensi memori yang sama. Karenanya kode Anda tidak benar-benar menguji perbedaan antara dua metode concat.
Coba ini untuk ukuran:
Output sampel:
sumber
string.Format
bernilai kinerja kecil di sini. Secara arsitektur lebih baik karena ini berarti Anda dapat mengubah format lebih mudah. Tapi pembuat string saya benar-benar tidak mengerti. Setiap utas lainnya di sini mengatakan Anda harus menggunakan Stringbuilder alih-alih string penggabung. Apa untungnya? Jelas bukan kecepatan, karena tolok ukur ini terbukti.Kasihan penerjemah yang malang
Jika Anda tahu aplikasi Anda akan tetap dalam bahasa Inggris, maka baiklah, simpan kutu jam. Namun, banyak budaya biasanya melihat Lastname Firstname di, misalnya, alamat.
Jadi gunakan
string.Format()
, terutama jika Anda ingin aplikasi Anda pergi ke mana saja bahwa bahasa Inggris bukan bahasa pertama.sumber
string.Format()
berperilaku berbeda dalam budaya yang berbeda? Bukankah masih mencetak nama depan kemudian nama belakang? Sepertinya Anda harus mempertimbangkan budaya yang berbeda di kedua situasi. Saya merasa seperti kehilangan sesuatu di sini.string.Format()
Anda tahu Anda menggunakan nama untuk alamat? Jikastring.Format()
ditukar{0} {1}
berdasarkan budaya, saya akan menganggapnya rusak.Inilah hasil saya lebih dari 100.000 iterasi:
Dan di sini adalah kode bangku:
Jadi, saya tidak tahu jawaban siapa yang ditandai sebagai jawaban :)
sumber
Senar gabungan baik-baik saja dalam skenario sederhana seperti itu - lebih rumit dengan hal yang lebih rumit dari itu, bahkan LastName, FirstName. Dengan format yang dapat Anda lihat, sekilas, seperti apa struktur akhir string ketika membaca kode, dengan penggabungan hampir mustahil untuk segera melihat hasil akhir (kecuali dengan contoh yang sangat sederhana seperti ini).
Apa artinya itu dalam jangka panjang adalah ketika Anda kembali untuk membuat perubahan pada format string Anda, Anda akan memiliki kemampuan untuk masuk dan membuat beberapa penyesuaian pada string format, atau mengerutkan alis Anda dan mulai bergerak di sekitar semua jenis aksesor properti dicampur dengan teks, yang lebih cenderung menimbulkan masalah.
Jika Anda menggunakan .NET 3.5, Anda dapat menggunakan metode ekstensi seperti ini dan mudah mengalir, dari sintaks manset seperti ini:
Akhirnya, ketika aplikasi Anda tumbuh dalam kompleksitas Anda dapat memutuskan bahwa untuk menjaga string dalam aplikasi Anda, Anda ingin memindahkannya ke file sumber daya untuk melokalisasi atau hanya menjadi pembantu statis. Ini akan menjadi JAUH lebih mudah untuk dicapai jika Anda memiliki format yang digunakan secara konsisten, dan kode Anda dapat dengan mudah di refactored untuk menggunakan sesuatu seperti
sumber
Untuk manipulasi yang sangat sederhana, saya akan menggunakan gabungan, tetapi setelah Anda melampaui 2 atau 3 elemen, Format menjadi IMO yang lebih tepat.
Alasan lain untuk memilih String.Format adalah bahwa .NET string tidak dapat diubah dan melakukannya dengan cara ini menghasilkan lebih sedikit salinan sementara / perantara.
sumber
Sementara saya benar-benar memahami preferensi gaya dan memilih rangkaian untuk jawaban pertama saya sebagian berdasarkan pada preferensi saya sendiri, sebagian dari keputusan saya didasarkan pada pemikiran bahwa rangkaian akan lebih cepat. Jadi, karena penasaran, saya mengujinya dan hasilnya mengejutkan, terutama untuk string kecil.
Menggunakan kode berikut:
Saya mendapat hasil sebagai berikut:
Menggunakan metode pemformatan lebih dari 100 kali lebih lambat !! Rangkaian bahkan tidak mendaftar sebagai 1 ms, itulah sebabnya saya output ticks timer juga.
sumber
Mulai dari string interpolasi C # 6.0 dapat digunakan untuk melakukan ini, yang semakin menyederhanakan format.
String yang diinterpolasi memiliki kinerja yang mirip dengan String.Format, tetapi peningkatan keterbacaan dan sintaksis yang lebih pendek, karena fakta bahwa nilai dan ekspresi dimasukkan secara in-line.
Silakan juga merujuk ke artikel dotnetperls ini tentang interpolasi string.
Jika Anda mencari cara default untuk memformat string Anda, ini masuk akal dalam hal keterbacaan dan kinerja (kecuali jika mikrodetik akan membuat perbedaan dalam use case spesifik Anda).
sumber
Untuk penggabungan string dasar, saya biasanya menggunakan gaya kedua - lebih mudah dibaca dan lebih sederhana. Namun, jika saya melakukan kombinasi string yang lebih rumit, saya biasanya memilih String.Format.
String.Format menghemat banyak kutipan dan plus ...
Hanya beberapa kereta yang diselamatkan, tapi saya pikir, dalam contoh ini, format membuatnya jauh lebih bersih.
sumber
Tes yang lebih baik adalah mengawasi memori Anda menggunakan penghitung Perfmon dan CLR. Pemahaman saya adalah bahwa seluruh alasan Anda ingin menggunakan String.Format alih-alih hanya menyatukan string adalah, karena string tidak berubah, Anda tidak perlu membebani pengumpul sampah dengan string sementara yang perlu direklamasi di pass berikutnya.
StringBuilder dan String.Format, meskipun berpotensi lebih lambat, lebih hemat memori.
Apa yang sangat buruk tentang penggabungan string?
sumber
Secara umum saya lebih suka yang pertama, karena terutama ketika string menjadi panjang bisa lebih mudah dibaca.
Manfaat lainnya adalah saya percaya salah satu kinerja, karena yang terakhir benar-benar melakukan 2 pernyataan penciptaan string sebelum meneruskan string terakhir ke metode Console.Write. String.Format menggunakan StringBuilder di bawah selimut yang saya yakini, sehingga beberapa konvergensi dihindari.
Namun perlu dicatat bahwa jika parameter yang Anda berikan ke String.Format (dan metode lain seperti Console.Write) adalah tipe nilai maka mereka akan dimasukkan dalam kotak sebelum diteruskan, yang dapat memberikan hit kinerjanya sendiri. Posting blog di sini .
sumber
Seminggu dari sekarang 19 Agustus 2015, pertanyaan ini akan berusia tepat tujuh (7) tahun. Sekarang ada cara yang lebih baik untuk melakukan ini. Lebih baik dalam hal rawatan karena saya belum melakukan tes kinerja apa pun dibandingkan dengan hanya string gabungan (tetapi apakah itu penting akhir-akhir ini? Perbedaan beberapa milidetik?). Cara baru melakukannya dengan C # 6.0 :
Fitur baru ini lebih baik , IMO, dan sebenarnya lebih baik dalam kasus kami karena kami memiliki kode tempat kami membuat querystrings yang nilainya tergantung pada beberapa faktor. Bayangkan satu querystring di mana kita memiliki 6 argumen. Jadi alih-alih melakukan, misalnya:
di dapat ditulis seperti ini dan lebih mudah dibaca:
sumber
sumber
Saya memilih berdasarkan keterbacaan. Saya lebih suka opsi format ketika ada beberapa teks di sekitar variabel. Dalam contoh ini:
Anda memahami artinya bahkan tanpa nama variabel, sedangkan konser itu penuh dengan tanda kutip dan + tanda dan membingungkan mata saya:
(Saya meminjam contoh Mike karena saya suka)
Jika string format tidak banyak berarti tanpa nama variabel, saya harus menggunakan concat:
Opsi format membuat saya membaca nama variabel dan memetakannya ke nomor yang sesuai. Opsi concat tidak mengharuskan itu. Saya masih bingung dengan tanda kutip dan tanda +, tetapi alternatifnya lebih buruk. Rubi?
Dari segi kinerja, saya berharap opsi format menjadi lebih lambat daripada concat, karena format membutuhkan string untuk diuraikan . Saya tidak ingat harus mengoptimalkan instruksi semacam ini, tetapi jika saya lakukan, saya akan melihat
string
metode sepertiConcat()
danJoin()
.Keuntungan lain dengan format adalah bahwa string format dapat dimasukkan ke dalam file konfigurasi. Sangat berguna dengan pesan kesalahan dan teks UI.
sumber
Saya akan menggunakan String.Format, tetapi saya juga akan memiliki string format dalam file sumber daya sehingga dapat dilokalisasi untuk bahasa lain. Menggunakan concat string sederhana tidak memungkinkan Anda untuk melakukan itu. Jelas jika Anda tidak perlu melokalisasi string itu, ini bukan alasan untuk dipikirkan. Ini benar-benar tergantung pada untuk apa string itu.
Jika itu akan ditunjukkan kepada pengguna, saya akan menggunakan String.Format sehingga saya bisa melokalkan jika saya perlu - dan FxCop akan mengeja memeriksanya untuk saya, kalau-kalau :)
Jika ini berisi angka atau hal-hal non-string lainnya (misalnya tanggal), saya akan menggunakan String.Format karena itu memberi saya lebih banyak kontrol atas pemformatan .
Jika untuk membangun kueri seperti SQL, saya akan menggunakan Linq .
Jika untuk merangkai string di dalam satu lingkaran, saya akan menggunakan StringBuilder untuk menghindari masalah kinerja.
Jika itu untuk beberapa output pengguna tidak akan melihat, dan tidak akan mempengaruhi kinerja saya akan menggunakan String.Format karena saya sudah terbiasa menggunakannya dan saya hanya terbiasa :)
sumber
Jika Anda berurusan dengan sesuatu yang perlu mudah dibaca (dan ini adalah kode terbanyak), saya akan tetap menggunakan versi overload operator KECUALI:
Di bawah setidaknya dua dari keadaan ini, saya akan menggunakan StringBuilder sebagai gantinya.
sumber
Jika Anda bermaksud melokalisasi hasil, maka String.Format sangat penting karena bahasa alami yang berbeda bahkan mungkin tidak memiliki data dalam urutan yang sama.
sumber
Saya pikir ini sangat tergantung pada seberapa kompleks outputnya. Saya cenderung memilih skenario mana yang paling berhasil saat itu.
Pilih alat yang tepat berdasarkan pekerjaan: D Mana yang terlihat paling bersih!
sumber
Saya lebih suka yang kedua juga, tetapi saya tidak punya argumen rasional saat ini untuk mendukung posisi itu.
sumber
Yang bagus!
Baru ditambahkan
Dan itu bahkan lebih cepat (saya kira string.Compat dipanggil dalam kedua contoh, tetapi yang pertama membutuhkan semacam terjemahan).
sumber
string.Concat(...)
. Ini dilakukan selama kompilasi sehingga tidak berdampak pada kinerja run-time. Jika Anda menjalankan tes Anda beberapa kali atau menjalankannya pada sampel tes yang lebih besar Anda akan melihat mereka identik.Karena saya tidak berpikir jawabannya di sini mencakup semuanya, saya ingin membuat tambahan kecil di sini.
Console.WriteLine(string format, params object[] pars)
panggilanstring.Format
. Tanda '+' menyiratkan penggabungan string. Saya tidak berpikir ini selalu ada hubungannya dengan gaya; Saya cenderung untuk mencampur dua gaya tergantung pada konteks saya.Jawaban singkat
Keputusan yang Anda hadapi berkaitan dengan alokasi string. Saya akan mencoba membuatnya sederhana.
Katakan sudah
Jika Anda menjalankan ini, itu akan mengevaluasi sebagai berikut:
tmp
di sini sebenarnya bukan variabel lokal, tetapi ini adalah sementara untuk JIT (didorong pada IL stack). Jika Anda mendorong string pada tumpukan (sepertildstr
dalam IL untuk literal), Anda meletakkan referensi ke pointer string pada stack.Saat Anda menelepon
concat
referensi ini menjadi masalah, karena tidak ada referensi string yang tersedia yang mengandung kedua string. Ini berarti bahwa. NET perlu mengalokasikan blok memori baru, dan kemudian mengisinya dengan dua string. Alasan ini menjadi masalah, adalah karena alokasi relatif mahal.Yang mengubah pertanyaan menjadi: Bagaimana Anda bisa mengurangi jumlah
concat
operasi?Jadi, jawaban kasarnya adalah:
string.Format
untuk> 1 concat, '+' akan bekerja dengan baik untuk 1 concat. Dan jika Anda tidak peduli melakukan optimasi kinerja mikro,string.Format
akan berfungsi dengan baik dalam kasus umum.Catatan tentang Budaya
Dan kemudian ada sesuatu yang disebut budaya ...
string.Format
memungkinkan Anda untuk digunakanCultureInfo
dalam pemformatan Anda. Operator sederhana '+' menggunakan budaya saat ini.Ini terutama komentar penting jika Anda sedang menulis format file dan f.ex.
double
nilai yang Anda 'tambahkan' ke string. Pada mesin yang berbeda, Anda mungkin berakhir dengan string yang berbeda jika Anda tidak menggunakannyastring.Format
dengan eksplisitCultureInfo
.F.ex. pertimbangkan apa yang terjadi jika Anda mengubah '.' untuk ',' saat menulis file koma-terpisah-nilai Anda ... dalam bahasa Belanda pemisah desimal adalah koma, sehingga pengguna Anda mungkin hanya akan mendapatkan kejutan 'lucu'.
Jawaban yang lebih jelas
Jika Anda tidak tahu ukuran pasti dari string sebelumnya, yang terbaik adalah menggunakan kebijakan seperti ini untuk secara keseluruhan menempatkan buffer yang Anda gunakan. Ruang kendur pertama kali diisi, setelah itu data disalin.
Berkembang berarti mengalokasikan blok memori baru dan menyalin data lama ke buffer baru. Blok memori lama kemudian bisa dilepaskan. Anda mendapatkan intinya pada saat ini: pertumbuhan adalah operasi yang mahal.
Cara paling praktis untuk melakukan ini adalah dengan menggunakan kebijakan penempatan secara keseluruhan. Kebijakan yang paling umum adalah menempatkan buffer secara keseluruhan dalam kekuatan 2. Tentu saja, Anda harus melakukannya sedikit lebih pintar dari itu (karena tidak masuk akal untuk tumbuh dari 1,2,4,8 jika Anda sudah tahu Anda membutuhkan 128 karakter) ) Tapi kamu mendapatkan gambarnya. Kebijakan ini memastikan Anda tidak perlu terlalu banyak operasi mahal yang saya jelaskan di atas.
StringBuilder
adalah kelas yang pada dasarnya secara keseluruhan menempatkan buffer yang mendasari dalam kekuatan dua.string.Format
gunakan diStringBuilder
bawah tenda.Hal ini membuat keputusan Anda menjadi trade-off dasar antara keseluruhan-dan-tambahkan (-multiple) (dengan budaya) atau hanya mengalokasikan-dan-menambahkan.
sumber
Secara pribadi, yang kedua karena semua yang Anda gunakan adalah dalam urutan langsung, maka akan menjadi output. Sedangkan dengan yang pertama Anda harus mencocokkan {0} dan {1} dengan var yang tepat, yang mudah berantakan.
Setidaknya itu tidak seburuk sprintf C ++ di mana jika Anda mendapatkan tipe variabel yang salah semuanya akan meledak.
Juga, karena yang kedua semuanya inline dan tidak harus melakukan pencarian dan mengganti semua {0} hal-hal, yang terakhir harus lebih cepat ... meskipun saya tidak tahu pasti.
sumber
Saya sebenarnya suka yang pertama karena ketika ada banyak variabel yang bercampur dengan teks itu tampaknya lebih mudah dibaca untuk saya. Plus, lebih mudah untuk berurusan dengan tanda kutip ketika menggunakan string. Format (), eh, format. Berikut adalah analisis rangkaian string yang layak .
sumber
Saya selalu menggunakan rute string.Format (). Mampu menyimpan format dalam variabel seperti contoh Nathan adalah keuntungan besar. Dalam beberapa kasus saya dapat menambahkan variabel tetapi sekali lebih dari 1 variabel sedang disatukan saya menolak untuk menggunakan format.
sumber
Oh, dan hanya untuk kelengkapan, berikut ini adalah beberapa kutu lebih cepat daripada penggabungan normal:
sumber
Yang pertama (format) terlihat lebih baik bagi saya. Ini lebih mudah dibaca dan Anda tidak membuat objek string sementara tambahan.
sumber
Saya ingin tahu di mana StringBuilder berdiri dengan tes-tes ini. Hasil di bawah ini ...
Hasil:
sumber
Menurut bahan persiapan MCSD, Microsoft menyarankan menggunakan operator + ketika berhadapan dengan sejumlah kecil gabungan (mungkin 2 hingga 4). Saya masih tidak yakin mengapa, tapi itu sesuatu yang perlu dipertimbangkan.
sumber