Dziś chcemy opowiedzieć o niektórych ostatnich aktualizacjach systemu Sherlock [to wysokowydajny klaster Uniwersytetu Stanforda — przyp. tłum.] , które znacznie przyspieszają listing plików w katalogach z dużą ilością wpisów.
W przeciwieństwie do zwykłych artykułów, jest to raczej raport insidera na temat regularnej pracy nad Sherlockiem, aby utrzymać go w jak najlepszej formie dla naszych użytkowników. Mamy nadzieję w przyszłości publikować więcej takich artykułów.
Listing wielu plików zajmuje czas
Wszystko zaczęło się od pytania w pomocy technicznej od użytkownika. Zgłosił problem, że wykonanie ls zajmuje kilka minut w katalogu z ponad 15 000 wpisów w $SCRATCH [katalog na pliki tymczasowe — przyp. tłum.].
Tysiące plików w jednym katalogu zazwyczaj stwarzają trudności dla systemu plików i zdecydowanie nie jest to zalecane. Użytkownik o tym wiedział i przyznał, że to nie jest dobre, ale wspomniał, że na jego laptopie listing wykonuje się 1000 razy szybciej niż w Sherlocku. Oczywiście, dotknęło nas to. Dlatego zaglądnęliśmy głębiej.
Bo ls wygląda ładnie
Zbadaliśmy, co tak naprawdę robi ls podczas listowania katalogu i dlaczego proces zajmuje tyle czasu. W większości nowoczesnych dystrybucji ls domyślnie działa jako ls --color=auto, ponieważ wszyscy lubią kolor.
Ale ładne kolory mają swoją cenę: dla każdego pliku ls musi uzyskać informacje o typie pliku, jego uprawnieniach, flagach, rozszerzonych atrybutach i tym podobnych, aby wybrać odpowiedni kolor.
Jednym z prostych rozwiązań problemu jest całkowite wyłączenie koloru w ls, ale wyobraź sobie oburzenie użytkowników. Absolutnie nie można zabrać kolorowego wyjścia, nie jesteśmy potworami.
Dlatego zajrzeliśmy głębiej. ls koloruje wpisy za pomocą zmiennej środowiskowej LS_COLORS, która jest ustawiana przez dircolors(1) na podstawie pliku konfiguracyjnego dir_colors(5). Tak,plik wykonywalny odczytuje plik konfiguracyjny w celu utworzenia zmiennej środowiskowej, którą później wykorzystuje ls door , nieważne co.) Zbadajmy to bliżej
Aby określić, która z schematów kolorów powoduje spowolnienie, stworzyliśmy środowisko eksperymentalne:
$ mkdir $SCRATCH/dont $ touch $SCRATCH/dont/{1..10000} # nie próbuj tego w domu! $ time ls --color=always $SCRATCH/dont | wc -l 10000real 0m12.758s user 0m0.104s sys 0m0.699s
$ mkdir $SCRATCH/dont
$ touch $SCRATCH/dont/{1..10000} # nie próbuj tego w domu!
$ time ls --color=always $SCRATCH/dont | wc -l
10000
czas rzeczywisty 0m12.758s
czas użytkownika 0m0.104s
czas systemowy 0m0.699s12,7 sekundy dla 10 000 plików, niezbyt dobrze.
A propos, potrzebna flaga
--color=always: choć odwołuje się wls --color=auto, alelsrozpoznaje, kiedy nie jest podłączony do terminala (np. przez kanał lub z przekierowaniem wyjścia) i wyłącza kolorowanie, jeśli ustawiona jest wartośćauto. Mądry facet.
Co więc zajmuje tyle czasu? Sprawdziliśmy przy użyciu strace:
$ strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% czas sekundy usecs/call wywołania błędy 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
[...] O rany: 10 000 wywołań lstat(), 10 000 wywołań getxattr() (które wszystkie kończą się niepowodzeniem, ponieważ w naszym środowisku nie ma atrybutów, których szuka ls), 10 000 wywołań capget().
Na pewno można to zoptymalizować.
Atrybut capabilities? Nie.
Podążając za radami , próbowaliśmy wyłączyć sprawdzanie atrybutu :
$ eval $(dircolors -b | sed s/ca=[^:]*:/ca=:)
$ time strace -c ls --color=always $SCRATCH/dont | wc -l
10000
% czas sekundy usecs/call wywołania błędy 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 łącznie
real 0m8.160s
user 0m0.115s
sys 0m0.961s Wow, przyspieszenie do 8 sekund! Pozbyliśmy się wszystkich tych kosztownych wywołań getxattr(), a wywołania capget() też zniknęły, świetnie.
Ale wciąż zostały te uciążliwe wywołania lstat(), chociaż…
Ile potrzebnych jest kolorów?
Dlatego przyjrzeliśmy się temu dokładniej LS_COLORS.
Na początku 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; $ 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 kiedy zmienna środowiskowa LS_COLORS nie jest zdefiniowana lub brakuje tylko jednego z jej elementów =color:, domyślnie korzysta z wbudowanej bazy danych i wciąż używa kolorów. Dlatego, jeśli chcesz wyłączyć kolorowanie dla danego typu pliku, musisz ją nadpisać za pomocą = lub 00 w pliku DIR_COLORS.
Po wielu próbach i błędach zawęziliśmy poszukiwania do tego:
EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00co jest zapisane jako
LS_COLORS='ex=00:su=00:sg=00:ca=00:' To oznacza: nie koloruj plików ani według atrybutu , ani według bitów , ani według .
Przyspieszamy ls
A jeśli nie wykonasz żadnego z tych sprawdzeń, to wywołania lstat() znikają, a teraz jest zupełnie inaczej:
$ 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 razem
real 0m0.337s
user 0m0.032s
sys 0m0.029s0,3 sekundy na liście 10 000 plików, rekord.
Konfigurujemy Sherlocka
Od 13 sekund z ustawieniami domyślnymi do 0,3 sekundy z niewielką konfiguracją LS_COLORS oznacza 40-krotne przyspieszenie dzięki braku setuid / setgid i kolorowanych plików wykonywalnych. Nie taka wielka strata.
Oczywiście, teraz jest to skonfigurowane w Sherlock dla każdego użytkownika.
Ale jeśli chcesz przywrócić kolorowanie, możesz po prostu wrócić do ustawień domyślnych:
$ unset LS_COLORS Ale wtedy na katalogach z dużą ilością plików koniecznie parz kawę, podczas gdy to działa. ls.
Źródło: habr.com
