闲得蛋疼,想去统计一下FreeBSD和Linux内核代码行数,好“羞辱”一下FreeBSD,并籍此慰藉一下自己作为Linux用户的虚荣之心(就是鲁迅笔下的阿Q精神):
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]" |');
while (<$files>) {
open($fp, $_);
while (<$fp>) {
$line++;
}
}
print $line . "\n";
|
运行之:
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
* environment list shall not exceed {ARG_MAX}-2048 bytes. It also
* specifies that it shall be at least LINE_MAX.
*/
#ifdef _SC_ARG_MAX
long val = sysconf(_SC_ARG_MAX);
if (val > 0)
{
/* Note that val can in fact be greater than ARG_MAX
* and bc_ctl.arg_max can also be greater than ARG_MAX.
*/
assert (bc_ctl.arg_max <= (val-XARGS_POSIX_HEADROOM));
}
else
{
# if defined ARG_MAX
assert (bc_ctl.arg_max <= (ARG_MAX-XARGS_POSIX_HEADROOM));
# endif
}
#else
/* No _SC_ARG_MAX */
assert (bc_ctl.arg_max <= (ARG_MAX-XARGS_POSIX_HEADROOM));
#endif
|
可见有相关的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. |
比较保险的做法还是尽量避免过多参数吧。
阅读(7938) | 评论(1) | 转发(0) |