Когато променлива на средата ускорява процеса 40 пъти

Днес искаме да говорим за някои от най-новите актуализации на системата Sherlock [това е клъстер с висока производителност в Станфордския университет - прибл. прев.], които значително ускоряват изброяването на файлове в директории с голям брой записи.

За разлика от обикновените статии, това е по-скоро вътрешен доклад за това как редовно работим върху Sherlock, за да го поддържаме да работи по най-добрия начин за нашите потребители. Надяваме се да публикуваме повече статии като тази в бъдеще.

Изброяването на много файлове отнема време

Всичко започна с въпрос за техническа поддръжка от потребител. Той съобщи за проблема, че изпълнението ls отнема няколко минути в директория с над 15 000 записа $SCRATCH [директория за временни файлове - прибл. платно].

Хиляди файлове в една директория обикновено представляват тежест за файловата система и определено не се препоръчва. Потребителят знаеше това и призна, че не е добре, но спомена, че списъкът е 1000 пъти по-бърз на неговия лаптоп от Sherlock. Разбира се, това ни нарани. Така че погледнахме по-дълбоко.

Защото изглежда добре

Разгледахме какво всъщност прави ls при изброяване на директория и защо процесът отнема толкова време. В повечето съвременни дистрибуции ls по подразбиране работи като ls --color=auto, защото всички харесват цветовете.

Но красивите цветове си имат цена: за всеки файл ls трябва да получи информация за типа на файла, неговите разрешения, флагове, разширени атрибути и други подобни, за да избере подходящия цвят.

Едно просто решение на проблема е да деактивирате напълно цвета в ls, но си представете възмущението на потребителите. При никакви обстоятелства не трябва да отнемате цветния изход, ние не сме чудовища.

Така че погледнахме по-дълбоко. ls цветове вписвания чрез променлива на средата LS_COLORS, който е зададен dircolors(1) въз основа на конфигурационен файл dir_colors(5). да изпълнимият файл чете конфигурационния файл, за да създаде променлива на средата, която след това използва (и ако не разбирате от файлове врата (do), след това dir_colors ще работи, Въпреки всичко).

Нека да разгледаме по-отблизо

За да определим коя цветова схема причинява забавянето, създадохме експериментална среда:

$ mkdir $SCRATCH/dont
$ touch $SCRATCH/dont/{1..10000} # don't try this at home!
$ time ls --color=always $SCRATCH/dont | wc -l
10000

real    0m12.758s
user    0m0.104s
sys     0m0.699s

12,7 секунди за 10 000 файла, не много добре.

Между другото, имаме нужда от знаме --color=always: въпреки че се обръща към ls --color=autoно ls открива, когато не е свързан към терминал (напр. чрез тръба или с пренасочване на изхода) и деактивира оцветяването, ако е зададено auto. Умен човек.

И така, какво отнема толкова време? Погледнахме с strace:

$ strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 44.21    0.186617          19     10000           lstat
 42.60    0.179807          18     10000     10000 getxattr
 12.19    0.051438           5     10000           capget
  0.71    0.003002          38        80           getdents
  0.07    0.000305          10        30           mmap
  0.05    0.000217          12        18           mprotect
  0.03    0.000135          14        10           read
  0.03    0.000123          11        11           open
  0.02    0.000082           6        14           close
[...]

Уау: 10 000 обаждания lstat(), 10 000 обаждания getxattr() (които всички се провалят, защото нашата среда няма атрибутите, които ls търси), 10 000 обаждания capget().

Със сигурност това може да се оптимизира.

Атрибут на способностите? не

Следвайки съвета бъг от преди 10 години, опитахме да деактивираме проверката на атрибути възможности:

$ eval $(dircolors -b | sed s/ca=[^:]*:/ca=:/)
$ time strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 98.95    0.423443          42     10000           lstat
  0.78    0.003353          42        80           getdents
  0.04    0.000188          10        18           mprotect
  0.04    0.000181           6        30           mmap
  0.02    0.000085           9        10           read
  0.02    0.000084          28         3           mremap
  0.02    0.000077           7        11           open
  0.02    0.000066           5        14           close
[...]
------ ----------- ----------- --------- --------- ----------------
100.00    0.427920                 10221         6 total

real    0m8.160s
user    0m0.115s
sys     0m0.961s

Уау, до 8 секунди ускорение! Отървахме се от всички онези скъпи разговори getxattr(), и предизвикателства capget() също изчезна, страхотно.

Но все още има тези досадни обаждания lstat(), Макар че…

Колко цветя ви трябват?

Затова погледнахме по-отблизо LS_COLORS.

Първо просто деактивирахме тази променлива:

$ echo $LS_COLORS
rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:
$ unset LS_COLORS
$ echo $LS_COLORS

$  time ls --color=always $SCRATCH/dont | wc -l
10000

real    0m13.037s
user    0m0.077s
sys     0m1.092s

Какво!?! Още 13 секунди?

Оказва се, че когато променливата на средата LS_COLORS само един от неговите елементи не е дефиниран или липсва <type>=color:, той използва вградената база данни по подразбиране и все още използва цветове. Така че, ако искате да деактивирате оцветяването за определен тип файл, трябва да го замените с <type>=: или <type> 00 във файл DIR_COLORS.

След много проби и грешки стеснихме търсенето до това:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

което е написано като

LS_COLORS='ex=00:su=00:sg=00:ca=00:'

Това означава: не оцветявайте файловете по атрибут. възможности, но малко по малко setuid/setgid, нито от флаг за изпълнимост.

Ние ускоряваме ls

И ако не направите нито една от тези проверки, тогава се обажда lstat() изчезват и сега е съвсем различен въпрос:

$ export LS_COLORS='ex=00:su=00:sg=00:ca=00:'
$ time strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 63.02    0.002865          36        80           getdents
  8.10    0.000368          12        30           mmap
  5.72    0.000260          14        18           mprotect
  3.72    0.000169          15        11           open
  2.79    0.000127          13        10           read
[...]
------ ----------- ----------- --------- --------- ----------------
100.00    0.004546                   221         6 total

real    0m0.337s
user    0m0.032s
sys     0m0.029s

0,3 секунди в списък от 10 000 файла, рекорд.

Настройване на Шерлок

От 13 секунди с настройки по подразбиране до 0,3 секунди с малки корекции LS_COLORS означава 40-кратно ускорение поради липсата setuid / setgid и цветни изпълними файлове. Не е толкова голяма загуба.

Разбира се, това вече е конфигурирано в Sherlock за всеки потребител.

Но ако искате да върнете оцветяването, можете просто да се върнете към настройките по подразбиране:

$ unset LS_COLORS

Но след това в директории с много файлове, не забравяйте да варите кафе, докато работи ls.

Източник: www.habr.com

Добавяне на нов коментар