Wc neden bu kadar yavaş?


17

Wc yardımcı programı neden bu kadar yavaş?

Büyük bir dosyada çalıştırdığımda, md5sum'dan yaklaşık 20 kat daha uzun sürer:

MyDesktop:/tmp$ dd if=/dev/zero bs=1024k count=1024 of=/tmp/bigfile
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.687094 s, 1.6 GB/s

MyDesktop:/tmp$ time wc /tmp/bigfile 
         0          0 1073741824 /tmp/bigfile

real    0m45.969s
user    0m45.424s
sys     0m0.424s

MyDesktop:/tmp$ time md5sum /tmp/bigfile 
cd573cfaace07e7949bc0c46028904ff  /tmp/bigfile

real    0m2.520s
user    0m2.196s
sys     0m0.316s

Sadece dosya nulls dolu olması nedeniyle garip bir kenar koşulu değil, dosya rastgele verilerle dolu veya bir metin dosyası olsa bile aynı performans farkı görüyorum.

(bu Ubuntu 13.04, 64 bit'te)


Yalnızca satır sayısını önemseyenlere dikkat edin: wc -l <dosyaadı> çok büyük dosyalarda çok daha hızlıdır.
EL

Yanıtlar:


27

Bu yüzden kaynağa gittim ve yavaşlık çift baytlık karakterleri ele alıyor gibi görünüyor. Temel olarak, okunan her karakter için, onu mbrtowc()geniş bir karaktere dönüştürmeyi denemek için çağırması gerekir, daha sonra bu geniş karakter, bir kelime ayırıcı, satır ayırıcı vb.

Aslında, yerel LANGdeğişkenimi varsayılandan değiştiririm en_US.UTF-8(UTF-8 çok baytlı bir karakter kümesidir) ve bunu " C" (basit tek baytlı karakter kümesi) olarak ayarlarsam, wcönemli ölçüde hızlandıran tek baytlı optimizasyonları kullanabilir, eskisi kadar sadece dörtte biri alıyor.

Ayrıca, her karakteri yalnızca word ( -w), satır uzunluğu ( -L) veya character ( -m) sayıyorsa kontrol etmesi gerekir . Yalnızca bayt ve / veya satır sayıları yapıyorsa, geniş karakter işlemeyi atlayabilir ve daha sonra son derece hızlı çalışır - daha hızlıdır md5sum.

Koştum gprof ve baytlı karakterleri (işlemek için kullanılan işlevler mymbsinit(), mymbrtowc(), myiswprint(), vs) tampon aracılığıyla adımlar çok daha karmaşık o zorunda olduğu için olduğunu 30 tek başına yürütme zamanının% ve kod hakkında kadar alıyor değişken boyutlu karakterler için arabellek boyunca değişken boyutlu adımları ele almanın yanı sıra, bir sonraki sefer ele alınabilmesi için arabelleği arabellek başına geçiren kısmen tamamlanmış karakterleri doldurma.

Şimdi ne arayacağımı bildiğime göre, bazı yardımcı programlarla utf-8 yavaşlığından bahseden birkaç gönderi buldum:

/programming/13913014/grepping-a-huge-file-80gb-any-way-to-speed-it-up http://dtrace.org/blogs/brendan/2011/12/08 / 2000x performanslı-kazan /


2
Oh, OP olduğunu fark ettin. : p
Ivan Chau

2
En çok oylanan cevap bu olmasına rağmen, alakasız. md5sumkelime numarasını saymanıza asla izin vermez wcve dosyanın md5 karmasını hesaplamaz! Metin yazarken arabamın daktiloma kıyasla neden bu kadar yavaş olduğunu sormak gibi.
user49468

5
@ user49468: Her ikisi de girdi dosyasının her bir baytını okumak zorunda olduğu için her ikisinin de IO'ya bağlı olduğunu varsaymak mantıklıdır. Bu cevap wc, çok baytlı karakterleri işlerken aslında CPU'ya bağlı olduğunu kanıtlıyor .
MSalters

2
@ user49468: wc ve md5sum farklı şeyler yapabilir, ancak her ikisi de bir dosyayı okur ve nispeten basit bir hesaplama yapar, biri bir sağlama toplamı hesaplar, biri bayt, kelime ayırıcı ve yeni satırları hesaplar. Eh, düşünce basit, ama çok baytlı karakter setleri ekstra karmaşıklığı katmadığımızı almıştı. Daha çok "Arabam mağazaya giderken neden minibüsümden 20 kat daha hızlı?" Diye sormak gibidir. İkisi arasında bir fark beklersiniz, ancak 20X fark değil.
Johnny

1
@Johnny size araba / minivan karşılaştırma her ikisi de sizi mağazaya taşımak için tasarlanmış yönü yoktur. Yani bir hız karşılaştırması var. Aracınızı şerit boyama aracına kıyasla daha uygundur. Her ikisi de sokakları kullandığından, şerit ressamı alışverişe uygun olmadığından ve tersi olduğundan hızları önemli değildir.
user49468

1

Sadece bir tahminde bulunuyorsunuz ama elmaları portakallarla karşılaştırdığınızda ne wcyaptığınıza göre karşılaştırıyorsunuz.md5sum .

md5sum'un görevi

Bir md5sumdosyayı işlerken dosyayı akış olarak açar ve MD5 sağlama toplamı işlevi aracılığıyla akışı çalıştırmaya başlar çok az bellek gerektiren . Temelde CPU ve disk I / O bağlı.

wc'nin görevi

Ne zaman wcbu sadece dosyayı bir defada bir karakter ayrıştırma daha sonra bir çok yapıyor çalışır. Dosyaların yapısını, her seferinde satırları, karakterler arasındaki sınırların nerede olduğu ve bir kelime sınırı olup olmadığı konusunda tespitler yaparak analiz etmelidir.

Misal

Aşağıdaki dizeleri ve algoritmaların her birinin ayrıştırılırken nasıl hareket etmesi gerektiğini düşünün:

“Hello! Greg”
“Hello!Greg”
“Hello\nGreg”
“A.D.D.”
“Wow, how great!”
“wow     \n\n\n    great”
“it was a man-eating shark.”

MD5 için, bu dizelerde önemsiz bir şekilde bir karakter taşır. İçinwc bir kelimenin ve satır sınırının ne olduğuna karar vermek ve gördüğü olay sayısını takip etmek zorundadır.

Ek tuvalet tartışmaları

2006'dawc .NET'te uygulamayı tartışan bu kodlama sorununu buldum . Bazı sahte kodlara bakarken zorluklar oldukça açıktır, bu yüzden bu neden wcdiğer operasyonlardan daha yavaş göründüğüne ışık tutmaya yardımcı olabilir .


1
Standart Unix wc komutundan farklı bir şey açıklıyorsunuz (en azından Ubuntu ile birlikte gelen komut değil). Bu wc benzersiz kelimeleri saymaz , sadece kelimeleri, bu yüzden "merhaba merhaba dünya" 2 değil, 3 kelime.
Johnny

Bu teoriye dayanarak, daha basit bir görev, kulağa saymak gibi daha hızlı gidecek gibi geliyor. Satır sayısını belirtmek için 'wc'yi değiştirmek sonuçları önemli ölçüde değiştirir mi? 'wc -l'
Joshua Miller

@Johnny - Asla söylediğin benzersiz kelimeleri saydığını söylemedim. wcdosyayı ayrıştırırken birden çok şeyi sayar. Dosyayı ayrıştırırken sözcük, satır ve bayt sayısını sayar. Adam sayfasını okuyun!
slm

@JoshuaMiller - wcYalnızca satır saymayı söylemenin içsel ayrıştırmayı sınırlayıp sınırlamadığı belirsizdir, böylece her şeyi saymış olsa bile yalnızca bunları sayar veya yalnızca satır sonuçlarını rapor eder.
slm

@slm Benzersiz kelimeleri saydığını söylediniz, örneğin “Merhaba! Greg ”, Hello 1, Greg 1 ile sonuçlanır , yani her kelime için sayılır. Ve bağlandığınız .Net projesi, "Ana görevlerinden biri, bir veri kümesinden geçmek ve belirli bir kelimenin tekrar sayısını saymaktır. Örneğin," Merhaba, evet merhaba "cümlesi size söyleyecektir. Merhaba kelimesi iki kez kullanıldı ve evet kelimesi bir kez kullanıldı. " Gerçekte yankı sonucu "Merhaba, evet merhaba" | wc --words , "3", değil "Merhaba: 2, Evet: 1"
Johnny
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.