客户端冷启动优化实践_第1页
客户端冷启动优化实践_第2页
客户端冷启动优化实践_第3页
客户端冷启动优化实践_第4页
客户端冷启动优化实践_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、客户端做到一定程度,都会做启动优化,启动优化主要有如下方式1、 dll基址固定2、 dll延迟加载3、 dll文件预读4、 程序二进制文件连续分布5、 二进制文件relink6、 启动逻辑优化调整客户端性启动性能优化比起服务器要简单,服务器动不动就搞缓存、分布式、算法调优、客户端启动优化说来说去,核心思想不过下几点1、 减少文件io2、 减少pagefault3、 减少磁盘跨磁道操作4、 启动逻辑前移,先显示ui,后加载逻辑涉及到的工具1、 processmonitor查看启动的时候fileio2、 xpref分析启动的时候性能,消耗时间的部分在哪块3、 wcontig查看文件碎片的小工具4、

2、 sawbuck,这是google提供的一系列二进制重组工具。用了这些方法和工具后,完全可以忽略掉微软的prefetcher,这个工具1不开源,其次资料非常少,能起到的作用也有限,微软只会用闭源这一招,但是比他强大的方法实在太多。重点讲下基址固定,dll文件预读,二进制relink,二进制文件磁盘整理基址固定:每个DLL和可执行文件都有一个首选基地址。它表示该模块被映射到进程地址空间时最佳的内存地址。在构建可执行文件时,默认情况下链接器会将它的首选基地址设为0x400000。对于DLL来说,链接器会将它的首选基地址设为0x,然后将该地址以及代码、数据的相关地址都写入它们的PE文件中。当它们被加

3、载时,加载程序读取首选基地址的值,并试图把它们加载到相应位置。对于可执行文件和DLL中的代码,它们运行的时候所引用的的数据的地址,在链接的时候就已经确定。并且这些都是当exe文件或是DLL被加载到它们的首选基地址处时才是有效的。对于汇编代码:MOV0x00414540,5它是将5赋值给0x00414540处的内存地址。此地址已经固定。它说明当EXE或是DLL被加载到0x400000处时,0x00414540才是正确的。然而并不是所有模块都会被载入到首选基地址处。一旦模块没有被加载到首选基地址处,在该模块中对于地址的引用都是错误的,这时候基址重定位就是必须的。所谓重定位就是当某模块未被载入到首选

4、基地址时,加载器会计算模块实际载入的地址跟首选基地址的差值,将这个差值加到机器指令所引用的原来的地址,得到的就是模块中各指令所引用的数据在本进程地址空间的正确地址,随后加载器会修正模块中对每个内存地址的引用。为了便于系统有能力对各数据的地址进行修正,windows提供了重定位段。它包含很多基址重定位信息。这个段是有很多项组成。每一项表示一个要重定位的地址,它包含一个字节偏移量列。该偏移量表示一条机器指令所使用的内存地址。这便于系统在确认该模块需要重定位时对需要重定位的数据进行定位。当链接器在构建模块时,它会将重定位段嵌入到生成的文件中。对exe文件来说,由于每个文件总是使用独立的地址空间,所以

5、exe文件总是可以被加载到首选基地址上。对于DLL来说,很多DLL都是使用寄主进程的地址空间,不能保证各DLL的首选基地址各不相同。所以DLL一定要有重定位段,除非在链接时使用/FIXED开关。此时链接器会去掉重定位段。如果此后模块未被载入首选基地址,由于无法重定位,模块不会被载入,导致程序无法运行。如果加载程序将模块加载到它的首选基地址,那么系统就不会访问模块的重定位段。否则系统会打开模块的重定位段并遍历其中的条目,对每个条目,加载程序先找到包含机器指令的那个存储页面,算出差值,将差值加到机器指令当前正在使用的内存地址上。对于上例:假如它是在一DLL中。如果该DLL实际被加载到0x处,由于首

6、选基地址是0x,两者差为0x。加载器修正之后,该指令所引用的实际地址变成了0x。这样对各个数据的引用都会引用到正确的地址。要知道基址重定位需要很大的系统开销:1 :加载程序需要遍历模块重定位段并修改模块中大量的代码。这增加了程序初始化时间。2 :当加载程序写入模块的代码页面时,由于它们具有写时复制属性,写时复制机制会导致系统从页交换文件中分配空间来容纳这些修改后的页面。明白了这些我们应该清楚,为每个映射到进程的DLL设置不同的首选基地址是必须的。在链接时,选中ProjectPropertiesLinkerAdvancved,然后在BaseAddress中设置。这听起来很容易,但是如果程序需要载

