#ls #posix #size #replace #libc #faster #tell

程序 fls

一个快速的POSIX ls,无需libc

1 个不稳定版本

0.1.0 2021年8月2日

#407Unix API

GPL-3.0-or-later

68KB
2K SLoC

fls

一个接近POSIX兼容且无需libc的 ls,比GNU的更小、更快、更美观。

exalsd 都是优秀的 ls 类似Rust程序,但它们的速度比系统 ls 慢,且代码大小大约是其10倍。此外,您实际上不能用它们中的任何一个替换 ls,因为某些软件依赖于解析 ls 的输出。但即使作为用户体验的改进,我认为其他项目讲述了一个错误的故事;现代软件不需要更大或更慢。

1我并不是要批评GNU的 ls,但据我所知,它是我在所重视的指标上最接近的东西。

粗略基准测试

--color=never -R / > /dev/null --color=always -R / --color=auto ~ --color=auto -l ~
fls 0.66 秒 2.32 秒 0.16 毫秒 0.30 毫秒
GNU ls 1.22 秒 4.37 秒 0.38 毫秒 2.30 毫秒
exa 3.61 秒 63.7 秒 3 0.78 毫秒 3.30 毫秒 4
lsd ???2 ???2 36.5 毫秒 36.8 毫秒

这些并不涵盖所有合理的选项组合,但如果您找到了一个组合,其中 fls 比任何替代方案都慢,请提出一个问题。

2lsd 无法检测符号链接循环,因此在 -R / 上会无限运行。
3我有一些大型模糊测试语料库的目录;从我收集这些数据时运行的 perf top,我看到 exa 大部分时间都花在 term_grid::Grid::column_widths 上。我怀疑它的网格布局算法是二次的。
4我报告的所有情况都是墙时间;这是唯一一个CPU时间有显著差异的情况。 exa 的CPU时间是 ~2.2 倍这个值。

"无需libc"

fls 不链接到任何内容。经过(去除)的 fls 可执行文件比 GNU 的(去除)的 ls 可执行文件小,尽管一些驱动 GNU 的代码位于另一个文件中。

更小且更快?

对代码大小的最大影响是 #![no_std],因为标准库的运行时相对较大。标准库的大部分单个组件大小都很合理,但生成回溯的代码非常大,据我所知,#![no_std] 是唯一去除它的方法。其余的代码大小主要通过运行出色的工具 cargo bloat 来缩减,该工具用于识别替换泛型以运行时调度的位置,并通过手动审查代码来提取重复的代码模式。

在速度方面,fls 可能比 GNU 的 ls 更快,因为它不使用 POSIX 接口来列出文件。我们直接调用 getdents64 并解析输出,而不是玩弄 read_dir 的调用。由于我们调用 getdents64,我们可以访问可选的目录条目类型信息,这通常让我们省去许多 stat 调用,这些调用相对于其他文件系统系统调用可能很昂贵。我说“可能”,因为 fls 总是比 GNU 的 ls 更快。原始目标是直接使用 getdents64(见下文),一旦我有了可工作的原型,它就比竞争者更快。

--颜色=auto

fls--color=always--color=never 与 GNU ls 具有相同的解释,但在 --color=auto 下,fls 将仅根据文件扩展名和从 getdents64 可用的信息应用颜色,这是可选的。因此,fls --color=auto 的颜色是不可预测的,但你可以在不进行任何昂贵的 stat 调用的同时得到一些输出颜色。fls 是在我开发环境是一个计算节点和 HPC 文件系统时开发的,而在大型目录中使用 ls --color=always 可能需要几秒钟到几分钟。而 fls --color=auto 在那些目录中提供了相同的颜色,只需一眨眼的时间。因此,如果没有提供参数且标准输出是终端,则默认使用 --color=auto

排序

在没有选项的情况下,fls 使用类似于 ls -v 的比较函数对名称进行排序,该函数尝试将数字序列视为单个数字。您不需要在文件名中填充数字到固定宽度,以便它们按直观顺序显示。

POSIX 功能

  • -A 不要列出隐含的 ...
  • -C 按列列出列表条目
  • -F 在条目后附加指示符
  • -H 当在命令行上提供时跟随符号链接
  • -L 总是跟随符号链接
  • -R 递归到子目录中
  • -S 按大小排序
  • -a 不要忽略以点(.)开头的条目
  • -c 按ctime排序
  • -d 列出目录本身,而不是其内容
  • -f 不排序
  • -g 长格式但无所有者
  • -i 打印每个条目的inode
  • -k 假设块大小为1024字节
  • -l 长格式
  • -m 单行,由逗号(,)分隔
  • -n 长格式但列出uid和gid而不是名称
  • -o 长格式但无组
  • -p 在目录后附加指示符
  • -q 将不可打印的字符替换为问号(?)
  • -r 反向排序顺序
  • -s 打印每个文件的块大小
  • -t 按修改时间排序
  • -u 按访问时间排序
  • -x 按行排序条目
  • -1 每行列出一条条目

依赖关系

~2MB
~40K SLoC