`
jim443
  • 浏览: 7822 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

加速Linux程序编译

阅读更多

节选自http://www.freemindworld.com/blog/index.shtml

 

项目越来越大,每次需要重新编译整个项目都是一件很浪费时间的事情。Research了一下,找到以下可以帮助提高速度的方法,总结一下。

  1. tmpfs

  有人说在Windows下用了RAMDisk把一个项目编译时间从4.5小时减少到了5分钟,也许这个数字是有点夸张了,不过粗想想,把文件放到内存上做编译应该是比在磁盘上快多了吧,尤其如果编译器需要生成很多临时文件的话。

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

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

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

  用物理磁盘:40分16秒
  用tmpfs:39分56秒

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

  1. 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不规范,没有正确的设置好依赖关系,并行编译的结果就是编译不能正常进行。如果依赖关系设置过于保守,则可能本身编译的可并行度就下降了,也不能取得最佳的效果。

  1. 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的使用和命中情况:

cache directory                     /home/lifanxi/.ccache
cache hit                           7165
cache miss                         14283
called for link                       71
not a C/C++ file                     120
no input file                       3045
files in cache                     28566
cache size                          81.7 Mbytes
max cache size                     976.6 Mbytes

  可以看到,显然只有第二编次译时cache命中了,cache miss是第一次和第三次编译带来的。两次cache占用了81.7M的磁盘,还是完全可以接受的。

  1. distcc

  一台机器的能力有限,可以联合多台电脑一起来编译。这在公司的日常开发中也是可行的,因为可能每个开发人员都有自己的开发编译环境,它们的编译器版本一般是一致的,公司的网络也通常具有较好的性能。这时就是distcc大显身手的时候了。

  使用distcc,并不像想象中那样要求每台电脑都具有完全一致的环境,它只要求源代码可以用make -j并行编译,并且参与分布式编译的电脑系统中具有相同的编译器。因为它的原理只是把预处理好的源文件分发到多台计算机上,预处理、编译后的目标文件的链接和其它除编译以外的工作仍然是在发起编译的主控电脑上完成,所以只要求发起编译的那台机器具备一套完整的编译环境就可以了。

  distcc安装后,可以启动一下它的服务:  

/usr/bin/distccd  --daemon --allow 10.64.0.0/16

  默认的3632端口允许来自同一个网络的distcc连接。

  然后设置一下DISTCC_HOSTS环境变量,设置可以参与编译的机器列表。通常localhost也参与编译,但如果可以参与编译的机器很多,则可以把localhost从这个列表中去掉,这样本机就完全只是进行预处理、分发和链接了,编译都在别的机器上完成。因为机器很多时,localhost的处理负担很重,所以它就不再“兼职”编译了。  

export DISTCC_HOSTS="localhost 10.64.25.1 10.64.25.2 10.64.25.3"

  然后与ccache类似把g++,gcc等常用的命令链接到/usr/bin/distcc上就可以了。

  在make的时候,也必须用-j参数,一般是参数可以用所有参用编译的计算机CPU内核总数的两倍做为并行的任务数。

  同样测试一下:

  一台双核计算机,make -j4:23分16秒
  两台双核计算机,make -j4:16分40秒
  两台双核计算机,make -j8:15分49秒

  跟最开始用一台双核时的23分钟相比,还是快了不少的。如果有更多的计算机加入,也可以得到更好的效果。

  在编译过程中可以用distccmon-text来查看编译任务的分配情况。distcc也可以与ccache同时使用,通过设置一个环境变量就可以做到,非常方便。

  总结一下:

  tmpfs: 解决IO瓶颈,充分利用本机内存资源
  make -j: 充分利用本机计算资源
  distcc: 利用多台计算机资源
  ccache: 减少重复编译相同代码的时间

  这些工具的好处都在于布署的成本相对较低,综合利用这些工具,就可以轻轻松松的节省相当可观的时间。上面介绍的都是这些工具最基本的用法,更多的用法可以参考它们各自的man page。 <script type="text/javascript"></script>

分享到:
评论

相关推荐

    Linux下编译安装SDL2.0

    在Linux环境下,构建和安装SDL2.0是一个...总结来说,Linux环境下编译安装SDL2.0涉及到下载所需依赖,解压、配置、编译和安装这些包。完成这些步骤后,开发者就能利用SDL2.0的强大功能在Linux上开发丰富的图形应用了。

    Prelink--一种Linux下加速程序启动的技术研究.pdf

    Prelink是一种针对Linux系统的优化技术,旨在加速程序启动和系统加载。它的工作原理主要涉及到以下几个核心方面: 1. **缓存符号解析结果**:在程序运行之前,Prelink预先进行符号解析,将程序中未定义的函数名转换...

    linux内核编译详解

    ### Linux内核编译详解:核心知识概览 #### 一、内核的重要性与特性 内核作为操作系统的心脏,负责管理系统的关键资源,包括进程、内存、设备驱动、文件和网络系统,直接决定了系统的整体性能和稳定性。Linux的...

    Vulkan CPU加速器,包含Windows和Linux版本

    总的来说,Vulkan CPU加速器提供的SDK为开发者提供了在Windows和Linux上利用Vulkan的强大能力,实现高效、跨平台的图形和计算应用。通过深入学习和实践这些知识点,开发者可以构建出性能卓越的游戏、可视化应用和...

    armv5tej-linux交叉编译环境

    总之,armv5tej-linux交叉编译环境是为ARMv5TEJ架构设备开发软件的关键,它允许开发者在个人电脑上构建适用于嵌入式系统的应用程序,极大地提高了效率和便利性。通过理解并熟练掌握交叉编译工具链的使用,开发者能够...

    Linux下安装OpenCV CUDA加速1

    总结一下,本文详细介绍了在Linux下安装OpenCV并开启CUDA加速的步骤,包括安装依赖、获取源代码、配置编译选项、编译安装以及更新环境变量。通过遵循这些步骤,你可以充分利用NVIDIA GPU来提升OpenCV应用的执行效率...

    libjpeg-turbo 交叉编译aarch64 6.5.0 jpeg图像加速库

    《libjpeg-turbo 6.5.0:在aarch64平台上实现JPEG图像加速库的交叉编译详解》 libjpeg-turbo是一个开源的、高效的JPEG图像处理库,它利用SIMD(单指令多数据)指令来提高JPEG编码和解码的速度。6.5.0版本作为其一...

    在linux环境下安装vtk

    make -j4 # 使用4个线程加速编译,根据硬件情况调整 sudo make install ``` 4. **配置环境变量**: - 安装完成后,需要将VTK的库路径添加到`LD_LIBRARY_PATH`环境变量中,可以在`~/.bashrc`或`~/.bash_profile`...

    ninja加速编译应用程序

    标题中的“ninja加速编译应用程序”指的是利用Ninja来提升应用程序的编译效率。在Windows平台上,通常我们会使用名为`ninja-win`的版本,即`ninja.exe`,这是一个专为Windows环境设计的可执行文件。 ### Ninja的...

    Alias2.4 for linux 程序库

    Alias2.4 for Linux程序库的使用,不仅可以加速数值计算密集型的应用开发,还可以为开发者提供一个稳定且经过优化的计算平台,尤其适用于科学模拟、数据分析、机器学习等领域。因此,对于那些需要进行复杂数学运算的...

    arm-vfp-linux-gnu-4.3.2交叉编译工具链及安装

    `arm-vfp-linux-gnu-4.3.2`工具链集成了这个特性,确保了编译出的代码能够充分利用VFP硬件加速。 交叉编译工具链通常包括了编译器(如gcc)、链接器、汇编器、调试器等组件,本例中的`arm-vfp-gnu-gcc-4.3.2`是其中...

    Linux硬件驱动和应用程序

    最后,通过Makefile或者CMake等工具将驱动程序编译为内核模块,或者集成到内核源码中进行编译,确保驱动能在ZedBoard的Linux系统中正常工作。 应用程序的开发则涉及标准C/C++库的使用,以及对硬件驱动的调用。例如...

    海思 qt 移植 linuxfb 修改

    在本文中,我们将深入探讨如何在海思3519A平台上进行QT应用程序的移植,并重点关注涉及Linux帧缓冲(LinuxFB)的修改过程。QT是一个跨平台的应用程序开发框架,广泛用于创建图形用户界面,而LinuxFB是Linux系统中...

    海思SS928 aarch64-mix210-linux编译链

    在开发针对这种处理器的应用时,选择正确的编译链至关重要,因为它直接影响到程序的性能、兼容性和效率。 aarch64是ARM的64位指令集架构,也称为AArch64,是现代ARM处理器的基石。与32位架构相比,aarch64提供了更...

    FpcupDeluxe国内加速预编译版

    开源FPC和Lazarus实一个极好的跨平台开发工具,具有一次编写处处编译的优势,...为此,我修改了部分源码,加入了镜像加速功能,预编译了win和linux下64和32位的应用程序,帮助大家有效建立fpc和lazarus跨平台开发环境。

    嵌入式 Linux NFS方式下应用程序的实现 .pdf

    服务器作为核心,承担着内核编译、应用程序编译的任务,需配备标准的Linux操作系统,如Redhat Linux。工作站则通常运行Windows系统,用于日常操作和必要时与服务器及开发板交互。嵌入式开发板系统直接承载应用程序的...

    英特尔 i350 网卡驱动 Linux源码

    【标题】"英特尔 i350 网卡驱动 Linux源码" 描述了这个压缩包文件的内容,它是针对英特尔的i350网卡在Linux操作系统下的驱动程序的源代码。这个驱动程序是为了使Linux系统能够识别并充分利用英特尔i350网络接口控制...

    windows linux 交叉编译器

    linux-gnueabihf"是交叉编译目标体系结构的标识符,其中"arm"表示目标是ARM处理器,"linux"表示目标操作系统是Linux,"gnueabihf"则表示是针对“GNU EABI with Hard Float”,意味着该编译器支持浮点运算硬件加速。...

Global site tag (gtag.js) - Google Analytics