这篇文章是读过善用佳软的“超级小巧的5款免费款树状笔记软件”后,关于软件运行文件大小的一些感想。
在其他条件都相同的理想情况下,当然同样尺寸的软件,实现功能越多越好,这是没有疑问的。
不过……
首先,其他条件都相同这个情况,本身就非常不容易满足;
其次,即使满足了其他条件都相同 ,如何衡量和比较不同软件的实现功能呢?如果两个软件的运行文件大小一样,A 软件实现了 10 个功能,完成每个功能各需要 1 分钟,B 软件实现了 8 个功能,完成每个功能各需要 30 秒,虽然 A 软件的实现功能比 B 软件多,但用户对 A 软件的评价是否一定比 B 软件高呢?
我们现在来看看,软件运行文件的大小都受什么因素影响。
1、编译器优化方面的因素
以 C 为例, 编译器提供了 inline function(或者用 #define 的变种),就是牺牲文件运行代码的尺寸来换取运行速度的提高(这在需要实时快速反应的软件来说尤其重要),使用了 inline function 的运行文件,尺寸比较大;
现代的高级语言编译器,都有各种优化选项,供程序员选择,比如 gcc 中的 -O 选项就相当复杂,可参看 info gcc 中的 Optimize Options 一节,-O 默认的优化目标是产生的代码小,运行效率高,但实际情况中,这两方面往往是互相矛盾的。由于优化技术已经很成熟,用高级语言编程的代码,经编译器优化后,不同程序员之间的差别越来越小,所以高手间代码本身尺寸大小的对决,往往是汇编这一层次的较量,在高级语言层次,除非实现方法完全不同,否则很难从文件尺寸上分出高下。
2、 软件运行环境的因素
同样一个 hello world 的实现,如果用 perl 来写,一行字符的脚本就能搞定,而用 C 写一个简单的程序编译成可执行代码则要2KB多,表面上看来,用 perl 写出来的代码小,但是 perl 脚本需要有 perl 解释环境才能运行,如果把 perl 解释环境都加入考虑的范畴,那么 perl 脚本的尺寸要比 C 编译出来的可执行代码要大很多了。
类似的软件环境还有 .NET, JRE, python, PHP…… 等等。脱离了软件运行环境,只比较运行软件文件的大小,得出的结果意义并不大。
3、 动态库的因素
现在一般用户接触到的软件,已经很少能找到不加载动态库的了,用 Microsoft Visual C++ 写 Windows GUI 界面软件,最常见的就是使用 MFC,如果选择动态连接的话,生成的可执行代码会很小,但运行过程中系统必须加载相应版本的 MFC dll。如果只比较可执行代码,而不是同时也使用 depends (Windows) 或者 ldd (Linux) 来考虑它们需要加载的动态库的话,就有失偏颇了。
有时为了满足特定系统的需求或者运行稳定性要求,程序员也会编译出静态连接的可执行代码,比如
. 系统不支持动态库,如 DOS
. 某些低层软件可能在动态库系统还未建立时就需要运行,如用不含 initrd 的嵌入式 Linux 小系统中的 busybox/init,在它开始执行时包含动态库文件系统可能还未加载
. 为避免不同版本动态库的冲突而故意编译成静态连接软件,这种软件不依赖系统中的动态库,可以不考虑不同版本之间的兼容性,有时能大大节省技术支持部门的开销。
4、跟程序员有关的附加信息
这一部分也许和一般用户关系不大,但有时它也是影响软件可执行文件大小的因素
. Debug 版本,这类软件含有调试信息,在软件出现问题时对程序员非常宝贵,尤其是在这个 beta 满天飞的时代
. paranoid 型容错编程风格,假如两个程序员写出的程序是这样的:
程序员 A 的:
function foo()
{
try {
job1();
job2();
job3();
} catch exception(e)
{ exception_handler(e);}
}
程序员 B 的:
function foo()
{
job1();
job2();
job3();
}
程序员 B 的版本一定会比程序员 A 的版本小,但是说实话,我宁可要尺寸较大的程序员 A 的版本。
5 Comments
我不懂编程,所以,很感激你的补充。已经把链接收入原文了。
我也不懂编程。
程序员A好像是多写了一个捕获异常。
呵呵 学习
程序员A的捕获异常是很必要的,在异常被捕获后,可以进一步处理,比如提示用户出了什么问题(例如用户输入的什么参数不正确),交给用户去处理,而B的程序一旦出错,可能就是程序崩溃,用户根本没机会知道问题是什么。
不晓得
Post a Comment