从统计代码行数说开
时间:2010-06-29 来源:xiaosuo
xiaosuo@gentux FreeBSD $ svn up 版本 209583。 xiaosuo@gentux FreeBSD $ find . -name "*.[hc]" | xargs wc -l ... 836324 总用量 ... localhost linux # git pull Already up-to-date. localhost linux # find . -name "*.[hc]" | xargs wc -l 19537 total |
结果让我愕然,太假了吧,FreeBSD竟然比Linux代码量大,并且Linux才那么点儿代码?应该是统计方法有问题,换用perl语言实现一个统计程序如下:
#!/usr/bin/perl -w $line = 0;
open($files, 'find . -name "*.[hc]" |'); |
运行之:
xiaosuo@gentux FreeBSD $ ./line.pl 3956986 ... localhost linux # ./line.pl 11898857 |
长出一口气,终于得到了靠谱的数据,并且虚荣心得到些许满足,Linux代码行数是FreeBSD的3倍多。
那么,先前的统计为什么出错了呢?以前我可都是这么统计代码行数的。猜测是因为文件数量太多,xargs不能一次性将所有文件的路径以参数的形式传递给wc,致使wc被调用了多次。检测方法比较简单,在原有的命令基础上再加一个过滤器,筛选出总用量统计。
xiaosuo@gentux FreeBSD $ find . -name "*.[hc]" | xargs wc -l | grep 总用量 3120662 总用量 836324 总用量 |
和结论相符,那么修正一下shell脚本,让xargs每次传给wc一个参数,并用其他方式统计行数。
xiaosuo@gentux FreeBSD $ find . -name "*.[hc]" | xargs -L 1 wc -l | awk '{print $1}' | while read num; do total=$((total+num)); echo $total; done ... 3956986 |
这次得出了正确的数字,只是速度较慢,其实可以将统计方法应用于上一个过滤后的结果以加速执行。
那么xargs传递的参数个数的上限是多少呢?统计了一下每次wc调用的参数个数:
localhost linux # find . -name "*.[hc]" | xargs ./a.pl 4708 3460 3730 3998 4110 3544 4157 1798 |
并没有发现任何规律。看来还得翻源码:
/* IEEE Std 1003.1, 2003 specifies that the combined argument and |
可见有相关的sysconf变量,但是你查看其相应的man page字段,发现这个数值其实不怎么可靠。
ARG_MAX - _SC_ARG_MAX The maximum length of the arguments to the exec(3) family of functions. Must not be less than _POSIX_ARG_MAX (4096). |
BUGS It is difficult to use ARG_MAX because it is not specified how much of the argument space for exec(3) is consumed by the user's environment variables. Some returned values may be huge; they are not suitable for allocating memory. |
比较保险的做法还是尽量避免过多参数吧。