Linux编译技巧

编译技巧

从mount引发的血案

背景故事

项目越来越大,每次需要重新编译整个项目都是一件很浪费时间的事情。

tmpfs

tmpfs在类Unix操作系统上是一个常见的名称会用来做为暂时的档案储存方式,在更多的情况下,它会用虚拟的内存而不是一个永久保存的媒体来做为在档案系统上的使用。tmpfs可以使用您的内存或swap分区来存储文件。

tmpfs是基于Linux的虚拟内存管理子系统,面向普通用户的,根据用户需要随时可以创建此类型目录,以方便快捷地获得飞一样的读写速度。

当用户创建了此类型的目录后,剩下的工作就交给MMU来完成,不论是最终是在物理内存中还是在SWAP中,都尽可能地满足用户的需求。

这就是我们之前提到过的 虚拟硬盘

把文件放到内存上做编译,尤其如果编译器需要生成很多临时文件的话,比在磁盘上快多了。

在Linux中,直接mount一个tmpfs就可以了。而且对所编译的工程没有任何要求,也不用改动编译环境。

刚好我们复习一下之前学习到的一些mount的命令:

①. mount -t tmpfs tmpfs ~/build -o size=1G

  • -t 对应的是类型

  • -o 对应的是选项

②. df -lh

  • -l 只显示本地文件

  • -h 可读

用df就能看出有tmpfs的挂载点:

用来检查linux服务器的文件系统的磁盘空间占用情况。


用2.6.32.2的Linux Kernel来测试一下编译速度:

  • 用物理磁盘:40分16秒

  • 用tmpfs:39分56秒

呃……没什么变化。看来编译慢很大程度上瓶颈并不在IO上面。但对于一个实际项目来说,编译过程中可能还会有打包等IO密集的操作,所以只要可能,用tmpfs是有益无害的。当然对于大项目来说,你需要有足够的内存才能负担得起这个tmpfs的开销。

make -j

既然IO不是瓶颈,那CPU就应该是一个影响编译速度的重要因素了。

用make -j带一个参数,可以把项目在进行并行编译,比如在一台双核的机器上,完全可以用make -j4,让make最多允许4个编译命令同时执行,这样可以更有效的利用CPU资源。

还是用Kernel来测试:

  • 用make: 40分16秒

  • 用make -j4:23分16秒

  • 用make -j8:22分59秒

由此看来,在多核 CPU 上,适当的进行并行编译还是可以明显提高编译速度的。但并行的任务不宜太多,一般是以 CPU 的核心数目的两倍为宜。

不过这个方案不是完全没有 cost 的,如果项目的 Makefile 不规范,没有正确的设置好依赖关系,并行编译的结果就是编译不能正常进行。如果依赖关系设置过于保守,则可能本身编译的可并行度就下降了,也不能取得最佳的效果。

ccache

ccache用于把编译的中间结果进行缓存,以便在再次编译的时候可以节省时间。这对于玩Kernel来说实在是再好不过了,因为经常需要修改一些Kernel的代码,然后再重新编译,而这两次编译大部分东西可能都没有发生变化。对于平时开发项目来说,也是一样。为什么不是直接用make所支持的增量编译呢?还是因为现实中,因为Makefile的不规范,很可能这种“聪明”的方案根本不能正常工作,只有每次make clean再make才行。

安装完ccache后,可以在/usr/local/bin下建立gcc,g++,c++,cc的symbolic link,链到/usr/bin/ccache上。总之确认系统在调用gcc等命令时会调用到ccache就可以了(通常情况下/usr/local /bin会在PATH中排在/usr/bin前面)。

继续测试:

  • 用ccache的第一次编译(make -j4):23分38秒

  • 用ccache的第二次编译(make -j4):8分48秒

  • 用ccache的第三次编译(修改若干配置,make -j4):23分48秒

看来修改配置(我改了CPU类型…)对ccache的影响是很大的,因为基本头文件发生变化后,就导致所有缓存数据都无效了,必须重头来做。但如果只是修改一些.c文件的代码,ccache的效果还是相当明显的。而且使用ccache对项目没有特别的依赖,布署成本很低,这在日常工作中很实用。

可以用ccache -s来查看cache的使用和命中情况:

1
2
3
4
5
6
7
8
9
cache directory /home/kingand67/.ccache
primary config /home/kingand67/.ccache/ccache.conf
secondary config (readonly) /etc/ccache.conf
cache hit (direct) 0
cache hit (preprocessed) 0
cache miss 0
files in cache 0
cache size 0.0 kB
max cache size 5.0 GB

参考

提高编译速度