C standart iostreams için düşük performans görevi yapar, ya da sadece kötü bir uygulama ile ilgili muyum?
Her zaman C standart kütüphane iostreams yavaş performans bahsettiğim, güvensizlik dalgası ile bir araya geldi. Henüz var profiler sonuçları gösteren büyük miktarda zaman harcanır iostream Kütüphanesi kod (tam derleyici en iyi duruma getirme) ve geçiş yapmasını iostreams OS-özel G/Ç API ve özel arabellek yönetimi yok ver bir sipariş büyüklüğü iyileştirme.
Ne ekstra işi C standart kütüphane yapıyor, bu standart tarafından gerekli ve pratikte işe yarar mı? Ya da bazı Derleyiciler manuel tampon yönetimi ile rekabetçi iostreams uygulamaları sağlar mı?
Kriterler
Önemli olan hareket etmek, kısa programlar birkaç iostreams iç tampon egzersiz için yazdım:
ostringstream
http://ideone.com/2PPYw içine ikili veri yerleştirme- 81* *
char[]
bir tampon içine ikili veri yerleştirme vector<char>
bir kullanarak* http://ideone.com/Mj2Fi *3 içine ikili veri yerleştirme- YENİ: 4* *basit http://ideone.com/9iitv yineleyici
- YENİdoğrudan ikili veri* http://ideone.com/qc9QA *5 içine koyarak
- YENİ:
vector<char>
basit yineleyici plus sınırları http://ideone.com/YyrKy kontrol edin
ostringstream
stringbuf
sürümleri çok daha yavaş oldukları için daha az tekrar çalıştırmak unutmayın.
İdeone, ostringstream
* *12std:copy
*11, *'den yaklaşık 3 kat daha yavaş ve ham bir tampona memcpy
göre yaklaşık 15 kat daha yavaştır. Bu öncesi-sonrası özel tamponlama için benim gerçek uygulama açıldığında profil ile tutarlı hissediyor.
Bunlar tüm bellek arabellekleri, yani yavaşlık iostreams olamaz suçladı yavaş disk I/O, çok fazla kızarma, senkronizasyon istasyonu. ya da başka şeyler insanları kullanmak için bahane gözlenen yavaşlık C standart kütüphane iostream.
Olacağını görmek güzel kriterler diğer sistemleri ve yorum şeylere ortak uygulamaları yapmak (gibi gds'ler, kütüphanenin , Visual C , Intel C ) ve ne kadar yükü ise zorunlu standart.
Bu test için gerekçe
Bir kaç kişi doğru iostreams daha yaygın olarak biçimlendirilmiş çıkış için kullanılan işaret ettiler. Ancak, aynı zamanda sadece modern API ikili dosya erişimi için C standardı tarafından sağlanır. Ama gerçek nedeni için yaptığımız performans testlerinde iç tamponlama için geçerlidir tipik biçimlendirilmiş I/O: eğer iostreams alamazsınız disk denetleyicisi sağlanan ham veri, nasıl onlar muhtemelen takip zaman onlar sorumlu biçimlendirme de?
Kriter Zamanlama
Tüm bunlar (k
) dış döngünün her yineleme için.
Üzerinde ideone (gcc-4.3.4, bilinmeyen OS ve donanım):
ostringstream
: 53 milisaniyestringbuf
: 27 msvector<char>
back_inserter
: ile 17,6 ms- Sıradan yineleyici
vector<char>
: 10.6 ms vector<char>
yineleyici ve sınırları kontrol: 11.4 mschar[]
: 3.7 ms
Benim laptop (2010 86, cl /Ox /EHsc
Windows 7 Ultimate 64-bit, Intel Core i7, 8 GB RAM, Visual C):
ostringstream
:, 71.6 ms 73.4 milisaniyestringbuf
: 21.7 ms, ms 21.3vector<char>
back_inserter
: 34, 6 ' lık ms, ms 34.4- Sıradan yineleyici
vector<char>
: 1.10 ms, ms tarafından 1,04 vector<char>
ve kontrol yineleyici sınırları: 1.11 ms, 0.87, 1.12, 0.89, 1.02, 1.14 ms ms ms ms mschar[]
: 1.48 ms, ms 1.57
Visual C Profil-Güdümlü Optimizasyonu*, link /ltcg:pgi
, *30 çalışacak, link /ltcg:pgo
ölçü: 2010 86,
ostringstream
: 61.2 ms, ms 60.5- Sıradan yineleyici ile
vector<char>
: tarafından 1,04 ms, ms 1.03
Aynı laptop, aynı OS, 4.3.4 g -O3
: özellik listesi gcc kullanarak
ostringstream
: 62.7 ms, ms 60.5stringbuf
: üzere 44, 4 ms, ms 44.5vector<char>
back_inserter
: 13.5 ms, ms-13, 6 gibi- Sıradan yineleyici
vector<char>
:, 3.9 ms ms 4.1 vector<char>
yineleyici ve sınırları kontrol: 4.0, ms, ms 4.0char[]
: 3.57 ms, ms 3.75
Aynı laptop, C 2008 SP1, cl /Ox /EHsc
: Görsel
ostringstream
: 88.7 ms, ms 87.6stringbuf
: ms 23.3, 23.4 msvector<char>
back_inserter
: 26.1 ms, ms 24.5- Sıradan yineleyici
vector<char>
: 3.13 ms, ms 2.48 vector<char>
yineleyici ve sınırları kontrol: 2.97 ms, ms 2.53char[]
:, 1.25 ms ms 1.52
Aynı laptop, C 2010 64-bit derleyici: Visual
ostringstream
: 48.6 ms, ms 45.0stringbuf
: 16.2 ms, ms 16.0vector<char>
back_inserter
: 26.3 ms, ms 26,5 iken- Sıradan yineleyici
vector<char>
: 0.87 ms, ms 0.89 vector<char>
yineleyici ve sınırları kontrol: 0.99 ms, ms 0.99char[]
: 1.25 ms, ms 1.24
EDİT: iki kere nasıl tutarlı sonuçlar olduğunu görmek için Koştu. Oldukça tutarlı IMO.
Benim laptop, ideone izin verdiğinden daha fazla CPU zaman ayırabilirim beri, tüm yöntemleri için 1000 tekrarlanma sayısını ayarlayın. NOT: Bu ostringstream
ve sadece ilk geçişte yer alan 59 ** tahsisat, nihai sonuçlar üzerinde çok az etkisi olması gerektiği anlamına gelir.
DÜZENLEME: Oops, yineleyici gelişmiş değildi ve çok fazla önbellek isabet vardı bu nedenle vector
--sıradan-yineleyici ile bir hata buldu. vector<char>
char[]
iyi performans nasıl diye merak etmiştim. , vector<char>
hala char[]
altında VC 2010 daha hızlı olmasına rağmen pek bir fark yoktu.
Sonuç
Çıkış akışları tampon saat veri eklenir her üç adım gerektirir:
- Gelen blok kullanılabilir arabellek alanı uygun olduğunu kontrol edin.
- Gelen blok kopyalayın.
- -Uç veri işaretçisi güncelleştirin.
En son kod parçacığını ben, "vector<char>
yineleyici basit artı" sadece bu, aynı zamanda ek alan ayırır ve gelen blok uymazsa, mevcut veri taşır. kontrol sınırları gönderildi Clifford belirttiği gibi, O sınıf/dosya tampon, sadece geçerli arabelleği temizleme ve yeniden o işi olmaz. Bu bir üst tampon çıkış maliyeti bağlı olmalı. Ve bellek içi çalışan bir tampon yapmak için gereken tam olarak bu.
Neden onu test ettiğimde ideone stringbuf
2.5 x daha yavaş, ve en az 10 kat daha yavaş? Bunu açıklamıyor bu yüzden bu basit polymorphically mikro kriter kullanılmasını değil.
CEVAP
Sorunuzu başlık olarak çok ayrıntıya cevap: 2006 Technical Report on C Performance İOStreams (s.ilginç bir bölüm vardır 68). Sorunuza en uygun Bölüm 6.1.2 ("") Yürütme Hızı:
İOStreams işleme bazı yönlerini beri birden fazla yönü üzerinde dağıtılmış, Standart bir görev gibi görünüyor verimsiz bir uygulama. Bu ama — bazı formunu kullanarak değil önişleme, işi çok olabilir Kaçınılması. Biraz daha akıllı olan tipik olarak kullanılır Daha linker, mümkün bunlardan bazıları kaldırmak için verimsizlikleri. Bu tartışılan bir konu §6.2.3 ve madde 6.2.5.
Rapor 2006 yılında yazılmış bu yana tek tavsiyelerin çoğu mevcut Derleyiciler dahil olurdu umarım olur, ama belki de bu durum böyle değil.
Sizin de belirttiğiniz gibi, yönü write()
(ama bu körü körüne kabul etmem) özelliği olmayabilir. Ne özelliği? ostringstream
kodu GCC ile derlenmiş GProf çalışan verir aşağıdaki arıza:
std::basic_streambuf<char>::xsputn(char const*, int)
44.23%std::ostream::write(char const*, int)
34.62%main
12.50%std::ostream::sentry::sentry(std::ostream&)
6.73%std::string::_M_replace_safe(unsigned int, unsigned int, char const*, unsigned int)
0.96%std::basic_ostringstream<char>::basic_ostringstream(std::_Ios_Openmode)
0.96%std::fpos<int>::fpos(long long)
0.00%
Bu yüzden toplu zaman geçirdi xsputn
hangi sonunda aramalar std::copy()
sonra bir sürü kontrol ve güncelleme imleç pozisyonları ve tamponlar (bir bak c \bits\streambuf.tcc
ayrıntılar).
Bu benim en kötü durum durum odaklanmış. Gerçekleştirilen tüm kontrol verileri oldukça büyük parçalar ile ilgili toplam işin küçük bir kısmı bitmiş olur. Ama kodu aynı anda dört bayt veri değiştirme, ve tüm ekstra maliyetleri her zaman erişebilirsiniz. Belli ki önlemek böylece gerçek bir durum düşünün ne kadar önemsiz cezası olurdu write
adlı bir dizinin 1m in yerine 1 milyon kez bir int. Ve gerçek bir durumda bir çok İOStreams, yani bellek için güvenli ve emniyetli tip tasarımının önemli özellikleri seviniriz. Bu faydalar bir fiyata geliyor, ve bu maliyetler yürütme zamanı hakim kılan bir test yazdım.
Bir sınıf statik alanlar ve yöntemler ...
&Quot;protokol"?neden kullanmak i...
Neden yerine HTML JSON oluşturulan dön...
Kötü uygulama ayarlayıcı bir dönüş yap...
Nasıl YANİ sadece uygulama/json görünt...