特修斯的动态链接库

简介:

特修斯的动态链接库

前言

最近几周动弹得越发少了,身材愈发有一桶天下的趋势,这让我很是困扰,毕竟像我这种身高的人,继续胖下去似乎最终的结果就是胖成球了,当然不是乒乓球。所以,一有时间,设备又齐全的话,我便会去公司的健身房跑跑步什么的。晚上九点的西溪园区,健身房的人还是很多,在漫无止境的等待机器中我产生了强烈的希望公司大规模裁员的意愿,不过考虑到我保不齐第一个就被干掉了,想想也就算了。久而久之,我听到了一个说法,只要你每天消耗的卡路里超过你吃下的卡路里,就可以减肥,很厉害的样子。特修斯之船?捣鼓哲学的人真是可怕。

然而我既不是什么文人墨客,也不是什么健身教练。我肯定不是来讲什么瘦身之道的。像我这种头脑简单,四肢简化的人,

 ___不客气的说,还是挺多的。___ 所以我到底要说些什么呢?身为一个不是怎么好的程序猿,我能分享得完美无缺的,也就大概或许是如何写个HelloWorld?
 

但是很幸运的是,我在淘宝,不需要打电话推销我的产品,也不需要偷别人的技术 所以我有时间做一些不一样的研究和实践。接下来的东西,错漏多多少少是会有的,希望各位看官不要嫌弃,有兴趣的可以帮忙指正,。

动态库包大小裁剪

一、多做之过

很可惜,我大概能猜到你们看到这里的心情。通过搜索找到这篇文章的,你们内心大概只有一个诉求,快tm告诉我怎么优化,加什么编译选项,我要立刻立即马上生效的那种。我能体会这种心情,所以如果你有强烈的需要,可以去第三章,那里或许有一些帮助。不过我仍希望你们可以看看前两章这些或许对你现在不是那么重要的东西,这也是我为什么把这俩章放在前面的原因。这些东西在我们的动态库缩减中远远比那些个编译选项做得更好。

就像前面所说,当我们要优化一个动态库的大小的时候,第一个想法是编译选项调优,这很直接,在大多数情况也很有效。但我不打算先说这个,我要说的是,在优化一个动态库大小之前,我们为什么不想想,我们是不是做得太多了。一个基于可靠协议的通信有必要做完整性校验么?一个简单通信sdk有必要接入aio,select,epoll等这些所有的IO机制么。一个钱包有必要做社

在你暗自不爽之前,可以先去看看自己的代码。是不是真的完美无缺而又恰到好处。我相信各位的能力,但我对各位的时间表示怀疑。我这半年到目前来一直接手的,是一个历经多位大佬精心打造的项目,从接手的那一刻起,似乎就注定了只需添砖加瓦,不必翻新重修。但是很可惜,它也有做得过多的,食之无味,弃之完全不可惜,但就是甩不掉的东西。在添加一个新的模块时,为了保证这些东西,我又不得不新增一些同样的东西,依次循环。

所以,趁着这些多做的事情还没有彻底病变之前就干掉它。我不需要强调良好的设计的重要性,因为当一个糟糕的设计摊到你身上时,你就可以清清楚楚的了解这一切了。至于那些已经乱七八糟的东西,我只有2个建议,一是长痛不如短痛,二是节哀。

二、逃出克隆岛

现在似乎已经很少有那种拷贝粘贴的程序员了。但我们在开发中,可能经常会引进其他的开源库。往往开源库中的某些功能跟我们的功能存在重叠。机智的人早已找到了另一个办法 : 换一个不重叠的开源库.

一般来说,一个设计良好的开源库一般是具备一定的拆卸能力的。引进开源库不是简单的git clone,花点时间看看文档,看看代码,这肯定是有效的。

三、编译优化及其他

__Os选项__. 为什么我们不能承认这就是一个很好的优化方式呢。人尽皆知但效果显著。我拿出来讲一遍都似乎有凑字数的嫌疑。但很不幸的是,这个选项有效但不一定是安全的,有兴趣的同学可以参考我的上一篇文章《谁动了我的GCC优化》。

__strip__. ,又是一个人尽皆知的手段。我也根本没有打算对这个展开什么。只有一点很不爽国内的技术论坛,一提到动态库大小问题,次次搬出这个。其次我只是在凑字数

-fvisibility=hidden__. 终于有一个可能普及程度不那么高的,但是稍微有点经验的程序员都可能知道的。在linux中源文件中的所有函数都有一个默认的visibility属性为public,这些符号都会导入到符号表。而这个选项会隐藏所有的符号,只有手动指定的符号才会被导出到符号表 (__attribute ((visibility("default")))),通过减少了表项来使得包大小缩减。有兴趣的同学可以参看《C专家编程》一书。