7、入大量的模块,我们还需要这样一个一个设置吗话又说回来了,有些模块并不是我们创建的,我们应该怎么办呢Windows为我们提供了一个名为:的工具。如果在执行它时为它提供一组映像文件名,它会执行以下操作:1 :它会模拟创建一个地址空间。2 :它会打开这一组映像文件,并得到它们的大小和首选基地址。3:它会在模拟的地址空间对模块重定位的过程进行模拟,以便各模块没有交叉。4 :对于每个需要重定位的模块,它会解析模块的重定位段,并修改模块在磁盘文件中的代码。5 :将每个模块新的首选基地址写入各个模块磁盘文件中。所以推荐你在构建完所有项目后运行。由于Microsoft在发布windows之前,已经使用对所有操

8、作系统提供的模块进行了重定位,所以即使将操作系统的所有模块都映射到进程地址空间也不会发生交叉的现象。我们不再需要对随操作系统一起发布的模块进行基址重定位。使用或是手工修改各模块的首选基地址,以免某些模块不被加载到首选基地址上。这当然可以提高系统性能。但是我们还可以更显著的提高性能。这种技术就是模块绑定。让我们来回顾一下程序加载模块的过程:加载程序首先为进程创建虚拟地址空间,接着把可执行文件映射进来。之后打开可执行文件的导入段,将该程序需要的DLL进行定位并把它们也载入进来。随着加载程序将DLL模块加载到进程地址空间,它会同时检查每个DLL的导入段。如果一个DLL有导入段,那么加载程序会继续将所

9、需的额外的DLL模块映射到进程地址空间。当所有DLL都已被载入进程地址空间,它开始修复所有对导入符号的引用。这时它会再次查看每个模块的导入段,对导入段中每个符号,它会检查对应DLL的导出段,然后取出该符号的RVA并给他加上DLL模块被载入到进程地址空间的虚拟地址。计算出符号在进程的虚拟地址(VA),写入到可执行模块的导入段中。这样当一个符号被引用的时候,程序会查看可执行模块的导入段并取得导入符号虚拟地址(VA)O这就是模块加载的大概过程。可以看到,每次在程序加载时,都要将导入段的符号地址从其他DLL中获得,然后写入到导入段的相应位置(IAT)。这十分耗费时间。所谓的模块绑定就是说在运行之前,所

10、有导入符号在进程地址空间的地址已经获得,不需要加载时在计算出来这节省初始化时间,另外将导入符号的虚拟地址写入exe模块的导入段,也会由于写时复制机制将要修改的页面以系统页交换文件为后备存储器。这会遇到与基址重定位相似的问题。所以模块绑定对提高系统性能的提高是显著的。VisualStudio提供了一个名为的工具,如果在执行它的时候传给它一个映像文件名,它会对其执行模块绑定操作。具体过程为:1:它会打开模块的导入段。2:对导入段列出的每个DLL,它会中查该DLL文件的文件头,来确定该DLL的首选基地址。3:它会在DLL的导出段查看每个符号。4:取得符号的RAV并将其与模块的首选基地址相加。得到导入

11、符号的虚拟地址(VA)。5:在映像文件的导入段中添加额外信息。这些信息包括映像文件被绑定的各DLL的名称,以及各模块的时间戳。在整个过程中做了两个重要假设:1 :进程初始化时所需的DLL都被映射到了它们的首选基地址。2 :绑定完成之后,DLL导出段所列出的符号的位置没有发生改变。这可以通过检查每个DLL的时间戳来保证。如果上述假设有一个不成立。加载程序必就向绑定之前一样,手动修正可执行文件导入段。如果都成立加载程序就可以不用做这些工作了。Dll预读DLL预加载是指在显示加载DLL之前,进行DLL的预读不同系统预读方法选取对性能影响较大,经测试在Win7上用HANDLEfile_handle=C

12、reateFileA(file_path,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);这种方式打开文件,再用:ReadFile读,性能较好。在WinXPt用适合用这种方式HMODULEdll_module=:LoadLibraryExA(file_path,NULL,LOAD_WITH_ALTERED_SEARCH_PATH|DONT_RESOLVE_DLL_REFERENCES);完整代码如下:摘自chrom

13、eboolPreReadImage(constchar*file_path,size_tsize_to_read,size_tstep_size);typedefunsignedcharuint8;voidTouchPagesInRange(void*base_addr,size_tlength)if(base_addr=NULL)|(length<=0)return;Also,makesureweuseaSYSTEM_INFOsystem_info=;GetSystemInfo(&system_info);if=0)=4096;volatileuint8*touch_ptr=r

14、einterpret_cast<uint8*>(base_addr);volatileuint8*final_touch_ptr=touch_ptr+length-1;uint8dummy;while(touch_ptr<final_touch_ptr)dummy=*touch_ptr;touch_ptr+=;dummy=*final_touch_ptr;PIMAGE_DOS_HEADERGetDosHeader(HMODULEmodule)returnreinterpret_cast<PIMAGE_DOS_HEADER>(module);PIMAGE_NT_HE

