这是一个 bash 脚本,您可以在文件(或者如果您愿意,也可以是文件的子集)上运行。它将密钥文件分割成越来越大的块,并为每个块尝试 grep 操作。这些操作是计时的——现在我正在计时每个 grep 操作,以及处理所有子表达式的总时间。
输出以秒为单位 - 通过一些努力,您可以获得毫秒,但您遇到的问题不太可能需要这种粒度。
使用以下形式的命令在终端窗口中运行脚本
./timeScript keyFile textFile 100 > outputFile
这将运行脚本,使用 keyFile 作为存储搜索键的文件,使用 textFile 作为您要查找键的文件,并使用 100 作为初始块大小。在每个循环中,块大小都会加倍。
在第二个终端中,运行命令
tail -f outputFile
它将跟踪您的其他进程的输出到文件outputFile
我建议您打开第三个终端窗口,并在该窗口中运行top。您将能够看到您的进程占用了多少内存和 CPU - 同样,如果您看到大量内存消耗,它会提示您事情进展不顺利。
这应该可以让您了解事情何时开始放缓 - 这就是您问题的答案。我不认为有一个“神奇的数字”——它可能取决于您的机器,尤其是文件大小和您拥有的内存量。
您可以获取脚本的输出并通过 grep:
grep entire outputFile
您最终只会得到摘要 - 块大小和所用时间,例如
Time for processing entire file with blocksize 800: 4 seconds
如果您将这些数字相互对照(或简单地检查数字),您将看到算法何时最佳,何时变慢。
这是代码:我没有进行广泛的错误检查,但它似乎对我有用。显然,在您的最终解决方案中,您需要对 grep 的输出做一些事情(而不是将其通过管道传送到 wc -l,我这样做只是为了查看匹配了多少行)...
#!/bin/bash
# script to look at difference in timing
# when grepping a file with a large number of expressions
# assume first argument = name of file with list of expressions
# second argument = name of file to check
# optional third argument = initial block size (default 100)
#
# split f1 into chunks of 1, 2, 4, 8... expressions at a time
# and print out how long it took to process all the lines in f2
if (($# < 2 )); then
echo Warning: need at leasttwo parameters.
echo Usage: timeScript keyFile searchFile [initial blocksize]
exit 0
fi
f1_linecount=`cat $1 | wc -l`
echo linecount of file1 is $f1_linecount
f2_linecount=`cat $2 | wc -l`
echo linecount of file2 is $f2_linecount
echo
if (($# < 3 )); then
blockLength=100
else
blockLength=$3
fi
while (($blockLength < f1_linecount))
do
echo Using blocks of $blockLength
#split is a built in command that splits the file
# -l tells it to break after $blockLength lines
# and the block$blockLength parameter is a prefix for the file
split -l $blockLength $1 block$blockLength
Tstart="$(date +%s)"
Tbefore=$Tstart
for fn in block*
do
echo "grep -f $fn $2 | wc -l"
echo number of lines matched: `grep -f $fn $2 | wc -l`
Tnow="$(($(date +%s)))"
echo Time taken: $(($Tnow - $Tbefore)) s
Tbefore=$Tnow
done
echo Time for processing entire file with blocksize $blockLength: $(($Tnow - $Tstart)) seconds
blockLength=$((2*$blockLength))
# remove the split files - no longer needed
rm block*
echo block length is now $blockLength and f1 linecount is $f1_linecount
done
exit 0