应用程序启动速度优化

Mac OS/Android下的Static Initializer

Mozilla工程师通过优化Static Initializer(静态初始化,或全局建构函数, Global Constructor)和Binary布局来提升FireFox启动速度的文章,非常有参考价值。文章中以x86及x86-64平台为基础,下面加了Mac OS及Android上的binary布局。

什么是Static Initializer? 简而言之就是全局C++对象的初始化。有人笑称一个C++程序的main()函数执行之前,可能该做事都做完了,这就是Static Initializer的影响。如果里面又有一层层依赖引用,就会大大影响启动时间。下面是一个示例程序:

MyClass oneClass(0x010203);
const MyClass twoClass(0x010204);

attribute ((constructor)) void foo(void)
{
    printf(“foo is running and printf is available at this point\n”);
}

int main(int argc, const char * argv[])
{
  //do something here…
}
前两个对象oneClass和twoClass即是使用了静态初始化的两个对象, 而foo函数则通过编译选项强制放到程序的初始化段(init segement)中,在程序初始化时就会执行。以下即最终在Mac OS上的布局:


在Android ARM ELF中则是下面这个布局:

FireFox的优化

在Mozilla工程师的文章[链接]中,基于Firefox 4.0b8在x86及x86-64的测试数据发现如下的平均启动时间:
平均启动时间(ms) Pages Read Bytes Read
x86 3,228.76 ± 0.57% 4,787 19,607,552
x86-64 3,382.0 ± 0.51% 5,874 24,059,904
使用systemtap[链接]可以得到一个访问核心库libxul.so的access pattern:
  1. 红点表示从磁盘加载的页数
  2. 红线则是在文件中的定位(seek)操作
  3. 背景中的色块代表了.rel.dyn/.rela.syn(红色),.text(粉色),.rodata(绿色),.data.rel.ro(淡绿色)。

Static Initializers

在开始时那些垂直的线段正是Static Initializers运行的时间,占去了不少的时间。解决之道就是减少static initializers,特别留心那些全局变量、静态变量。 以这种方法分析了一下,一共有237个static initializers,其中147是由cycle collection globals所引入的。经过修正后cycle collection的全局对象降到一个,整个情况并未有大的改观:
平均启动时间(ms) Pages Read Bytes Read
x86 3,216.1 ± 0.59% 4,656 19,070,976
x86-64 3,488.14 ± 0.75% 5,759 23,588,864
以下是新的I/O access pattern: I/O虽然有所降低,其实还有许多其它内容的读操作在static initialization前已经发生了,所以还有别的工作需要做。

Reordering objects

另一工作即是重新布局binary, 让内核需要的数据可以尽快获取。之前Taras的一个研究发现只要做些toolchain上的变更就可以实现。 使用Taras的icegrind做了优化后,改进变得明显了:
平均启动时间(ms) Pages Read Bytes Read
x86 2,939.18 ± 0.81% 4,129 16,912,384
x86-64 3,247.64 ± 0.68% 5,254 21,520,384
I/O pattern:

Packing Relocations

最后,再可以通过减少relocation段,来优化启动时间。这样可以有效降低I/O,以及dynamic relocations section,也能减小程序包。我使用的工具在这里。 参考:关于通过调整ELF优化启动时间 下面是最终的效果:
平均启动时间(ms) Pages Read Bytes Read
x86 3,149.32 ± 0.62% 4,443 18,198,528
x86-64 3,191.58 ± 0.62% 4,733 19,386,368
I/O Pattern如下: 这是一个晦涩的主题,非党值得深入研究,可以从作者提供的链接入手展开。我水平有限,抛砖引玉,期待着更为深入的阐述。 转载请注明出处: http://blog.csdn.net/horkychen

参考

1. How to Make Startup Suck Less (Also Reduce Memory Usage!) 2. Death by static initialization 3. icegrind - Valgrind Plugin for optimizing Cold Startup 4. Resolving ELF Relocation Name / Symbols 5. Static initializers 6. ELF for ARM Architecture

应用程序启动速度优化

时间: 2024-08-11 09:56:34

应用程序启动速度优化的相关文章

Android内核开发:系统启动速度优化

在学习新知识的过程中,我一直很推荐结合实战任务去学习,只有经历实战,才能加深对理论知识的理解.<Android内核开发>系列已经写了八篇了,本文就结合前面的内容,给大家布置一个实战任务: 优化Android系统的启动速度. 这里我简单介绍一下优化的基本思路和涉及的文件,具体细节由大家自己在实践去摸索,提高自己Google能力和解决问题的能力. Android系统的启动优化主要分为三大部分: (1) Bootloader优化 (2) Linux Kernel的剪裁与优化 (3) Android

Java程序性能优化——设计优化

