Bash:以随机索引访问大型数组很慢

时间:2018-10-02 05:31:31

标签: arrays bash performance

当我创建一个大型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,由:串联。有什么办法可以快速做到这一点?

1 个答案:

答案 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倍(要花一粒以上的盐),但是当然仍然比优化的本机实现慢类似的倍数。