Следуя более раннему потоку, я свалил свою проблему на его голые кости, перейдя с Perl script на Python, я обнаружил огромную проблему с производительностью с отсечением файлов в Python. Выполнение этого на сервере Ubuntu.
NB: это не поток X или Y, который мне нужно знать в корне, если это так, или если я делаю что-то глупое.
Я создал свои тестовые данные, 50 000 файлов 10 КБ (это отражает размер файла avg того, что я обрабатываю):
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
Создал 2 сценария как можно проще:
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()
Затем я очистил кеши и запустил 2 сценария slurp, между каждым прогоном я снова очистил кеши, используя:
sync; sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
Затем отслеживался, чтобы гарантировать, что он все время читает с диска:
sudo iotop -a -u me
Я попробовал это на физической машине с дисками RAID 10 и на новой виртуальной машине, в которой находится виртуальная машина на RAID-массивах RAID 1, только что включил тестовые прогоны с моей виртуальной машины, так как физический сервер был почти таким же быстрее.
$ 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
Я заметил на iotop, когда Perl запускал DISK READ, составлял около 45 М/с, а IOWAIT - около 70%, при запуске Python DISK READ составлял 2 М/с и IOWAIT 97%. Я не уверен, куда идти отсюда, чтобы сварить их так же просто, как я могу.
В случае, если это релевантно
$ 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
ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ ЗАПРОСИТЬ
Я побежал и схватил информацию для файла 1000.xml, но все, похоже, делают то же самое:
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>
Одно замечание, которое я заметил, не уверен, что он имеет значение, заключается в том, что Perl, похоже, запускает это против всех файлов, прежде чем он начнет их открывать, в то время как python не выполняет:
32303 lstat("2/1000.xml", {st_mode=S_IFREG|0664, st_size=10000, ...}) = 0 <0.000022>
Кроме того, был запущен strace с -c (всего несколько вызовов):
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
Был ли какой-то синтаксический анализ вывода strace с включенным -T и подсчитал первый 8192 байт для каждого файла, и он ясно, что это время, а ниже общее время, затраченное на 50000 первых чтений файла за которым следует среднее время для каждого чтения.
300.247128000002 (0.00600446220302379)   - Python
11.6845620000003 (0.000233681892724297)  - Perl
Не уверен, что это поможет!
ОБНОВЛЕНИЕ 2 Обновленный код в Python для использования os.open и os.read и просто выполните одно чтение первых 4096 байт (это будет работать для меня, поскольку информация, которую я хочу, находится в верхней части файла), также устраняет все остальные вызовы в strace:
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)
По-прежнему не лучше... Далее я собираюсь создать виртуальную машину на Azure и попробовать там еще один пример!
ОБНОВЛЕНИЕ 3 - Извините за размер этого!
Хорошо, некоторые интересные результаты, используя ваш (@J.F.Sebastian) script на 3-х настройках, разделили вывод на старте для краткости, а также удалили все тесты, которые просто быстро запускаются из кеша и выглядят следующим образом:
0.23user 0.26system 0:00.50elapsed 99%CPU (0avgtext+0avgdata 9140maxresident)k
0inputs+0outputs (0major+2479minor)pagefaults 0swaps
Azure A2 Standard VM (2 ядра 3,5 ГБ RAM-диск неизвестен, но медленный)
$ 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
Сопоставимые первые результаты slurp для обоих, не уверены, что происходило во время второго Perl slurp?
Мой VMWare Linux VM (2 ядра 8 ГБ RAM Disk RAID1 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
На этот раз, как и прежде, Perl быстрее работает на первом slurp, не уверен, что происходит на втором Perl slurp, хотя раньше этого не видел. Ran measure.sh снова, и результат был точно таким же, что дайте или занять несколько секунд. Затем я сделал то, что сделал бы любой нормальный человек, и обновил ядро, чтобы он соответствовал машине Azure 3.13.0-35-generic и снова запустил measure.sh и не имел никакого значения для результатов.
Из любопытства я затем поменял параметры 1 и 2 в measure.sh, и произошло что-то странное. Perl замедлился, и Python ускорился!
+ /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
Это еще больше смутило меня: - (
Физический сервер (32 ядра 132 ГБ 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
Здесь Perl, кажется, побеждает каждый раз.
озадачены
Учитывая странность моей локальной виртуальной машины, когда я обменивал каталоги, на котором я больше всего контролирую, я собираюсь попробовать двоичный подход для всех возможных вариантов запуска python vs perl с использованием 1 или 2 в качестве каталог данных и попробуйте запустить их несколько раз для согласованности, но это займет некоторое время, и я немного смучу, поэтому сначала может потребоваться перерыв. Все, что я хочу, это последовательность: - (
ОБНОВЛЕНИЕ 4 - Консистенция
(Ниже выполняется на VM-сервере ubuntu-14.04.1, ядро 3.13.0-35-generiС# 62-Ubuntu)
Я думаю, что я нашел некоторую согласованность, все время выполнял тесты для Python/Perl slurp на data dir 1/2. Я нашел следующее:
- Python всегда работает медленно на созданных файлах (т.е. создан dd)
 - Python всегда работает с скопированными файлами (т.е. создан cp -r)
 - Perl всегда работает на созданных файлах (т.е. создан dd)
 - Perl всегда медленно копирует файлы (т.е. создает cp -r)
 
Итак, я посмотрел на копирование на уровне ОС, и похоже, что Ubuntu cp ведет себя так же, как Python, т.е. замедляет исходные файлы и быстро копирует файлы.
Это то, что я запускал, и результаты, я делал это несколько раз на машине с одним SATA HD и системой RAID10, результаты:
$ 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
Результаты трассировки показывают, где время тратится
$ 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
Итак, копирование копий происходит намного быстрее, чем копирование исходных файлов. Моя текущая догадка заключается в том, что при копировании файлы выравниваются на диске лучше, чем когда они были изначально созданы, что делает их более эффективными для чтения?
Интересно, что "rsyn" и "cp", похоже, работают в противоположных направлениях по скорости, подобно Perl и 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