JBo*_*Boy 14 bash benchmarking sed head cat
我必须从一个大文件(1500000行)中获取一个特定的行,在多个文件的循环中多次,我问自己什么是最好的选择(在性能方面).有很多方法可以做到这一点,我男子气概使用这些2
cat ${file} | head -1
Run Code Online (Sandbox Code Playgroud)
要么
cat ${file} | sed -n '1p'
Run Code Online (Sandbox Code Playgroud)
我找不到这个问题的答案,他们只获取第一行或两者之一(或两者)首先打开整个文件,然后获取第1行?
Chr*_*our 30
放弃无用的使用cat并做:
$ sed -n '1{p;q}' file
Run Code Online (Sandbox Code Playgroud)
这将sed在打印行后退出脚本.
基准测试脚本:
#!/bin/bash
TIMEFORMAT='%3R'
n=25
heading=('head -1 file' 'sed -n 1p file' "sed -n '1{p;q} file" 'read line < file && echo $line')
# files upto a hundred million lines (if your on slow machine decrease!!)
for (( j=1; j<=100,000,000;j=j*10 ))
do
echo "Lines in file: $j"
# create file containing j lines
seq 1 $j > file
# initial read of file
cat file > /dev/null
for comm in {0..3}
do
avg=0
echo
echo ${heading[$comm]}
for (( i=1; i<=$n; i++ ))
do
case $comm in
0)
t=$( { time head -1 file > /dev/null; } 2>&1);;
1)
t=$( { time sed -n 1p file > /dev/null; } 2>&1);;
2)
t=$( { time sed '1{p;q}' file > /dev/null; } 2>&1);;
3)
t=$( { time read line < file && echo $line > /dev/null; } 2>&1);;
esac
avg=$avg+$t
done
echo "scale=3;($avg)/$n" | bc
done
done
Run Code Online (Sandbox Code Playgroud)
只需保存benchmark.sh并运行即可bash benchmark.sh.
结果:
head -1 file
.001
sed -n 1p file
.048
sed -n '1{p;q} file
.002
read line < file && echo $line
0
Run Code Online (Sandbox Code Playgroud)
**来自1,000,000行的文件结果.*
因此,时间sed -n 1p将与文件的长度成线性增长,但其他变化的时间将是恒定的(并且可以忽略不计),因为它们在读取第一行后都退出:

注意:由于在更快的Linux机器上,时间与原始帖子不同.
如果你真的只是获得第一行并阅读数百个文件,那么考虑使用shell内置而不是外部外部命令,使用read内置用于bash和ksh的shell.这消除了进程创建的开销awk,sed,head,等.
另一个问题是对I/O进行定时性能分析.第一次打开然后读取文件时,文件数据可能没有缓存在内存中.但是,如果再次对同一文件尝试第二个命令,则数据和inode都已缓存,因此定时结果可能更快,几乎与您使用的命令无关.此外,inode可以保持几乎永远缓存.例如,它们在Solaris上运行.或者无论如何,好几天.
例如,linux缓存所有东西和厨房水槽,这是一个很好的性能属性.但如果您不了解这个问题,它会使基准测试成为问题.
所有这些缓存效果"干扰"都取决于操作系统和硬件.
所以 - 选择一个文件,用命令读取.现在它被缓存了.运行相同的测试命令几十次,这是对命令和子进程创建的效果进行采样,而不是I/O硬件.
在读取文件一次之后,这是获取同一文件的第一行的10次迭代的sed vs读取:
SED: sed '1{p;q}' uopgenl20121216.lis
real 0m0.917s
user 0m0.258s
sys 0m0.492s
Run Code Online (Sandbox Code Playgroud)
读: read foo < uopgenl20121216.lis ; export foo; echo "$foo"
real 0m0.017s
user 0m0.000s
sys 0m0.015s
Run Code Online (Sandbox Code Playgroud)
这显然是做作的,但确实显示了内置性能与使用命令之间的区别.
如果你只想从一个大文件中打印 1 行(比如第 20 行),你也可以这样做:
head -20 filename | tail -1
Run Code Online (Sandbox Code Playgroud)
我用 bash 做了一个“基本”测试,它的性能似乎比sed -n '1{p;q}上面的解决方案更好。
测试采用一个大文件并从中间的某个位置(第 行)打印一行10000000,重复 100 次,每次选择下一行。所以它选择行10000000,10000001,10000002, ...等等直到10000099
$wc -l english
36374448 english
$time for i in {0..99}; do j=$((i+10000000)); sed -n $j'{p;q}' english >/dev/null; done;
real 1m27.207s
user 1m20.712s
sys 0m6.284s
Run Code Online (Sandbox Code Playgroud)
与
$time for i in {0..99}; do j=$((i+10000000)); head -$j english | tail -1 >/dev/null; done;
real 1m3.796s
user 0m59.356s
sys 0m32.376s
Run Code Online (Sandbox Code Playgroud)
用于从多个文件中打印一行
$wc -l english*
36374448 english
17797377 english.1024MB
3461885 english.200MB
57633710 total
$time for i in english*; do sed -n '10000000{p;q}' $i >/dev/null; done;
real 0m2.059s
user 0m1.904s
sys 0m0.144s
$time for i in english*; do head -10000000 $i | tail -1 >/dev/null; done;
real 0m1.535s
user 0m1.420s
sys 0m0.788s
Run Code Online (Sandbox Code Playgroud)