Gdy zmienna środowiskowa przyspiesza proces 40-krotnie

Dziś chcemy porozmawiać o niektórych najnowszych aktualizacjach systemu Sherlock [jest to wysokowydajny klaster na Uniwersytecie Stanforda - ok. trans.], które znacznie przyspieszają wyświetlanie plików w katalogach z dużą liczbą wpisów.

W przeciwieństwie do zwykłych artykułów, jest to raczej raport poufny na temat tego, jak regularnie pracujemy nad Sherlockiem, aby zapewnić naszym użytkownikom jak najlepsze działanie. Mamy nadzieję, że w przyszłości opublikujemy więcej tego typu artykułów.

Wyświetlanie wielu plików wymaga czasu

Wszystko zaczęło się od pytania do pomocy technicznej zadane przez użytkownika. Zgłosił problem związany z wykonaniem ls zajmuje kilka minut w katalogu zawierającym ponad 15 000 wpisów $SCRATCH [katalog plików tymczasowych - ok. uliczka].

Tysiące plików w jednym katalogu zwykle stanowi obciążenie dla systemu plików i zdecydowanie nie jest zalecane. Użytkownik wiedział o tym i przyznał, że nie było dobrze, ale wspomniał, że wpis na jego laptopie był 1000 razy szybszy niż Sherlock. Oczywiście, że nas to zabolało. Zajrzeliśmy więc głębiej.

Bo wygląda ładnie

Przyjrzeliśmy się, co tak naprawdę robi ls podczas umieszczania katalogu na liście i dlaczego proces ten trwa tak długo. W większości nowoczesnych dystrybucji ls domyślnie działa jako ls --color=auto, bo każdy lubi kolory.

Ale piękne kolory mają swoją cenę: za każdy plik ls musi uzyskać informacje o typie pliku, jego uprawnieniach, flagach, rozszerzonych atrybutach i tym podobnych, aby wybrać odpowiedni kolor.

Jednym z prostych rozwiązań tego problemu jest całkowite wyłączenie kolorów w ls, ale wyobraźcie sobie oburzenie użytkowników. W żadnym wypadku nie należy odbierać koloru, nie jesteśmy potworami.

Zajrzeliśmy więc głębiej. ls kolory wpisów poprzez zmienną środowiskową LS_COLORS, który jest ustawiony dircolors(1) na podstawie pliku konfiguracyjnego dir_colors(5). Tak, plik wykonywalny odczytuje plik konfiguracyjny w celu utworzenia zmiennej środowiskowej, której następnie używa ls (a jeśli nie wiesz o plikach drzwi (zrób), a następnie dir_colors będzie działać, Pomimo wszystko).

Przyjrzyjmy się bliżej

Aby określić, który schemat kolorów powoduje spowolnienie, stworzyliśmy środowisko eksperymentalne:

$ 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 sekundy na 10 000 plików, niezbyt dobrze.

Nawiasem mówiąc, potrzebujemy flagi --color=always: chociaż odwraca się ls --color=autoale ls wykrywa, kiedy nie jest podłączony do terminala (np. potokiem lub z przekierowaniem wyjścia) i wyłącza kolorowanie, jeśli jest ustawione na auto. Mądry facet.

Więc co trwa tak długo? Patrzyliśmy z 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
[...]

Wow: 10 000 połączeń lstat(), 10 000 połączeń getxattr() (które wszystkie kończą się niepowodzeniem, ponieważ nasze środowisko nie ma atrybutów, których szuka ls), 10 000 wywołań capget().

Na pewno da się to zoptymalizować.

Atrybut możliwości? Nie

Postępowanie zgodnie z radą błąd sprzed 10 lat, próbowaliśmy wyłączyć sprawdzanie atrybutów możliwości:

$ 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

Wow, aż 8 sekund przyspieszenia! Pozbyliśmy się tych wszystkich drogich rozmów getxattr()i wyzwania capget() też zniknął, świetnie.

Ale nadal są te irytujące połączenia lstat(), Chociaż…

Ile kwiatów potrzebujesz?

Dlatego przyjrzeliśmy się bliżej LS_COLORS.

Najpierw po prostu wyłączyliśmy tę zmienną:

$ 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

Co!?! Nadal 13 sekund?

Okazuje się, że gdy zmienna środowiskowa LS_COLORS tylko jeden z jego elementów nie jest zdefiniowany lub go brakuje <type>=color:, domyślnie korzysta z wbudowanej bazy danych i nadal używa kolorów. Jeśli więc chcesz wyłączyć kolorowanie dla określonego typu pliku, musisz je zastąpić <type>=: lub <type> 00 w pliku DIR_COLORS.

Po wielu próbach i błędach zawęziliśmy nasze poszukiwania do tego:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

co jest napisane jako

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

Oznacza to: nie koloruj plików według atrybutów. możliwości, ale krok po kroku setuid/setgid, ani przez flaga wykonalności.

Przyspieszamy ls

A jeśli nie wykonasz żadnej z tych kontroli, zadzwoń lstat() zniknąć, a teraz to zupełnie inna sprawa:

$ 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 sekundy na liście 10 000 plików to rekord.

Konfigurowanie Sherlocka

Od 13 sekund przy ustawieniach domyślnych do 0,3 sekundy z niewielkimi zmianami LS_COLORS oznacza 40-krotne przyspieszenie z powodu nieobecności setuid / setgid i kolorowe pliki wykonywalne. Nie taka duża strata.

Oczywiście jest to teraz skonfigurowane w Sherlocku dla każdego użytkownika.

Ale jeśli chcesz przywrócić kolorystykę, możesz po prostu wrócić do ustawień domyślnych:

$ unset LS_COLORS

Ale w katalogach z dużą ilością plików pamiętaj o zaparzeniu kawy podczas jej działania ls.

Źródło: www.habr.com

Dodaj komentarz