Dalam pertanyaan C ++ tentang pengoptimalan dan gaya kode , beberapa jawaban merujuk ke "SSO" dalam konteks mengoptimalkan salinan std::string
. Apa arti SSO dalam konteks itu?
Jelas bukan "single sign on". "Optimasi string bersama", mungkin?
c++
string
optimization
Raedwald
sumber
sumber
std::string
diterapkan", dan yang lain bertanya "apa arti SSO", Anda harus benar-benar gila untuk menganggap mereka sebagai pertanyaan yang samaJawaban:
Latar Belakang / Gambaran Umum
Operasi pada variabel otomatis ("dari tumpukan", yang merupakan variabel yang Anda buat tanpa memanggil
malloc
/new
) umumnya jauh lebih cepat daripada yang melibatkan toko gratis ("tumpukan", yang merupakan variabel yang dibuat menggunakan menggunakannew
). Namun, ukuran array otomatis tetap pada waktu kompilasi, tetapi ukuran array dari toko gratis tidak. Selain itu, ukuran tumpukan terbatas (biasanya beberapa MiB), sedangkan penyimpanan gratis hanya dibatasi oleh memori sistem Anda.SSO adalah Optimasi String Pendek / Kecil. A
std::string
biasanya menyimpan string sebagai penunjuk ke free store ("the heap"), yang memberikan karakteristik kinerja yang sama seperti jika Anda meneleponnew char [size]
. Ini mencegah stack overflow untuk string yang sangat besar, tetapi bisa lebih lambat, terutama dengan operasi penyalinan. Sebagai optimasi, banyak implementasistd::string
membuat array otomatis kecil, sepertichar [20]
. Jika Anda memiliki string yang 20 karakter atau lebih kecil (diberikan contoh ini, ukuran sebenarnya bervariasi), ia menyimpannya secara langsung dalam array itu. Ini menghindari kebutuhan untuk meneleponnew
sama sekali, yang mempercepat segalanya.EDIT:
Saya tidak berharap jawaban ini menjadi sangat populer, tetapi karena itu, izinkan saya memberikan implementasi yang lebih realistis, dengan peringatan bahwa saya tidak pernah benar-benar membaca implementasi SSO "di alam liar".
Detail implementasi
Minimal,
std::string
kebutuhan untuk menyimpan informasi berikut:Ukurannya bisa disimpan sebagai
std::string::size_type
atau sebagai penunjuk hingga akhir. Satu-satunya perbedaan adalah apakah Anda ingin mengurangi dua pointer ketika pengguna memanggilsize
atau menambahkansize_type
ke pointer ketika pengguna memanggilend
. Kapasitas dapat disimpan dengan cara baik juga.Anda tidak membayar apa yang tidak Anda gunakan.
Pertama, pertimbangkan implementasi naif berdasarkan apa yang saya uraikan di atas:
Untuk sistem 64-bit, itu umumnya berarti
std::string
memiliki 24 byte 'overhead' per string, ditambah 16 byte untuk buffer SSO (16 dipilih di sini bukan 20 karena persyaratan padding). Tidaklah masuk akal untuk menyimpan ketiga anggota data tersebut ditambah sejumlah karakter lokal, seperti dalam contoh sederhana saya. Jikam_size <= 16
, maka saya akan memasukkan semua datam_sso
, jadi saya sudah tahu kapasitasnya dan saya tidak perlu pointer ke data. Jikam_size > 16
, maka saya tidak perlum_sso
. Sama sekali tidak ada tumpang tindih di mana saya membutuhkan semuanya. Solusi cerdas yang tidak membuang ruang akan terlihat sedikit lebih seperti ini (hanya untuk tujuan yang belum teruji, contohnya):Saya berasumsi bahwa sebagian besar implementasi lebih terlihat seperti ini.
sumber
std::string const &
, mendapatkan data adalah tipuan memori tunggal, karena data disimpan di lokasi referensi. Jika tidak ada optimasi string kecil, mengakses data akan membutuhkan dua tipuan memori (pertama untuk memuat referensi ke string dan membaca isinya, lalu yang kedua untuk membaca konten pointer data dalam string).SSO adalah singkatan untuk "Small String Optimization", sebuah teknik di mana string kecil tertanam dalam tubuh kelas string daripada menggunakan buffer yang dialokasikan secara terpisah.
sumber
Seperti yang sudah dijelaskan oleh jawaban lain, SSO berarti Optimasi String Kecil / Pendek . Motivasi di balik optimasi ini adalah bukti yang tidak dapat disangkal bahwa aplikasi pada umumnya menangani string yang jauh lebih pendek daripada string yang lebih panjang.
Seperti yang dijelaskan oleh David Stone dalam jawabannya di atas ,
std::string
kelas menggunakan buffer internal untuk menyimpan konten hingga panjang tertentu, dan ini menghilangkan kebutuhan untuk mengalokasikan memori secara dinamis. Ini membuat kode lebih efisien dan lebih cepat .Jawaban terkait lainnya ini dengan jelas menunjukkan bahwa ukuran buffer internal tergantung pada
std::string
implementasi, yang bervariasi dari platform ke platform (lihat hasil benchmark di bawah).Tolak ukur
Berikut ini adalah program kecil yang menandai operasi penyalinan banyak string dengan panjang yang sama. Ia mulai mencetak waktu untuk menyalin 10 juta string dengan panjang = 1. Kemudian berulang dengan string panjang = 2. Terus berlanjut hingga panjangnya 50.
Jika Anda ingin menjalankan program ini, Anda harus melakukannya seperti
./a.out > /dev/null
sehingga waktu untuk mencetak string tidak dihitung. Angka-angka yang penting dicetakstderr
, sehingga mereka akan muncul di konsol.Saya telah membuat grafik dengan output dari mesin MacBook dan Ubuntu saya. Perhatikan bahwa ada lompatan besar dalam waktu untuk menyalin string ketika panjangnya mencapai titik tertentu. Itulah saat ketika string tidak lagi sesuai dengan buffer internal dan alokasi memori harus digunakan.
Perhatikan juga bahwa pada mesin linux, lompatan terjadi ketika panjang string mencapai 16. Pada macbook, lompatan terjadi ketika panjangnya mencapai 23. Ini menegaskan bahwa SSO tergantung pada implementasi platform.
Ubuntu
Macbook Pro
sumber