Python performans sorunu okuyun
Bir Python bir Perl komut dosyası geçiş içinde çıplak kemikleri benim sorunum haşlanmış, bir önceki konu aşağıdaki Python slurping dosyaları ile büyük bir performans sorunu buldum. Ubuntu Server üzerinde çalışan bu.
NOT: Bu vs Y X bir konu değil ben temelde bu ne ya eğer aptalca bir şey yaptığımı bilmek istiyorum.
Benim test verileri, 50,000 10 KB dosya (bu işleme ben ne avg dosya boyutu aynalar) I yarattı
mkdir 1
cd 1
for i in {1..50000}; do dd if=/dev/zero of=$i.xml bs=1 count=10000; done
cd ..
cp -r 1 2
Sadece mümkün olduğunca 2 benim komut yarattı
Perl
foreach my $file (<$ARGV[0]/*.xml>){
my $fh;
open($fh, "< $file");
my $contents = do { local $/; <$fh> };
close($fh);
}
Python
import glob, sys
for file in glob.iglob(sys.argv[1] '/*.xml'):
with open(file) as x:
f = x.read()
Ben o zaman önbelleğe temizlenmiş ve her çalışma önbelleğe tekrar temizledim arasında 2 yudumda benim komut kullanarak koştu:
sync; sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
Her zaman diskten her şeyi okumak emin olmak için takip:
sudo iotop -a -u me
Denedim bu bir fiziksel makine ile RAID 10 disk ve üzerinde yeni bir VM Kur nerede VM üzerinde RAID 1 SSD, sadece dahil test benim VM olarak fiziksel sunucu oldu aynı şey, sadece daha hızlı.
$ time python readFiles.py 1
real 5m2.493s
user 0m1.783s
sys 0m5.013s
$ time perl readFiles.pl 2
real 0m13.059s
user 0m1.690s
sys 0m2.471s
$ time perl readFiles.pl 2
real 0m13.313s
user 0m1.670s
sys 0m2.579s
$ time python readFiles.py 1
real 4m43.378s
user 0m1.772s
sys 0m4.731s
Perl DİSK OKUMA etrafında 45/s ve İOWAİT yaklaşık M oldu çalışırken iotop üzerinde Python DİSK OKUMA çalışan 2 m/s ve İOWAİT 97%, 70%, fark ettim. Bana burada çok basit aşağı haşlanmış olan nereye emin değilim.
Dava içinde geçerlidir
$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
$ perl -v
This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-gnu-thread-multi
İSTEDİĞİNİZ GİBİ DAHA FAZLA BİLGİ
Trace koştum ve dosya 1000.xml bilgilerimi aldı ama hep aynı şeyleri yapmak için bir şey gibi görünüyor
Perl
$strace -f -T -o trace.perl.1 perl readFiles.pl 2
32303 open("2/1000.xml", O_RDONLY) = 3 <0.000020>
32303 ioctl(3, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, 0x7fff7f6f7b90) = -1 ENOTTY (Inappropriate ioctl for device) <0.000016>
32303 lseek(3, 0, SEEK_CUR) = 0 <0.000016>
32303 fstat(3, {st_mode=S_IFREG|0664, st_size=10000, ...}) = 0 <0.000016>
32303 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 <0.000017>
32303 fstat(3, {st_mode=S_IFREG|0664, st_size=10000, ...}) = 0 <0.000030>
32303 read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192 <0.005323>
32303 read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 1808 <0.000022>
32303 read(3, "", 8192) = 0 <0.000019>
32303 close(3) = 0 <0.000017>
Python
$strace -f -T -o trace.python.1 python readFiles.py 1
32313 open("1/1000.xml", O_RDONLY) = 3 <0.000021>
32313 fstat(3, {st_mode=S_IFREG|0664, st_size=10000, ...}) = 0 <0.000017>
32313 fstat(3, {st_mode=S_IFREG|0664, st_size=10000, ...}) = 0 <0.000019>
32313 lseek(3, 0, SEEK_CUR) = 0 <0.000018>
32313 fstat(3, {st_mode=S_IFREG|0664, st_size=10000, ...}) = 0 <0.000018>
32313 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa18820a000 <0.000019>
32313 lseek(3, 0, SEEK_CUR) = 0 <0.000018>
32313 read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 8192) = 8192 <0.006795>
32313 read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 1808 <0.000031>
32313 read(3, "", 4096) = 0 <0.000018>
32313 close(3) = 0 <0.000027>
32313 munmap(0x7fa18820a000, 4096) = 0 <0.000022>
Değil emin eğer alakalı olmadığını fark ettim tek fark, Perl, python gelmez ise bunları açılış başlamadan önce tüm dosyaları karşı bu çalıştırmak için görünür
32303 lstat("2/1000.xml", {st_mode=S_IFREG|0664, st_size=10000, ...}) = 0 <0.000022>
Ayrıca ran-c (sadece üst birkaç görüşmesi yaptım): trace
Perl
$ time strace -f -c perl readFiles.pl 2
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
44.07 3.501471 23 150018 read
12.54 0.996490 10 100011 fstat
9.47 0.752552 15 50000 lstat
7.99 0.634904 13 50016 open
6.89 0.547016 11 50017 close
6.19 0.491944 10 50008 50005 ioctl
6.12 0.486208 10 50014 3 lseek
6.10 0.484374 10 50001 fcntl
real 0m37.829s
user 0m6.373s
sys 0m25.042s
Python
$ time strace -f -c python readFiles.py 1
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
42.97 4.186173 28 150104 read
15.58 1.518304 10 150103 fstat
10.51 1.023681 20 50242 174 open
10.12 0.986350 10 100003 lseek
7.69 0.749387 15 50047 munmap
6.85 0.667576 13 50071 close
5.90 0.574888 11 50073 mmap
real 5m5.237s
user 0m7.278s
sys 0m30.736s
Bazı ayrıştırma trace çıkış-T açık ve sayılan ilk 8192 bayt okumak için her dosya ve açık olduğu zaman oluyor, aşağıda toplam zaman geçirdiği için 50000 ilk okur bir dosya takip ortalama kez okunmuş.
300.247128000002 (0.00600446220302379) - Python
11.6845620000003 (0.000233681892724297) - Perl
Eğer işe yarayacağından emin değilim!
GÜNCELLEME 2 Python güncellenmiş kod işletim sistemi kullanmak için.açık ve os.ve ilk 4096 bayt (bu istediğim bilgi dosya üst kısmında olduğu için) tek bir okuma yap da trace: tüm diğer aramaları ortadan kaldırır
18346 open("1/1000.xml", O_RDONLY) = 3 <0.000026>
18346 read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096 <0.007206>
18346 close(3) = 0 <0.000024>
$ time strace -f -c python readFiles.py 1
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
55.39 2.388932 48 50104 read
22.86 0.986096 20 50242 174 open
20.72 0.893579 18 50071 close
real 4m48.751s
user 0m3.078s
sys 0m12.360s
Total Time (avg read call)
282.28626 (0.00564290374812595)
Başka bir örnek, Azure ve oraya bir VM oluşturmak gidiyorum sonra! hala daha iyi...!
Bu boyutu için 3 - Özür dilerim GÜNCELLEME!!
Tamam bazı ilginç sonuçlar kullanarak (@J. F. Sebastian) komut 3 kurulumları, elimden çıktı başlatmak için kısalık ve de kaldırılması tüm testler sadece koşmak süper hızlı önbellek ve bak gibi:
0.23user 0.26system 0:00.50elapsed 99%CPU (0avgtext 0avgdata 9140maxresident)k
0inputs 0outputs (0major 2479minor)pagefaults 0swaps
Azure A2 Standart VM (2 çekirdek 3.5 GB RAM Disk Bilinmeyen ama yavaş)
$ uname -a
Linux servername 3.13.0-35-generic #62-Ubuntu SMP Fri Aug 15 01:58:42 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
$ perl -v
This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-gnu-thread-multi
(with 41 registered patches, see perl -V for more detail)
/usr/bin/time perl slurp.pl 1
1.81user 2.95system 3:11.28elapsed 2%CPU (0avgtext 0avgdata 9144maxresident)k
1233840inputs 0outputs (20major 2461minor)pagefaults 0swaps
clearcache
sync
sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
/usr/bin/time python slurp.py 1
1.56user 3.76system 3:06.05elapsed 2%CPU (0avgtext 0avgdata 8024maxresident)k
1232232inputs 0outputs (14major 52273minor)pagefaults 0swaps
/usr/bin/time perl slurp.pl 2
1.90user 3.11system 6:02.17elapsed 1%CPU (0avgtext 0avgdata 9144maxresident)k
1233776inputs 0outputs (16major 2465minor)pagefaults 0swaps
Her ikisi için de benzer ilk yudumda sonuçları, 2. Perl slurp sırasında neler olduğuna emin değil misiniz?
VMWare Linux VM (8 GB RAM Disk RAID1 2 çekirdek SSD)
$ uname -a
Linux servername 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
$ perl -v
This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-gnu-thread-multi
(with 41 registered patches, see perl -V for more detail)
/usr/bin/time perl slurp.pl 1
1.66user 2.55system 0:13.28elapsed 31%CPU (0avgtext 0avgdata 9136maxresident)k
1233152inputs 0outputs (20major 2460minor)pagefaults 0swaps
clearcache
sync
sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
/usr/bin/time python slurp.py 1
2.10user 4.67system 4:45.65elapsed 2%CPU (0avgtext 0avgdata 8012maxresident)k
1232056inputs 0outputs (14major 52269minor)pagefaults 0swaps
/usr/bin/time perl slurp.pl 2
2.13user 4.11system 5:01.40elapsed 2%CPU (0avgtext 0avgdata 9140maxresident)k
1233264inputs 0outputs (16major 2463minor)pagefaults 0swaps
Bu kez, daha önce olduğu gibi, Perl şekilde daha hızlı ilk yudumda, ikinci Perl gazlı oluyor ama önce bu davranışı görülür ne emin değildir. Measure.sh tekrar koştu ve sonuç tam olarak ya da bir kaç saniye ver de aynıydı. Ben o zaman her normal insanın yapacağı şeyi yaptım ve Azure makine 3.13.0-35-generic maç için çekirdeği güncelledi ve tekrar measure.sh ve sonuç hiçbir değişiklik yapmadı koştu.
Meraktan sonra measure.sh 1 ve 2 parametre takas ve garip bir şey oldu..Perl yavaşladı ve Python hızlandırdı!
/usr/bin/time perl slurp.pl 2
1.78user 3.46system 4:43.90elapsed 1%CPU (0avgtext 0avgdata 9140maxresident)k
1234952inputs 0outputs (21major 2458minor)pagefaults 0swaps
clearcache
sync
sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
/usr/bin/time python slurp.py 2
1.19user 3.09system 0:10.67elapsed 40%CPU (0avgtext 0avgdata 8012maxresident)k
1233632inputs 0outputs (14major 52269minor)pagefaults 0swaps
/usr/bin/time perl slurp.pl 1
1.36user 2.32system 0:13.40elapsed 27%CPU (0avgtext 0avgdata 9136maxresident)k
1232032inputs 0outputs (17major 2465minor)pagefaults 0swaps
Bu sadece beni daha da karıştırdı :-(
Fiziksel Sunucu (32 çekirdek 132 GB RAM Disk RAID10 SAS)
$ uname -a
Linux servername 3.5.0-23-generic #35~precise1-Ubuntu SMP Fri Jan 25 17:13:26 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
$ python
Python 2.7.3 (default, Aug 1 2012, 05:14:39)
[GCC 4.6.3] on linux2
$ perl -v
This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux-gnu-thread-multi
(with 55 registered patches, see perl -V for more detail)
/usr/bin/time perl slurp.pl 1
2.22user 2.60system 0:15.78elapsed 30%CPU (0avgtext 0avgdata 43728maxresident)k
1233264inputs 0outputs (15major 2984minor)pagefaults 0swaps
clearcache
sync
sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
/usr/bin/time python slurp.py 1
2.51user 4.79system 1:58.53elapsed 6%CPU (0avgtext 0avgdata 34256maxresident)k
1234752inputs 0outputs (16major 52385minor)pagefaults 0swaps
/usr/bin/time perl slurp.pl 2
2.17user 2.95system 0:06.96elapsed 73%CPU (0avgtext 0avgdata 43744maxresident)k
1232008inputs 0outputs (14major 2987minor)pagefaults 0swaps
Burada Perl her zaman kazanmak gibi görünüyor.
şaşkın
Verilen gariplik benim yerel VM, ne zaman değiştirdim dizinleri, hangi makine var en kontrole gidiyorum deneyin bir ikili yaklaşım tüm olası seçenekleri çalışan python vs perl kullanarak 1 veya 2 olarak veri dizini ve denemek için çalışacak onları birden çok kez tutarlılık ama biraz sürer ben biraz delice bir sonu olması gerekli. Tek istediğim kıvamda :-(
4 - Tutarlılık GÜNCELLEŞTİRİN
(Ubuntu-14.04.1-server VM 3.13.0-35-generic #62-Ubuntu) üzerinde çalışan aşağıdadır
Bazı kıvamını buldu, testleri bir veri dir 1 / 2/Perl slurp şunları buldum Python için mümkün olan her şekilde düşünüyorum:
- Python her zaman oluşturulan dosyaları (yani dd tarafından oluşturulan) yavaş
- Python her zaman kopyalanan dosyaları (yani cp-r) tarafından oluşturulan Hızlı
- Perl her zaman oluşturulan dosyaları (yani dd tarafından oluşturulan) Hızlı
- Perl her zaman kopyalanan dosyaları (yani cp-r) tarafından oluşturulan yavaş
OS düzeyi kopyalama baktım ve Ubuntu bana öyle geliyor ki '' Python ile aynı şekilde davranır, yani kopyalanan dosyaları özgün dosyaları ve hızlı. yavaş cp
Bu koştum nedir ve sonuçları, RAID10 bir sistemde tek bir SATA HD ile ve bir makinede bu birkaç kez yaptım, sonuç:
$ mkdir 1
$ cd 1
$ for i in {1..50000}; do dd if=/dev/urandom of=$i.xml bs=1K count=10; done
$ cd ..
$ cp -r 1 2
$ sync; sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
$ time strace -f -c -o trace.copy2c cp -r 2 2copy
real 0m28.624s
user 0m1.429s
sys 0m27.558s
$ sync; sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
$ time strace -f -c -o trace.copy1c cp -r 1 1copy
real 5m21.166s
user 0m1.348s
sys 0m30.717s
İzleme sonuçları zaman harcandığını yerleri gösterir
$ head trace.copy1c trace.copy2c
==> trace.copy1c <==
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
60.09 2.541250 25 100008 read
12.22 0.516799 10 50000 write
9.62 0.406904 4 100009 open
5.59 0.236274 2 100013 close
4.80 0.203114 4 50004 1 lstat
4.71 0.199211 2 100009 fstat
2.19 0.092662 2 50000 fadvise64
0.72 0.030418 608 50 getdents
==> trace.copy2c <==
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
47.86 0.802376 8 100008 read
13.55 0.227108 5 50000 write
13.02 0.218312 2 100009 open
7.36 0.123364 1 100013 close
6.83 0.114589 1 100009 fstat
6.31 0.105742 2 50004 1 lstat
3.38 0.056634 1 50000 fadvise64
1.62 0.027191 544 50 getdents
Kopyalama kopya orijinal dosya kopyalama çok daha hızlı öyle görünüyor ki, benim şu anki tahminim kopyalanan dosyalar diskte aslında onları daha verimli hale yaratıldıkları zaman daha iyi okumak için hizalanmış?
İlginçtir 'rsyn' ve 'cp' ters speedwise çalışmak, çok gibi görünüyor Perl ve Python!
$ rm -rf 1copy 2copy; sync; sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'; echo "Rsync 1"; /usr/bin/time rsync -a 1 1copy; sync; sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'; echo "Rsync 2"; /usr/bin/time rsync -a 2 2copy
Rsync 1
3.62user 3.76system 0:13.00elapsed 56%CPU (0avgtext 0avgdata 5072maxresident)k
1230600inputs 1200000outputs (13major 2684minor)pagefaults 0swaps
Rsync 2
4.87user 6.52system 5:06.24elapsed 3%CPU (0avgtext 0avgdata 5076maxresident)k
1231832inputs 1200000outputs (13major 2689minor)pagefaults 0swaps
$ rm -rf 1copy 2copy; sync; sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'; echo "Copy 1"; /usr/bin/time cp -r 1 1copy; sync; sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'; echo "Copy 2"; /usr/bin/time cp -r 2 2copy
Copy 1
0.48user 6.42system 5:05.30elapsed 2%CPU (0avgtext 0avgdata 1212maxresident)k
1229432inputs 1200000outputs (6major 415minor)pagefaults 0swaps
Copy 2
0.33user 4.17system 0:11.13elapsed 40%CPU (0avgtext 0avgdata 1212maxresident)k
1230416inputs 1200000outputs (6major 414minor)pagefaults 0swaps
CEVAP
Dinlenme benzeşen şeyler olmalı çünkü örnekler sadece bir odaklanmak, karşılık vereceğim
Bence, bu durumda önceden Okuma (ya da belki başka bir yöntem, bu ilgili) olursa olsun ne özelliği:
Hadi bu örneği ele alalım
"1" dir dd komutu ve o zamana kadar yaptığınız gibi (isim 1000.xml için 1.xml ben kopyalanan dir 2 dir 1 Özgün . 1000 xml dosyası oluşturduk
$ mkdir 1
$ cd 1
$ for i in {1..1000}; do dd if=/dev/urandom of=$i.xml bs=1K count=10; done
$ cd ..
$ cp -r 1 2
$ sync; sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
$ time strace -f -c -o trace.copy2c cp -r 2 2copy
$ sync; sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
$ time strace -f -c -o trace.copy1c cp -r 1 1copy
Bir sonraki adımda cp komutu (trace) sipariş verileri kopyalanır ne öğrendim ben debug:
Yani cp mu sipariş (orijinal dizinden ikinci okuma ikinci kopyalanan dizin okumak için daha fazla zaman alıcı olduğunu gördüm çünkü sadece ilk 4 dosyaları) bunu şu şekilde
100.xml 150.xml 58.xml 64.xml ... benim örnekte*
Şimdi, bu dosyaları (coherent çıktı - ext3 fs) tarafından kullanılan dosya sistemi blok üzerinde bir göz atın:
Orijinal dizin:
BLOCKS:
(0-9):63038-63047 100.xml
(0-9):64091-64100 150.xml
(0-9):57926-57935 58.xml
(0-9):60959-60968 64.xml
....
Copied directory:
BLOCKS:
(0-9):65791-65800 100.xml
(0-9):65801-65810 150.xml
(0-9):65811-65820 58.xml
(0-9):65821-65830 64.xml
....
"Blok bitişik, ilk dosya 100.xml okuma sırasında" İleri Okuma "anlamına gelir yani"Kopyalanan dizin gördüğünüz gibi tekniği (kumanda veya sistem ayarları) performansı artırabilir.
dd başka bir sipariş 1000.xml ama cp komutu kopyalar için 1.xml dosya (100.xml, 150.xml, 58.xml,64.xml oluşturun. Yürütme:
cp -r 1 1copy
başka bu dizin kopyalamak için, kopya olan dosyaları blokları bu tür dosyaları okumak daha fazla zaman ayırın değil bitişik.
Kopyalama cp komutu dosya dd komutu tarafından oluşturulmaz) tarafından kopyalanan dosya sonra hangi dizin oluşturma çok bitişik
cp -r 2 2copy
kopyanın kopyası daha hızlıdır.
Özet: Python/perl aynı dır (ya da iki dizin cp komutu ile kopyalanan) kullanmanız gerekir ve ayrıca seçeneği O_DİRECT atlayarak okumak için kullanabilirsiniz performansını test etmek için yani tüm çekirdek tamponlar ve diskteki verileri doğrudan okuyabilir.
Lütfen unutmayın, bu sonuçlar çekirdek farklı tür, sistem, disk denetleyici, sistem ayarları üzerinde farklı, fs ve benzeri olabilir.
Eklemeler:
[debugfs]
[root@dhcppc3 test]# debugfs /dev/sda1
debugfs 1.39 (29-May-2006)
debugfs: cd test
debugfs: stat test.xml
Inode: 24102 Type: regular Mode: 0644 Flags: 0x0 Generation: 3385884179
User: 0 Group: 0 Size: 4
File ACL: 0 Directory ACL: 0
Links: 1 Blockcount: 2
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x543274bf -- Mon Oct 6 06:53:51 2014
atime: 0x543274be -- Mon Oct 6 06:53:50 2014
mtime: 0x543274bf -- Mon Oct 6 06:53:51 2014
BLOCKS:
(0):29935
TOTAL: 1
debugfs:
Nasıl Java SecureRandom ile performans...
Python ile büyük metin dosyaları, hafı...
Python urllib2 Basic Auth Sorunu...
Okuyun .mat Python dosyaları...
Python Performans - Hiç başka bir şeyi...