如何使awk命令在大型数据文件上运行更快

时间:2018-10-01 21:45:34

标签: bash performance shell awk

我使用下面的awk命令在现有.dat文件中的表中创建新的UUID列。

$ awk '("uuidgen" | getline uuid) > 0 {print uuid "|" $0} {close("uuidgen")}' $filename > ${filename}.pk

问题是我的.dat文件很大(例如50-60 GB),即使在较小的数据文件(例如15MB)上,此awk命令也要花费数小时。

有什么方法可以提高此awk命令的速度吗?

3 个答案:

答案 0 :(得分:1)

我想知道是否通过不用awk打开和关闭uuidgen每行来节省时间。

$ function regen() { while true; do uuidgen; done; }
$ coproc regen
$ awk -v f="$filename" '!(getline line < f){exit} {print $0,line}' OFS="|" < /dev/fd/${COPROC[0]} > "$filename".pk

这已经从变量中读取您的“真实”文件名,并从标准输入中读取了uuid,因为对uuidgen的调用是由bash“ coprocess”处理的。 getline周围的时髦之处在于,一旦awk用完$filename的输入,便告诉awk退出。另外,请注意,awk从输入重定向中获取输入,而不是直接读取文件。这个很重要; /dev/fd/##处的文件描述符是一个 bash 东西,awk无法打开它。

从理论上讲,这应该可以节省您执行不必要的系统调用来打开,运行和关闭uuidgen二进制文件的时间。另一方面,通过在循环中运行uuidgen,协同进程几乎可以做同样的事情。也许您会在SMP环境中看到一些改进。我没有用于基准测试的50GB文本文件。我很想听听您的结果。

请注意,coproc是bash版本4引入的功能。使用/dev/fd/*要求bash在文件描述符支持下进行编译。在我的系统中,这还意味着我必须确保已安装fdescfs(5)


我刚在系统(FreeBSD 11)上注意到以下内容:

$ /bin/uuidgen -
usage: uuidgen [-1] [-n count] [-o filename]

如果您的uuidgen也有一个-n选项,那么将它与ANY值一起添加到您的regen()函数中可能是一个有用的优化方法,以减少命令需要执行的次数。重新打开。例如:

$ function regen() { while true; do uuidgen -n 100; done; }

这将导致uuidgen每100行输入仅被调用一次,而不是每行被调用。


如果您正在运行Linux,则取决于您的设置方式,您可能会有UUID的备用来源。注意:

$ awk -v f=/proc/sys/kernel/random/uuid '{getline u<f; close(f); print u,$0}' OFS="|" "$filename" "$filename".pk

这不需要bash coproc,它只是直接从提供内核的Linux内核函数中awk直接读取了随机uuid。您仍在关闭输入的每一行的文件句柄,但至少不必执行uuidgen二进制文件。

YMMV。我不知道您正在运行什么操作系统,所以我不知道哪种可能适合您。

答案 1 :(得分:0)

我只是在猜测真正的问题是您正在为每行运行一个子流程。您可以逐行显式读取文件,并逐行读取batch-uuidgen的输出,因此只能一次处理一个子进程。不幸的是,uuidgen不能那样工作。

也许是另一个解决方案?

perl -MData::UUID -ple 'BEGIN{ $ug = Data::UUID->new } $_ = lc($ug->to_string($ug->create)) . " | " . $_' $filename > ${filename}.pk

这会更快吗?

答案 2 :(得分:0)

您的脚本正在调用shell来调用awk来调用shell来调用uuidgen。 Awk是用于处理文本的工具,它不是shell(可以从中调用其他工具的环境),所以不要那样做,只需从shell调用uuidgen:

$ cat file
foo .*
bar stuff
here

$ xargs -d $'\n' -n 1 printf '%s|%s\n' "$(uuidgen)" < file
5662f3bd-7818-4da8-9e3a-f5636b174e94|foo .*
5662f3bd-7818-4da8-9e3a-f5636b174e94|bar stuff
5662f3bd-7818-4da8-9e3a-f5636b174e94|here