在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 和硬盘似乎都不是导致执行速度极慢的原因。
如何才能加快这一进程?
是否可以继续使用
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$m
是m
第一个生成的文件(脚本生成具有固定行数的多个文件,而不是具有所有行的唯一文件)。
答案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
这与重定向整个循环而不是重定向循环中的特定命令是相同的建议。