15、ADERSGetNTHeaders(HMODULEmodule)PIMAGE_DOS_HEADERdos_header=GetDosHeader(module);returnreinterpret_cast<PIMAGE_NT_HEADERS>(reinterpret_cast<char*>(dos_header)+dos_header->e_lfanew);boolVerifyMagic(HMODULEmodule)PIMAGE_DOS_HEADERdos_header=GetDosHeader(module);if(dos_header->e_magic

16、!=IMAGE_DOS_SIGNATURE)returnfalse;PIMAGE_NT_HEADERSnt_headers=GetNTHeaders(module);if(nt_headers->Signature!=IMAGE_NT_SIGNATURE)returnfalse;if(nt_headers->!=sizeof(IMAGE_OPTIONAL_HEADER)returnfalse;if(nt_headers->!=IMAGE_NT_OPTIONAL_HDR_MAGIC)returnfalse;returntrue;boolPreReadImage(constcha

17、r*file_path,size_tsize_to_read,size_tstep_size)if(:Util:UI:IsWin7()OntheseOSes,theforcedreadsthroughtheDLLactuallyThesolutionistosequentiallyreadfilecontentsHANDLEfile_handle=CreateFileA(file_path,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL

18、_SCAN,NULL);if(file_handle=INVALID_HANDLE_VALUE)returnfalse;constDWORDactual_step_size=max(static_cast<DWORD>(step_size),static_cast<DWORD>(1024*1024);LPVOIDbuffer=:VirtualAlloc(NULL,actual_step_size,MEM_COMMIT,PAGE_READWRITE);if(buffer=NULL)returnfalse;DWORDlen;size_ttotal_read=0;while(

19、:ReadFile(file_handle,buffer,actual_step_size,&len,NULL)&&len>0&&(size_to_readtotal_read<size_to_read:true)total_read+=static_cast<size_t>(len);:VirtualFree(buffer,0,MEM_RELEASE);CloseHandle(file_handle);elseHere,readingtheDLLfromdiskdoesn'tdoWeusethesystem'sp

20、ageHMODULEdll_module=:LoadLibraryExA(file_path,NULL,LOAD_WITH_ALTERED_SEARCH_PATH|DONT_RESOLVE_DLL_REFERENCES);if(!dll_module)returnfalse;PIMAGE_NT_HEADERSnt_headers=GetNTHeaders(dll_module);size_tdll_module_length=min(size_to_readsize_to_read:0,static_cast<size_t>(nt_headers->);TouchPagesI

21、nRange(dll_module,dll_module_length);FreeLibrary(dll_module);returntrue;二进制文件重组PE文件重组是,应用程序冷启过程中,对某个PE文件所有函数按启动过程调用顺序进行二进制重组。重组工具:sawbuck,这是google提供的一系列工具。可在下载工具该网页也有原理介绍。首先,先下载sawbuck工具包重组方法如下:1.先确定要重组的应用程序目录,PE文件,并要有PE文件对应的PDB文件。如:.eitftersianisanWKlaw文件史Jplocales文件交.original2OL3/&/2519:44刘铁re

22、sources20L3,/B/28L5e15文件交懦chromedl12DL3,/2520:的版程序r星chrome.dll.pdb'M13/5/251S50ProgramDehjg.Echrome.c-kc201Wifi1644囹chromCiTKCip-db20L3/8/;8应24ProgramDcbuq2 .要对进行重组,则还需要准备把需重组的PE文件,和对应的PDB剪切到一个文件夹下,此文件夹一般与应用程序的EXE文件在同一目录。保证应用程序当前目录下,没有要重组的PE文件和应的PDB.如:把和移到original目录下.卜本地懑矗(D:卜Release>wlam帮助(如

23、共享”刻录新建文件夹名称,extensionslocalesoriginalFchrome.exechrome,exepdb3 .用sawbuck工具包中的,对进彳hhook.是命令行工具,使用如下命令可以对进彳thook,-input-image=D:Releaseoriginal-output-iamge=D:Release-mode=calltracehook4 .并):ProgpamFiles<x86>Google8awhucksiizyqybiniesXexe>instrumentinput-ina!jfe-d:Releaseorigin*lchrone,dll-c

24、utjput-inageleaseSchi*ome.dll-mode=caLItVacdK92?Zi®fl410:IHFO:application_impl.Ji<44>lSyzygyIn£tminenterUersion0_2_2V.9(1?6±>.0927/18941B:INFO:application_inpl_h<4>CopyrightCc>GoogleInc_Allrightsreserued.FH927Z1RH41R:INFO:inst7i*iimAntA>'_iJith_a.(fRnt_nrCA9&g

25、t;1DrFan±a(jRntPLI*fni*n-A11fri'AcemadeisuGal_clientB?27Z1O®410;IHFO:pc_relir*ker*cc<15?JJIrtputFDDnutspecifaeaixfliinyfurit0?27/lS0411:INFO:pe_relinker *ccS83)】 Xchrone.dll,pdb0927/1SB411:INFO:pe_relinker,cc<742> .dll092 7/18 Mil : INFO :pare LLnlnr. c c C743 > 1 .dll.pdtj

26、fl927/lfiB411 : IWFO :pe_re linker _ cc <744> J 0927/160411:INFO:pe_relinker_cc<?45) 1 r0927/1)10411 : I NFO:pe_rMe linker _cc CilS M Jivane .dlllining default out put FDB path: d:B& leaseInput iiK)dul« : d:ReleaseoriginalSchroneInput PDB ± d; ReleaseoriainalScliromeOutput mod

27、uile: d: ReleaseSclirone.dllOutput PDB : d:RelEaseclirame.dlLpdtjDecompns iinQf mtidlu le : 日:Re lease oi*i gina IXn手动复制(在sawbuck工具包中)到刚产出 相同的目录如:5.启动,命令如下:startstart-verbose-trace-dir=traces-trace-dir指定的产出目录,这里是目录traces,与在同一目录。D;FrogranFiles<>B6>>JGcolesawbucisyzyffyxbinariesxexe>:CA

28、Ftcall_trace_seruice.exestart-uerLose-1race-dii*atracesD;FruyudunFJ1e»<>86>'Stiu*jlc'virtwbuiiktjyayyj;'iJjliiKirlc3ee>3927x185338:INFO:service«cc<306>Stai't±n9thecall-traceservice.0927zia5330:UEREOSEl :ser<jice .cc<12?> 1 Q927zig5330:UEnBOSE

29、l;scrvice.cc<169> ace-sucJ usin? the JncalrpcJ protocol (0927/195338 ;UEWSE1; scrv ice «ccC182> (B927/18533B:UEJItioEl:seFvi£e,cc<192>Service nutejc acifuipedInitializing RPC endpoint * sjsysjy-call-trRegistering the CallTrace interface , Kejfisterinsf the CalirrdceCvntrvl i

30、nterf己cie?Z7/18530: INFO:service ,"CNCl The (B727/18533B:VEflB0SEl;scrv1cb.cc<Z06> IG927185330;UEFBOSE1:servIce,cc<234>1 mode .call-trace service Is running.Startln$r the RPG server. Call-trace seruIce Is i*ur»ningr In blocking6.运行7 .让运行一短时间后,执行如下命令:8 .stop停止记录数据。D:ProgiFrriFil

31、es<x8&>GciDgflcawbuchsyzyg|jjXJjdnat'x&sexe>callti*ice_fiepuice.exfStop(0927/185514;INFO:seruice_nain.cc<317>StoppingcalltraceloggingserviceinslanceatJsyzyc/y-call-traee-svculancalrpc.0927/185514;INFO;seruicejiain.cc<334>JCalltraceseruiceshutdounhasbeeni*etested,:Pa&

32、lt;jgi*amFiles<x86>XfioogleXsawbudtNsiizgyxbinariesexe>-停止后会在traces目录产生一些bin文件如:glckcowbudc*syzygykbinaritc*cctraces*小广手fi1J5SiV)工具T)弗助iH)写中k共享F刻录新建如续舞G静“君祢修笈日期,类型三IS_chmm-23130927195445400bifT|2013/2719:5S邑:N文4=,t-ace-rhrtime.ej(e-2CH5092718544&73&fcin2C139j271E:55BINi-4Vstcthromc.

33、cxc-2013092719556012.bin2013/27IS:55EJ】N文4一trice-throm».»Ke-2011092i-6372.biffX)132718!54ftJN文件trace-Dhrome.exe-23150195435-M84Lir2C139/2519.56B:N3C4trace-chr«m-200935195437756&bin2C12251&:56在N/#-trdrF-hrCEEEK4茹l利425】4弓中E79,bin7”啊内1匚喝&R'N7±有几个进程调用要重组的PE文件,就会产生几个bi

34、n文件,通过进程id可以区分不同的进程产生的bin.针对本例子chrome,找到主进程的bin文件,9 .如用对bin文件进行处理。-instrumented-image=*-output-file=*-pretty-printtraces'*p:ProgiranFiles(x86>XGooflesawbucsiizygjyShinari&sSexereoi'det'-exented-imagc=d:MieleaseScIifohe.dlloutput-filcIiraiW-reordcy1-?一一pretty-prinltracesStrace-clirone*exe-20130927185447-840R-hinrO9?7Zl9R724:INFO:icion_impl.b<44)1Jfy7jjf/p;RflmrdcwUrionR.2.29.fl<17(111r0527/l?0724:IHFO:applicA

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论