原文出自:http://blog.csdn.net/anxpp/article/details/51914119,转载请注明出处,谢谢! 1.前言 OK,之前写了一篇文章:"23种设计模式介绍以及在Java中的应用"详细介绍了如何将设计模式应用到Java编程中,而本文旨在介绍如何利用他们优化我们的程序,使其性能更佳. 设计模式的详细介绍请参照上面链接中的文章,不是本文的重点. 而Java程序的性能优化,不一定就仅仅是以提高系统性能为目的的,还可能是以用户体验.系统可维护性等为目的. 2

爱奇艺技术分享:爱奇艺Android客户端启动速度优化实践总结

本文由爱奇艺技术团队原创分享,原题<爱奇艺Android客户端启动优化与分析>. 1.引言 互联网领域里有个八秒定律,如果网页打开时间超过8秒,便会有超过70%的用户放弃等待,对Android APP而言,要求更加严格,如果系统无响应时间超过5秒,便会出现ANR,APP可能会被强制关闭,因此,启动时间作为一个重要的性能指标,关系着用户的第一体验. 爱奇艺安卓APP非常重视启动速度的优化,本文将从启动过程.启动时间测量.启动优化.以及后续监控等方面分享我们在启动优化方面积累的经验. 相关文章:

C++应用程序性能优化(一)——应用程序性能优化简介

C++应用程序性能优化(一)--应用程序性能优化简介 一.程序性能优化简介 1.程序性能优化简介 在计算机发展的早期阶段,硬件资源相对而言是非常昂贵的,CPU运行时间与内存容量给程序开发人员设置了极大限制.因此,早期的程序对运行性能和内存空间占用的要求是非常严格的,很多开发人员为了减少1%的CPU运行时间,为减少几十个甚至几个字节而不懈努力.随着计算机技术的快速发展,硬件资源变得相对便宜.但如果认为软件开发时,程序的性能优化不再重要,硬件将解决性能问题也是片面的.计算机硬件的发展解决了部分软件的

以C语言为例的程序性能优化 --《深入理解计算机系统》第五章读书笔记

其实大多数的编译器本身就能提供一些简单的优化,比如gcc就能通过使用 -O2 或者 -O3 的选项来优化程序.但编译器的优化始终也是有限,因为它必须小心翼翼保证优化过程不对程序的功能有改动.故而程序员本身应该对程序有优化意识.在我看来,这也是应该有的一种良好的编程习惯. 几种比较简单的优化措施: 1.代码移动 将要执行多次(比如在循环中)但计算结果不会改变的计算,移动到代码前面不会多次求值的部分.举一个比较极端的例子: /* convert string to lowercase: slow*/

Java程序性能优化——性能调优层次

为了提升系统性能,开发人员可以从系统的各个角度和层次对系统进行优化.除了最常见的代码优化外,在软件架构上.JVM虚拟机层.数据库以及操作系统层都可以通过各种手段进行调优,从而在整体上提升系统的性能. 设计调优 设计调优处于所有调优手段的上层,它往往需要在软件开发之前进行.在软件开发之初,软件架构师就应该评估系统可能存在的各种潜在的问题,并给出合理的设计方案.由于软件设计和架构对软件整体有决定性的影响,所以,设计调优对系统性能的影响也是最大的.如果说,代码优化.JVM优化都是对系统微观层面上"量&

程序的优化(PHP)

有些小细节往往容易被人忽视.有时候常常说优化代码优化代码,但是实际操作的时候,最容易被忽视的如下所示: echo 比 print 快. 使用echo的多重参数代替字符串连接. 在执行for循环之前确定最大循环数,不要每循环一次都计算最大值,最好运用foreach代替. 对global变量,应该用完就unset()掉. 用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会. 函数代替正则表达式完成相同功能. 当执行变量$i的递增或递减时,$i+

程序性能优化之SQL篇

如果说功能是程序的躯体,那么性能就是程序的灵魂.完整的功能可以保证程序的躯体是健全的,而良好的性能才是程序灵魂的象征,本文就程序的性能优化做简单的介绍. 最近对程序的性能的体会尤为深刻.最近做了一个数据查询和显示的功能,从7张表大概1500条数据中查询25条数据并且显示出来,时间消耗1秒钟.我的计算机参数为:CPU:i5处理器,4G内存.这个执行速度相当的慢,好在我查询的数据量比较小,等待时间不是很多,但是程序性能优化确实刻不容缓. 仔细分析了程序,发现有很多地方都是需要修改的,我们先从数据库开

Java程序性能优化技巧

多线程.集合.网络编程.内存优化.缓冲..spring.设计模式.软件工程.编程思想 1.生成对象时,合理分配空间和大小new ArrayList(100); 2.优化for循环Vector vect = new Vector(1000);for( inti=0; i<vect.size(); i++){ ...}for循环部分改写成:int size = vect.size();for( int i=0; i>size; i++){ ...} 如果size=1000,就可以减少1000次si