当我创建一个大型bash数组(即> 10000个元素)时,在随机位置访问它的速度很慢。
考虑以下示例:
a=($(seq 1000000))
while true; do
idx=$(( ($RANDOM * 32786 + $RANDOM) % 1000000 ))
echo ${a[idx]}
done | pv -r --line-mode 1>/dev/null
这显示了每秒仅500行的吞吐量。 排除访问权限会使性能恢复到合理的水平。
这是为什么?数组是否以某种怪异的方式实现了?
在一个更现实的示例中,我正在从文件中读取一些1Mio ID,并尝试准备大约100k个存储桶(即输出行),每个存储桶有30个ID,由:
串联。有什么办法可以快速做到这一点?
答案 0 :(得分:2)
尽管bash确实是该工作的错误工具(链接列表,请参见上面的注释),但仍然可以使用coproc和shuf -r
来达到可接受的性能。
一个稍微复杂的示例,需要上面的$a
:
(
coproc rid {
for e in "${a[@]}"; do
echo "$e";
done | shuf -r;
};
seq 150000 \
| while read s; do
for i in {1..10}; do
read -u ${rid[0]} a;
s="$s:$a";
done;
echo "$s";
done
) | pv -ls 150000 >/dev/null
-r
得到shuf
不会洗牌,而只是吐出随机元素而不会无限期记忆。( )
是必需的,因为我希望循环的输出转到pv
进行测量。这显示了此解决方案的问题:我认为coprocs不易于使用,因为您无法从子shell中读取它们的输出,因此必须考虑如何干净地终止它们。 shopt -s lastpipe
可能会帮助您解决一些问题。总而言之,这比原始版本快200倍(要花一粒以上的盐),但是当然仍然比优化的本机实现慢类似的倍数。