在bash和dash的速度方面是否有具体的数据?

根据这篇文章,选择将dash作为/bin/sh的原因是因为bash较慢:Dash as /bin/sh
有没有具体的数据显示dashbash快多少?
如果使用bash而不是dash来启动Ubuntu,需要多长时间?
上述链接的论点今天是否仍然有效?背景是:system-v init使用了很多shell脚本,但systemd没有。
这个问题不是关于合成基准测试中的速度,而是关于对最终用户的整体明显好处。关于dash与bash速度的合成基准测试不能回答这个问题。

2/bin/dash的发明是因为当时实际的Bourne shell和Korn shell不是开源的(80年代末90年代初),而且是专有的。 - Sergiy Kolodyazhnyy
1@SergiyKolodyazhnyy 但是在创建ash时,bash已经存在了。 - Sebastian Stark
此外,启动过程涉及一个初始化系统,它实际上是启动服务的关键。Shell 是用于通过脚本执行命令和自动化操作的工具,虽然可能作为初始化系统的一部分使用,但在启动过程中并不起主要作用。 - Sergiy Kolodyazhnyy
@SebastianStark 确实存在。但是有多个原因需要实际上的 Bourne shell 替代品。一、POSIX 兼容性。二、bash 是 GNU 的东西,在 Linux 上很好,因为大部分 Linux 社区最初来自 GNU 项目,但在 BSD 项目上并不那么受欢迎。而且 dash 本身是 Debian 实现的 ash(Almquist)shell,最初是一个 Open BSD 的东西。 - Sergiy Kolodyazhnyy
@SebastianStark 我强烈建议你查看wjandrea评论中的第二个链接。Gilles的回答非常全面。而且他和Stephane Chazelas对Unix历史的了解可能比整个Stackexchange网络上的任何人都要多。 - Sergiy Kolodyazhnyy
另请参阅https://unix.stackexchange.com/q/148035/85039 - Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy 这个问题不是关于速度,而是关于整体效益。 - guettli
@guettli 嗯,你确实要求提供具体的数据,而提供的链接中有关于外壳的具体测试。而且速度不是一个总体上的好处吗?如果我们谈论企业级处理,那么速度、维护成本和可移植性将是管理人员对系统管理员管理服务器的首要要求之一。嗯,让我问一下:到目前为止,确切地缺少什么?你得到了你希望得到的答案吗?有什么不清楚的地方吗? - Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy 或许我有所遗漏,但测试是在使用systemd之前完成的。旧的init系统非常依赖shell。我认为最好的解决方案是选择使用systemd并减少大量的shell进程。不使用shell确实提高了速度。我感到悲伤,因为很多宝贵的开发者因为/bin/dash的限制而失去了机会。找到错误、修复错误只是因为一些人认为/bin/dash是一个好的解决方案。我认为systemd是一个好的选择,/bin/dash不是。 - guettli
@guettli 你忽略的关键点是,shell和init系统是两个不同的东西。虽然System V使用了shell脚本,但它并不完全由shell脚本组成,它也主要是用C语言编写的,就像systemd一样。所以实际上你在问的是苹果和橙子的区别,shell和init只有部分相关。/bin/dash并不是用于引导启动的,它是用来运行脚本的,并且已经证明它比其他shell更快。 - Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy 有时候我喜欢戴上“最终用户眼镜”。然后我完全不关心实现细节。我关心的是净结果,总体利益。从shell脚本中删除bashism需要花费很多时间。在大多数情况下,我看不到任何好处。我知道在某些边缘情况(或特殊环境,如嵌入式设备)中它是有用的。但总的来说,我认为去除bashism是浪费时间。你可能会感觉很好,因为你认为你正在做好事……但你得到了什么?在合成基准测试中节省几秒钟? - guettli
@SebastianStark 如果对最终用户没有明显的好处,为什么要做某件事呢?我不明白这一点。 - guettli
终端用户是一个广泛的类别。他们可以是关注运行时间、速度和符合特定标准的企业级公司。再次强调,shell 是用于脚本编写的。如果你在多操作系统环境中使用 shell 脚本,最好使用 /bin/sh。Linux 和 Unix 不仅仅局限于桌面或引导过程。 - Sergiy Kolodyazhnyy
@SergiyKolodyazhnyy,你能否详细说明为什么/bin/sh更好?由于/bin/sh可以是任何东西,我认为/bin/bash要更安全,因为兼容性问题很少见。尽管如此,它们确实存在,因为在一个系统上/bin/bash可能是x版本,在另一个系统上可能是y版本。 - guettli
@guettli 当然可以,但是我现在工作很忙,所以我需要几天时间才能添加。我会告诉你的。 - Sergiy Kolodyazhnyy
@guettli 我稍微更新了我的回答,也加入了一些观点。我只希望这能在一定程度上帮助解释为什么破折号并不完全是(运行时)优化的问题。 - Sebastian Stark
1个回答

这个测试并不代表启动过程,但你可以通过编写一个小的测试脚本来自己尝试一下,我称之为shspeed
$ cat shspeed
for a in `seq 10000`; do ( :; ); done

这只是简单地连续分叉10000个子shell。现在用bash和dash运行它,并计时:
$ time dash shspeed
dash shspeed  0,70s user 0,33s system 107% cpu 0,965 total

