Када променљива окружења убрза процес за 40 пута

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

За разлику од редовних чланака, ово је више инсајдерски извештај о томе како редовно радимо на Схерлоцк-у како бисмо га одржали на најбољи могући начин за наше кориснике. Надамо се да ћемо у будућности објављивати још оваквих чланака.

Навођење многих датотека захтева време

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

Хиљаде датотека у једном директоријуму обично представљају оптерећење за систем датотека и дефинитивно се не препоручује. Корисник је то знао и признао да то није добро, али је споменуо да је листање била 1000 пута бржа на његовом лаптопу од Шерлока. Наравно, ово нас је повредило. Па смо погледали дубље.

Јер изгледа лепо

Погледали смо шта заправо ради ls када наводите директоријум и зашто процес траје толико дуго. На већини савремених дистрибуција ls подразумевано ради као ls --color=auto, јер сви воле боје.

Али лепе боје имају своју цену: за сваку датотеку ls мора да добије информације о типу датотеке, његовим дозволама, заставицама, проширеним атрибутима и слично како би изабрао одговарајућу боју.

Једно једноставно решење проблема је да се потпуно онемогући боја у лс-у, али замислите бес корисника. Ни у ком случају не би требало да одузимате излаз у боји, ми нисмо чудовишта.

Па смо погледали дубље. ls уносе боја преко променљиве окружења LS_COLORS, који је постављен dircolors(1) на основу конфигурационог фајла dir_colors(5)... Да, извршна датотека чита конфигурациону датотеку да би креирала променљиву окружења, коју лс затим користи (а ако не знате за датотеке врата (до), затим дир_цолорс ће радити, Упркос свему).

Хајде да погледамо изблиза

Да бисмо утврдили која шема боја узрокује успоравање, направили смо експериментално окружење:

$ 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() (што сви не успевају јер наше окружење нема атрибуте које тражи лс), 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.

Извор: ввв.хабр.цом

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