Bash 脚本性能

Bash 脚本性能

bash脚本中,会生成某个范围内的一些整数,将其与固定字符串连接起来,然后打印在文件中。操作系统是 Ubuntu 14.04,bash版本是4.3.11(1)-release.

要打印的字符串(以及行)有数百万个。以下是iotop几次硬盘使用情况:

 TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND  
5701 be/4 myuser    408.24 B/s   97.27 K/s  0.00 %  0.23 % bash ./script.sh
5701 be/4 myuser    408.20 B/s   97.27 K/s  0.00 %  0.00 % bash ./script.sh
5701 be/4 myuser    408.41 B/s   95.72 K/s  0.00 %  0.11 % bash ./script.sh

打印100万个字符串大约需要16分钟。硬盘的带宽远未达到饱和。uptime执行超过 15 分钟后:

load average: 0,97, 1,14, 1,19

在 4 核 CPU 中。因此,CPU 和硬盘似乎都不是导致执行速度极慢的原因。

  1. 如何才能加快这一进程?

  2. 是否可以继续使用bash或者我应该使用其他语言?


脚本的相关部分如下:

#!/bin/bash

i=0
a='fixedstring1'
b='fixedstring2'

while [[ $i -le 9999999 ]]; do
[...]
    ur="$a""$b""$i"
[...]
    echo $ur >> exp1/file$m
[...]
    (( i++ ))
done

file$mm第一个生成的文件(脚本生成具有固定行数的多个文件,而不是具有所有行的唯一文件)。

答案1

在你的情况下,Bash 循环非常慢:

> cat test-1.sh
#!/bin/sh

i=0
a='fixedstring1'
b='fixedstring2'


while [ $i -lt ${1:-9} ]; do
  ur="$a""$b""$i"
  echo $ur
  (( i++ ))
done

> time sh test-1.sh 999999 | wc -l
...
real    1m11.488s

使用jot(或seq) 会使速度更快:

> cat test-3.sh
#!/bin/sh

a='fixedstring1'
b='fixedstring2'

jot -w "$a$b" ${1:-9}
# seq -f "$a$b%g" ${1:-9}
> time sh test-3.sh 999999 | wc -l
...
real    0m0.613s

以及拆分数字归档的逻辑是什么?如果只是简单地限制行数,您可以使用split命令(现在我的意思是GNU split由于使用-d选项):

sh test-3.sh | split -d -l "how much lines in one file" - expr1/file

答案2

您重复打开和关闭同一个文件(可能数百次)。尝试最多打开每个文件一次。

i=0
a='fixedstring1'
b='fixedstring2'
m=0

exec 3>exp1/file$m

while [[ $i -le 9999999 ]]; do
    ur="$a$b$i"
    if ... # m changes
    then
        exec 3>exp1/file$m
    fi
    echo $ur >&3
    (( i++ ))
done

这与重定向整个循环而不是重定向循环中的特定命令是相同的建议。

相关内容