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,
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=auto
alels
wykrywa, kiedy nie jest podłączony do terminala (np. potokiem lub z przekierowaniem wyjścia) i wyłącza kolorowanie, jeśli jest ustawione naauto
. 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ą
$ 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.
, ani przez
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