应用程序启动速度的优化

Mac OS/Android在下面Static Initializer

Mozillaproject师通过优化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上的布局:


watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSG9ya3lDaGVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast"  />

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

FireFox的优化

在Mozillaproject师的文章[p=1296">链接]中,基于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: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSG9ya3lDaGVu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" /> 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-09-29 09:01:51

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

应用程序启动速度优化

Mac OS/Android下的Static Initializer Mozilla工程师通过优化Static Initializer(静态初始化,或全局建构函数, Global Constructor)和Binary布局来提升FireFox启动速度的文章,非常有参考价值.文章中以x86及x86-64平台为基础,下面加了Mac OS及Android上的binary布局. 什么是Static Initializer? 简而言之就是全局C++对象的初始化.有人笑称一个C++程序的main()函数执行

c++程序的效率优化初涉

能写出稳定高效的程序一直是程序员所追求的,今天就和大家一起探讨一下关于C++程序优化的几点看法. 由于C/C++语言的复杂性,致使C++编译器隐藏了层层幔布,我们不经意的一条语句都可能是编译器幕后几经周折的结果,在要求程序高效运行的环境下,每一条语句都会让我们慎之又慎,而程序优化又是个十分广泛的话题,包括程序架构设计的优化,语言本身的优化,编程技巧和策略等等,如此大的范围非我能力所及,这里谈的优化就是在实际开发中遇到的问题. 一.  举手之劳的小差别 既然说优化就一定要仔细,不放过任何微小的细节

java程序的内存优化

面试常被问java的垃圾回收机制,感觉平时写代码很少用到,但是注重程序的内存优化确实很重要.<EffectiveJava>这本书有几条讲的挺好,拿过来总结下吧. 首先简单的概括下java的内存回收机制. java内存主要是堆内存和栈内存,栈中的内存会在程序运行到所在作用域之外后进行回收.堆中的内存会在没有引用指向的时候,JVM虚拟机在某个时间段根据特定的算法进行回收. 平时写程序注意如下几点,对程序进行内存优化 1.避免创建不必要的对象 a.使用基本类型替代装箱类型(享元模式) b.Strin

从实际项目中的一个改进细节谈程序的易用性优化

说明:一下内容是笔者一个项目上真实的例子,这个系统是一个收费系统,需要打印发票 ,打印发票的时候需要将发票代码和发票号码打印在实际的发票上(税务上要求的).留存于此,希望对大家有启发. 从发票代码的改进谈程序的易用性优化 最近老有收费员领用发票的时候,输错发票代码,导致成百的发票打印作废.分析原因,最直接的原因有2: 1,收费员不仔细,没有仔细核对发票代码,领用录入时,和发票打印时. 2,可用的发票代码太相似:一个是 141001320043 ,一个是 141001420043,只有1位只差.收

java应用程序及服务器优化过程及loadrunner测试效果

我们目前的网站应用首页大小在130K左右,在之前的测试过程中,其百用户并发的平均响应能力在6.5秒,通过今天的性能优化大概提升两秒左右的时间,结果在5秒内,根据应用的技术及操作系统环境,已经达到最优了,但再次优化的可能性还是有的,详细信息如下: 一.操作系统: 机器名    CPU    内存    软件环境(操作系统/应用软件)    备注应用服务器    3.07GHz*2    8GB    Linux    1台应用服务器(虚拟机)测试机    2.50GHz    4GB    WIN

采用DTO和DAO对JDBC程序进行进一步优化

采用DTO和DAO对JDBC程序进行进一步优化 DTO:数据传输对象,主要用于远程调用等需要远程调用对象的地方DAO:数据访问对象,主要实现封装数据库的访问,通过它可以把数据库中的表转换成DTO类 引入DTO其实就是新建实体类. 那么DAO呢,就是封装访问数据的方法,比如对某一个表插入,更新,删除等方法可以放进对应的dao中 代码如下: 这是访问User表所使用方法的接口,里面放的是访问过程中会使用到时方法 public interface UserDao { public void save(

90程序锁的优化

在程序锁中,当打开一个软件的时候,会短暂的出现软件的界面,然后再出现输入密码的界面,对此需要坐下修改: 第一个地方: List<RunningTaskInfo> infos = am.getRunningTasks(1); 原来的是100,我们在此只需要得到一个最近运行的task就可以了. 第二个地方: 以前在查询的时候,查询的是数据库,这样比较慢,改之查询内存,修改dao方法: /** * 查询全部包名 */ public List<String> findAll(){ List

ECSHOP程序SEO完全优化

一.完全自定义页面titile,完全抛弃Ecshop定义的页面title格式:[产品名称]_[分类名]_[网店名称]-Powered by ECShop 1.分析:大家都知道,titile,kewords,description在SEO中的基础性和重要性,但是ECshop官方给出的titile实现方法会出现很多类似或相同的页面title,另外还有部分页面无法自定义kewords和 description.在此本人给出了完全自定义的方法,其实方法很简单的,只要稍微懂得一点点代码的都会. 2.修改包

程序员这样优化简历,一投制胜

本文转载于: (http://mp.weixin.qq.com/s?__biz=MzAxMzUzNzYyNA==&mid=402350606&idx=1&sn=c356b88f22d9277534aeee773f07d6ca&scene=23&srcid=02256Zn4PnYzdQ8M8WyTj5BG#rd&ADUIN=3024665621&ADSESSION=1456446961&ADTAG=CLIENT.QQ.5467_.0&A