$ time bash shspeed
bash shspeed  1,59s user 0,76s system 108% cpu 2,180 total

所以,在我的硬件上速度要快得多,我的硬件是一台大约1年的Dell XPS 13 9365。你可以想象在低端硬件上会有更大的差异。此外,这个测试只涉及一个for循环和生成一个子shell。也许对于某些测试来说,结果会更加显著。
当然,你可以忽略这一点,并说你不关心生成10000个子shell的速度有多快。嗯,有些人似乎很在意 :)
对于你特定的启动过程,可能不会有任何明显的差异。如果你使用/bin/bash作为/bin/sh,并用秒表测量差异,我认为没有问题。
请查看@wjandrea提供的以下链接,详细解释了这个问题:https://wiki.ubuntu.com/DashAsBinShWhat is the point of sh being linked to dash?

在systemd时代的Shell速度

在你修改了问题之后,它听起来更像是你对于哪个shell更快速并不那么感兴趣,而更关注为什么我们仍然坚持让启动过程快上半秒(或者类似的时间),尤其是现在我们不再像sysv-init标准时期那样广泛使用shell脚本。
由于我不参与Ubuntu的政治事务,我会尽力给出一个我认为的答案:
1. 如果通过简单地使用符号链接到另一个shell可以使某个东西快上半秒,那是值得的。 2. 让默认shell只做POSIX要求的事情是有道理的,这样可以保持可移植性。想象一下,一个发行版在初始化脚本中使用了bash的特性,而另一个发行版没有(至少目前没有)。 3. 添加(d)ash也是为了能够修复标准脚本中的bashism,并避免将来出现这种情况。/bin/sh是一个公认的标准,很多大型基础设施都依赖它。我不希望用一个代码库更庞大、功能不必要的东西来替代它。 4. 使用更少的CPU周期和内存总是值得的。即使systemd单位通常在后台运行shell脚本。
所有这些对于普通用户来说可能都是无关紧要的,但间接地,他们得到的是一个更稳定的系统发行版。
为什么不用bash呢?
这更多是个人意见:就我个人而言,我永远不会选择在dash中编写脚本。它只提供了非常基本的结构。对于一个更大的软件项目,我宁愿选择bash或zsh(或者根本不使用shell)。也许我想要使用哪些功能:高级参数展开、shell算术、数组,或许还有其他一些。
这在主要用于启动守护进程或安装软件的脚本中是不应该发生的。这些脚本应该使用最少的指令,并保持可读性和简单性。但是,如果所有bash的好处都能够为它们所用,很可能会发生这种情况。
/bin/sh 应该主要用于在合理便捷的环境中运行外部程序,而不是用于复杂的软件系统。
总结
/bin/sh 作为dash实现的POSIX兼容的快速稳定的脚本语言,在系统的shell脚本中表现出色,成为了标准和默认的解释器。这些特性绝不会为了方便而牺牲。
从程序员的角度来看,它实现了“专一而精”的宗旨。
这不是主要的优化,而是责任分离。

它已经在那里了,所以保持它不需要额外的努力。

从最终用户的角度来看,这引出了一个问题:是什么样的最终用户?桌面用户可能无所谓,但他们仍然会受益于更稳定(也许稍微快一点)的发行版。软件包维护者会非常关心,他们受益于一个可靠的系统解释器,具有一小部分明确定义和经过充分测试的功能。程序员不应该关心,因为他们很可能不在/bin/sh中开发。

附注:bash二进制文件的大小几乎是dash二进制文件的10倍!


1大括号不会生成子shell,而圆括号会。请参考man bash - wchargin
2使用for a in $(seq "$1"); do ( :; ); done生成子shell时,我的结果是:dash花费1.306秒,bash花费4.446秒(10000次迭代,3次最佳时间,2014 T440s)。 - wchargin
你说:“bash二进制文件的大小几乎是dash二进制文件的10倍!”我说:“以后再优化”。 - guettli
@wchargin 多尴尬啊,我搞混了。我修正了答案,并将其减少到10000轮。谢谢! - Sebastian Stark
@SebastianStark "bash二进制文件的大小几乎是dash二进制文件的10倍!" 对你来说似乎非常重要。我无法理解你的观点。我并不使用嵌入式设备。这对最终用户有什么好处呢?我猜普通的Linux用户(或应用程序)看不出任何区别。你是对的:Bash更大。但如果大小没有任何不利影响,那对我来说就不重要。你怎么看? - guettli
我的比率是:对于100,000次循环,bash的时间要比dash长7.11倍。(这只是出于我个人的兴趣而做的) - Doug Smythies
你在谈论启动守护进程。自从有了systemd,我认为在init系统和守护进程之间不再需要一个shell。守护进程不再需要进行双重fork的魔法操作。只需在前台启动,并使用systemd的守护进程类型"simple"即可。 - guettli
@guettli 你说得对,没必要这样做。但仍有第三方软件包可以实现它。另外不要忘记预安装/后安装脚本。 - Sebastian Stark
@SebastianStark 你说我不应该忘记“预安装/后安装”脚本。我认为如果所有这些脚本都使用/bin/bash,那么最终结果可以被视为微不足道。 - guettli
@guettli 在我的回答中,我除了速度之外还给出了足够的理由来解释为什么它仍然是有意义的。 - Sebastian Stark