Khi một biến môi trường tăng tốc quá trình lên 40 lần

Hôm nay chúng tôi muốn nói về một số cập nhật mới nhất cho hệ thống Sherlock [đây là cụm hiệu suất cao tại Đại học Stanford - khoảng. trans.], giúp tăng tốc đáng kể việc liệt kê các tệp trong thư mục có số lượng mục nhập lớn.

Không giống như các bài viết thông thường, đây là báo cáo nội bộ về cách chúng tôi thường xuyên làm việc trên Sherlock để đảm bảo nó hoạt động tốt nhất cho người dùng. Chúng tôi hy vọng sẽ xuất bản nhiều bài viết như thế này trong tương lai.

Liệt kê nhiều tập tin mất thời gian

Tất cả bắt đầu với một câu hỏi hỗ trợ kỹ thuật từ người dùng. Ông báo cáo vấn đề rằng việc thực hiện ls mất vài phút trong một thư mục với hơn 15 mục trong $SCRATCH [thư mục chứa các tập tin tạm thời - khoảng. làn đường].

Hàng nghìn tệp trong một thư mục thường gây gánh nặng cho hệ thống tệp và chắc chắn không được khuyến khích. Người dùng biết điều này và thừa nhận rằng nó không tốt, nhưng đề cập rằng danh sách trên máy tính xách tay của anh ấy nhanh hơn Sherlock 1000 lần. Tất nhiên, điều này làm tổn thương chúng tôi. Vì vậy, chúng tôi đã nhìn sâu hơn.

Bởi vì ls trông đẹp

Chúng tôi đã xem xét những gì nó thực sự làm ls khi liệt kê một thư mục và tại sao quá trình này lại mất nhiều thời gian như vậy. Trên hầu hết các bản phân phối hiện đại ls theo mặc định nó chạy như ls --color=auto, bởi vì mọi người đều thích màu sắc.

Nhưng màu sắc đẹp có giá của nó: cho mỗi tập tin ls phải lấy thông tin về loại tệp, quyền, cờ, thuộc tính mở rộng và những thứ tương tự để chọn màu thích hợp.

Một giải pháp đơn giản cho vấn đề này là tắt hoàn toàn màu sắc trong ls, nhưng hãy tưởng tượng sự phẫn nộ của người dùng. Trong mọi trường hợp, bạn không nên lấy đi đầu ra màu sắc, chúng tôi không phải là quái vật.

Vì vậy, chúng tôi đã nhìn sâu hơn. ls mục màu sắc thông qua biến môi trường LS_COLORS, được thiết lập dircolors(1) dựa trên tập tin cấu hình dir_colors(5)... Đúng, tệp thực thi sẽ đọc tệp cấu hình để tạo một biến môi trường, sau đó ls sẽ sử dụng (và nếu bạn không biết về các tập tin cửa (làm), sau đó dir_colors sẽ làm việc, Bất chấp mọi thứ).

Chúng ta hãy xem xét kỹ hơn

Để xác định cách phối màu nào gây ra tình trạng chậm, chúng tôi đã tạo một môi trường thử nghiệm:

$ 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 giây cho 10 tệp, không tốt lắm.

Nhân tiện, chúng ta cần một lá cờ --color=always: mặc dù anh ấy quay sang ls --color=autonhưng ls phát hiện khi nó không được kết nối với thiết bị đầu cuối (ví dụ: bằng đường ống hoặc chuyển hướng đầu ra) và tắt màu nếu được đặt thành auto. Anh chàng thông minh.

Vậy có chuyện gì mà lâu thế? Chúng tôi đã nhìn với 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
[...]

Ôi: 10 cuộc gọi lstat(), 10 cuộc gọi getxattr() (tất cả đều thất bại vì môi trường của chúng tôi không có các thuộc tính mà tôi đang tìm kiếm), 10 cuộc gọi capget().

Chắc chắn điều này có thể được tối ưu hóa.

Thuộc tính khả năng? Không

Làm theo lời khuyên lỗi từ 10 năm trước, chúng tôi đã cố gắng tắt tính năng kiểm tra thuộc tính khả năng:

$ 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, tăng tốc lên tới 8 giây! Chúng tôi đã loại bỏ tất cả những cuộc gọi đắt tiền đó getxattr(), và những thách thức capget() cũng biến mất, tuyệt vời.

Nhưng vẫn có những cuộc gọi khó chịu lstat(), Mặc dù…

Bạn cần bao nhiêu bông hoa?

Vì vậy, chúng tôi đã xem xét kỹ hơn LS_COLORS.

Đầu tiên chúng tôi chỉ đơn giản là vô hiệu hóa biến này:

$ 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

Cái gì!?! Vẫn còn 13 giây?

Hóa ra là khi biến môi trường LS_COLORS chỉ một trong các phần tử của nó không được xác định hoặc bị thiếu <type>=color:, nó sử dụng cơ sở dữ liệu tích hợp theo mặc định và vẫn sử dụng màu sắc. Vì vậy, nếu bạn muốn tắt tính năng tô màu cho một loại tệp nhất định, bạn cần ghi đè nó bằng <type>=: hoặc <type> 00 trong tập tin DIR_COLORS.

Sau rất nhiều thử nghiệm và sai sót, chúng tôi đã thu hẹp phạm vi tìm kiếm của mình xuống mức này:

EXEC 00
SETUID 00
SETGID 00
CAPABILITY 00

được viết là

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

Điều này có nghĩa là: không tô màu các tập tin theo thuộc tính. khả năng, nhưng từng chút một setuid/setgid, không phải bởi cờ thực thi.

Chúng tôi tăng tốc ls

Và nếu bạn không thực hiện bất kỳ kiểm tra nào trong số này thì hãy gọi lstat() biến mất, và bây giờ nó là một vấn đề hoàn toàn khác:

$ 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 giây trên danh sách 10 tệp, một bản ghi.

Đang thiết lập Sherlock

Từ 13 giây với cài đặt mặc định đến 0,3 giây với những điều chỉnh nhỏ LS_COLORS có nghĩa là tăng tốc gấp 40 lần do không có setuid / setgid và các tập tin thực thi được tô màu. Không phải là một mất mát lớn như vậy.

Tất nhiên, điều này hiện đã được định cấu hình trong Sherlock cho từng người dùng.

Nhưng nếu bạn muốn trả lại màu, bạn chỉ cần quay lại cài đặt mặc định:

$ unset LS_COLORS

Nhưng sau đó, trên các thư mục có nhiều tệp, hãy nhớ pha cà phê trong khi nó đang chạy ls.

Nguồn: www.habr.com

Thêm một lời nhận xét