当环境变量将过程加快40倍时

今天,我们想谈谈Sherlock系统的一些最新更新[这是斯坦福大学的高性能集群-大约是。 per。],大大加快了具有大量条目的目录中文件的列出。

与常规文章不同的是,这更多是内部调查报告,内容是有关Sherlock的常规工作如何进行的,以便以最佳方式维护用户。 我们希望将来发布更多此类文章。

列出许多文件需要时间


一切都始于用户提出的技术支持问题。 他报告了一个问题,即在目录$SCRATCH有超过15,000个条目的目录中运行ls花费几分钟时间。 跨]。

一个目录中的成千上万个文件通常会给文件系统带来麻烦,因此绝对不建议这样做。 用户知道这一点,并承认这不好,但是他提到在笔记本电脑上的挂牌速度比Sherlock快1000倍。 当然,它打击了我们。 因此,我们看起来更深入。

因为ls看起来很漂亮


我们查看了ls列出目录时的实际作用,以及该过程花了这么长时间的原因。 在大多数现代发行版中, ls默认为ls --color=auto ,因为每个人都喜欢这种颜色。

但是漂亮的颜色是有代价的:对于每个文件, ls需要获取有关文件类型,其权限,标志,高级属性等的信息,以便选择适当的颜色。

解决此问题的简单方法之一是完全禁用ls,但请想象一下用户的愤怒。 在任何情况下,您都不能输出颜色,我们不是怪物。

因此,我们看起来更深入。 ls通过LS_COLORS环境LS_COLORS绘制记录,该LS_COLORSdircolors(1)根据dir_colors(5)配置文件设置的。 是的, 可执行文件读取配置文件以创建一个ls然后使用的环境变量 (如果您不知道门 (do)文件,则dir_colors 可以使用 ,无论如何)。

我们将更详细地了解


为了确定哪种着色方案会导致速度降低,我们创建了一个实验环境:

 $ 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 

10,000个文件需要12.7秒,不是很好。
顺便说一句,我们需要标志--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,000次调用lstat() ,10,000次调用getxattr() (每个人都失败了,因为在我们的环境中ls不会寻找属性),10,000次调用capget()

当然可以优化。

能力属性 不


遵循十年前错误建议,我们尝试禁用功能属性的检查:

 $ 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:或= 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:*。cpi​​o = 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:
 $未设置LS_COLORS
 $ echo $ LS_COLORS

 $ time ls --color =总是$ SCRATCH / dont |  wc -l
 10,000

真正的0m13.037s
用户0m0.077s
 sys 0m1.092s 

什么!?! 还是13秒?

事实证明,当LS_COLORS环境LS_COLORS或仅缺少其元素之一<type>=color: ,默认情况下它将使用内置数据库,并且仍使用颜色。 因此,如果要禁用特定文件类型的着色,则需要在DIR_COLORS文件中使用<type>=:<type> 00覆盖它。

经过大量的试验和错误,我们将搜索范围缩小到:

 EXEC 00 SETUID 00 SETGID 00 CAPABILITY 00 

什么写成

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

这意味着:请勿通过功能 atrubut, 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 

在10,000个文件的列表上记录了0.3秒。

配置夏洛克


从默认设置的13秒到小设置的0.3秒,由于缺少setuid / setgid和彩色的可执行文件, LS_COLORS意味着40倍的加速。 没有那么大的损失。

当然,现在在Sherlock中为每个用户配置了此功能。

但是,如果要返回颜色,则可以返回默认设置:

 $ unset LS_COLORS 

但是,在具有大量文件的目录上,请确保在ls工作时冲泡咖啡。

Source: https://habr.com/ru/post/zh-CN450806/


All Articles