__删除没用到的函数和数据__。也就是在编译选项加上 -ffunction-sections -fdata-sections ,在链接选项上加上 -Wl,--gc-sections。这个最开始我是完全无法理解的,我大概是被《C专家编程》这本书骗了,这本书提到过,静态链接时只会链接那些需要的函数,但是事实证明并不是这样。在默认的静态链接中,默认的单元是一个.o文件,在没有任何声明的情况下,这个文件的所有数据和函数都会被链接到最后文件中。(有兴趣的同学可以试试看,在linux下可以用 readelf --syms 看最终符号表)。使用上述选项后,将链接单元缩小到函数/数据 ,这样最终链接时才能真正去除那些没有用到的函数和数据。至于那些信心满满的认为自己的代码不会有用不到的函数/数据的同学,你难道没用过别人的静态库么。

__引入静态库还是动态库__。我相信没有人会在自己的最终库之外再提供其依赖的动态库文件,更多的,在有源码的前提下,可以在链接三方库的静态库到最终的属于我们自己的库上。前者不仅不方便维护,而且势必在第三方动态库中存在我们不需要的符号。但后者真的有听起来那么完美么。如果大量的SDK提供方都使用了一个库,此时,动态链接似乎是个更好的方式。所以,需要自己考量。于我而言,当然是选择原谅它

-Wl,--icf=safe 这个选项会把完全相同的代码折叠,还是可以减少一些大小的。

换个编译器 。 这不是开玩笑,在android nkd开发中,我们用clang3.6编译出动态库大小比 用gcc4.9 大了60K左右,不过gcc4.9也存在一些问题的,详情参考《谁动了我的GCC优化》。当然clang也是有优点的,比如编译速度快。对的,编译速度快以及其他。

-flto GCC特有的优化手段。一个编译选项,但是工作在链接时。在4.9及以上似乎是自动完成的,但不知道为何ndk中 gcc4.9没有这样做。具体原理才疏学浅,正在学习中。需要注意的是,一定要gcc去完成链接。如果用到了c++,在链接时势必是g++链接的,这会导致很严重的问题。解决方法是,只对c文件使用-flto选项。

__限制内连代码__。代码的多次内连会导致代码区的体积增大。这本质是一个时空互换的问题,你是需要用强大的性能还是需要精简的体积,你可能无法选择,但你可以权衡。-finline-limit=n,自己选择n值吧。

__其他的一些代码小技巧__,比如用 exit(0) 取代 return,不要使用C++中的异常处理和RTTI,在安卓开发中,不要使用iostream,使用安卓自带的log库,等等。

压缩 这的确看起很有效,但实实在在地是在自欺欺人,请不要继续这样骗自己了。

四、认清事实

再怎么缩减也要按照基本法。很抱歉你天生就是这么胖

目录
相关文章
|
6月前
|
存储 Linux 编译器
什么是链接库 | 动态库与静态库
什么是链接库 | 动态库与静态库
80 0
|
Shell 开发工具 iOS开发
动态库下(5)
动态库下(5)
314 0
动态库下(5)
|
编译器 C语言 C++
【转】Lib静态链接库和Dll动态链接库
【转】Lib静态链接库和Dll动态链接库
126 0
|
开发工具 iOS开发
动态库(4)
动态库(4)
220 0
|
编译器 C++ 开发者
头文件.h、动态链接库.dll、静态链接库.lib的区别与应用总结
头文件.h、动态链接库.dll、静态链接库.lib的区别与应用总结
810 0
头文件.h、动态链接库.dll、静态链接库.lib的区别与应用总结
|
安全 API 网络安全
|
C语言 Linux
采用dlopen、dlsym、dlclose加载动态链接库【转】
转自:http://www.cnblogs.com/Anker/p/3746802.html 1、前言   为了使程序方便扩展,具备通用性,可以采用插件形式。采用异步事件驱动模型,保证主程序逻辑不变,将各个业务已动态链接库的形式加载进来,这就是所谓的插件。
1022 0
|
C语言 编译器 vr&ar
GCC 编译使用动态链接库和静态链接库
1 库的分类 根据链接时期的不同,库又有静态库和动态库之分。 静态库是在链接阶段被链接的(好像是废话,但事实就是这样),所以生成的可执行文件就不受库的影响了,即使库被删除了,程序依然可以成功运行。 有别于静态库,动态库的链接是在程序执行的时候被链接的。
1269 0

热门文章

最新文章