Кога променливата на околината го забрзува процесот за 40 пати

Денес сакаме да зборуваме за некои од најновите ажурирања на системот Шерлок [ова е кластер со високи перформанси на Универзитетот Стенфорд - прибл. trans.], што значително го забрзува списокот на датотеки во директориуми со голем број записи.

За разлика од обичните написи, ова е повеќе инсајдерски извештај за тоа како редовно работиме на Шерлок за да го одржуваме најдоброто за нашите корисници. Се надеваме дека ќе објавиме повеќе вакви написи во иднина.

Наведувањето на многу датотеки бара време

Се започна со прашање за техничка поддршка од корисник. Проблемот го пријавил дека егзекуцијата ls потребни се неколку минути во директориумот со преку 15 записи $SCRATCH [директориум за привремени датотеки - прибл. лента].

Илјадници датотеки во еден директориум обично претставуваат товар за датотечниот систем и дефинитивно не се препорачуваат. Корисникот го знаел ова и признал дека не е добро, но спомнал дека огласот бил 1000 пати побрз на неговиот лаптоп од Шерлок. Се разбира, ова ни наштети. Така, погледнавме подлабоко.

Затоа што изгледа убаво.

Разгледавме што всушност прави 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 датотеки, не многу добро.

Патем, ни треба знаме --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 повици lstat(), 10 повици getxattr() (кои сите не успеваат затоа што нашата околина ги нема атрибутите што ги бара ls), 10 повици 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 датотеки, рекорд.

Поставување на Шерлок

13 секунди со стандардни поставки до 0,3 секунди со мали дотерувања LS_COLORS значи 40-кратно забрзување поради отсуството setuid / setgid и обоени извршни датотеки. Не толку голема загуба.

Се разбира, ова сега е конфигурирано во Шерлок за секој корисник.

Но, ако сакате да го вратите боењето, можете едноставно да се вратите на стандардните поставки:

$ unset LS_COLORS

Но, тогаш на директориуми со многу датотеки, не заборавајте да сварите кафе додека работи ls.

Извор: www.habr.com

Додадете коментар