Bash 脚本;优化处理速度

Vin*_*ent 11 performance shell-script

我想知道是否有优化 Bash 脚本的一般准则。

  • 例如,写循环比写命令更方便,但为系统处理是否也更快?例子:

    for i in a b c; do echo $i; done
    
    echo a
    echo b
    echo c
    
    Run Code Online (Sandbox Code Playgroud)
  • 有时人们会针对同一问题提出不同的解决方案。例如,sedcutawkecho都能够从字符串中去除数字。我想知道您是否可以说代码的位数越少,如果您使用它,速度就越快:

    1. 相同的命令,例如

      STRING=abc.def
      echo ${STRING} | sed 's/.def//g'
      echo ${STRING} | sed '$s/....$//'
      
      Run Code Online (Sandbox Code Playgroud)
    2. 不同的命令,例如

      STRING=abc.def
      echo ${STRING} | cut -d . -f 1
      echo ${STRING} | sed 's/.def//g'
      
      Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 25

优化的第一条规则是:不要优化。先测试。如果测试表明您的程序太慢,请寻找可能的优化。

唯一确定的方法是对您的用例进行基准测试。有一些通用规则,但它们仅适用于典型应用程序中的典型数据量。

在任何特定情况下可能正确也可能不正确的一些一般规则:

  • 对于 shell 中的内部处理,ATT ksh 是最快的。如果您进行大量字符串操作,请使用 ATT ksh。Dash 排在第二位;bash、pdksh 和 zsh 落后了。
  • 如果您需要频繁调用 shell 以每次执行非常短的任务,那么 dash 会因其启动时间短而胜出。
  • 启动外部流程会花费时间,因此拥有一个包含复杂片段的管道比循环中的管道更快。
  • echo $foo比 慢echo "$foo",因为没有双引号,它会拆分$foo成单词并将每个单词解释为文件名通配符模式。更重要的是,很少需要这种拆分和通配行为。所以请记住始终在变量替换和命令替换周围加上双引号:"$foo", "$(foo)"
  • 专用工具往往胜过通用工具。例如,像cut或 之类的工具head可以用 来模拟sed,但sed会更慢,awk甚至会更慢。Shell 字符串处理很慢,但对于短字符串,它在很大程度上优于调用外部程序。
  • 更高级的语言(例如 Perl、Python 和 Ruby)通常可以让您编写更快的算法,但它们的启动时间要长得多,因此它们只值得为大量数据提供性能。
  • 至少在 Linux 上,管道往往比临时文件更快。
  • shell 脚本的大多数用途都是围绕 I/O 绑定的进程,因此 CPU 消耗并不重要。

在 shell 脚本中很少考虑性能问题。上面的列表纯粹是指示性的;在大多数情况下使用“慢”方法完全没问题,因为差异通常只有百分之几。

通常,shell 脚本的目的是快速完成某些工作。您必须从优化中获益良多,才能证明花费额外的时间来编写脚本是合理的。

  • Re *“您必须从……中获得很多”*:如果 *“您”* 包括用户群,则为真。使用流行的 Linux 软件包中的 shell 脚本,用户通常比草率的程序员节省的时间多几个数量级。 (3认同)
  • 尽管 `python` 和 `ruby` 启动起来肯定较慢,至少在我的系统上,`perl` 启动起来与 `bash` 或 `ksh` 一样快。GNU awk 比 GNU sed 慢得多,尤其是在 utf-8 语言环境中,但并非所有 awk 和所有 sed 都如此。ksh93 > dash > pdksh > zsh > bash 并不总是那么清晰。有些贝壳在某些方面比其他贝壳更好,而且赢家并不总是相同的。 (2认同)

von*_*and 8

Shell 不会对他们收到的代码进行任何重组,它只是一行一行地解释(在命令解释器中没有其他任何意义)。shell 花费的大部分时间都用于词法分析/解析/启动调用的程序。

对于简单的操作(比如问题末尾示例中的那些处理字符串),如果加载程序的时间没有淹没任何微小的速度差异,我会感到惊讶。

这个故事的寓意是,如果你真的需要更高的速度,你最好使用(半)编译语言,比如 Perl 或 Python,它们运行起来更快,你可以在其中编写许多直接提到的操作并且不必调用外部程序,并且可以选择调用外部程序或调用优化的 C(或其他)模块来完成大部分工作。这就是为什么在 Fedora 中“系统管理糖”(本质上是 GUI)是用 Python 编写的:可以添加一个漂亮的 GUI,不需要太多的努力,对于此类应用程序来说足够快,可以直接访问系统调用。如果这还不够速度,请使用 C++ 或 C。

但是不要去那里,除非你能证明性能提升值得失去灵活性和开发时间。Shell 脚本读起来还不错,但是当我想起我曾经试图破译的一些用于安装 Ultrix 的脚本时,我不寒而栗。我放弃了,应用了太多的“shell 脚本优化”。