【移动应用开发技术】Benchmarking And Profiling(性能评测和剖析)_第1页
【移动应用开发技术】Benchmarking And Profiling(性能评测和剖析)_第2页
【移动应用开发技术】Benchmarking And Profiling(性能评测和剖析)_第3页
【移动应用开发技术】Benchmarking And Profiling(性能评测和剖析)_第4页
【移动应用开发技术】Benchmarking And Profiling(性能评测和剖析)_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

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

文档简介

【移动应用开发技术】BenchmarkingAndProfiling(性能评测和剖析)

Beingabletomeasureperformanceisrequired针对性能进行度量inordertodeterminewhetheroptimizationsareneeded是否需要优化,andwhethertheoptimizationsactuallyimprovedanything优化后是否有提升.

Performanceinmostcaseswillbemeasuredasafunctionofthetimeittakestocompleteanoperation.Forexample,theperformanceofagamewillveryoftenbemeasuredinhowmanyframespersecondcanberendered每秒渲染多少帧来度量,whichdirectlydependsonhowmuchtimeittakestorenderframes:toachieveaconstantframerate恒定数率of60framespersecond,eachframeshouldtakelessthan16.67millisecondstorenderanddisplay.Also,aswediscussedinChapter1,aresponsetimeof100millisecondsisoftendesiredinorderforresultstoappearinstantaneous有瞬时的感觉.

Inthischapteryoulearnthevariouswaysofmeasuringtimeinyourapplication.Youalsolearnhowtouseaprofilingtool剖析工具,Traceview,totraceJavacodeandnativecodeandeasilyidentifybottlenecks瓶颈inyourapplication.Finally,youlearnabouttheloggingmechanisminAndroidandhowtotakeadvantageofthefilteringcapabilities日志过滤机制的方法.6.1MeasuringTime测量时间

Howmuchtimeanoperation操作orsequenceofoperations操作序列takestocompleteisacriticalpieceofinformationwhenitistimetooptimizecode.Withoutknowinghowmuchtimeisspentdoingsomething,youroptimizationsareimpossibletomeasure.JavaandAndroidprovidethefollowingsimpleAPIsyourapplicationcanusetomeasuretimeandthereforeperformance:System.currentTimeMillisSystem.nanoTimeDebug.threadCpuTimeNanosSystemClock.currentThreadTimeMillisSystemClock.elapsedRealtimeSystemClock.uptimeMillis

Typically,yourapplicationneedstomaketwocallstothesemethodsasasinglecallishardlymeaningful.Tomeasuretime,yourapplicationneedsastarttimeandanendtime,andperformanceismeasuredasthedifferencebetweenthesetwovalues.Attheriskofsoundingoverlypatronizing,nowisagoodtimetostatethatthereare1,000,000,000nanosecondsinonesecond,orinotherwords,ananosecondisonebillionthofasecond.

NOTE:Eventhoughsomemethodsreturnatimeexpressedinnanoseconds,itdoesnotimplynanosecondaccuracy纳秒级的.Theactualaccuracydependsontheplatformandmaydifferbetweendevices.Similarly,System.currentTimeMillis()returnsanumberofmillisecondsbutdoesnotguaranteemillisecondaccuracy.

AtypicalusageisshowninListing6–1.Listing6–1.MeasuringTimelongstartTime=System.nanoTime();//performoperationyouwanttomeasureherelongduration=System.nanoTime()-startTime;System.out.println(“Duration:”+duration);

AnimportantdetailisthefactthatListing6–1doesnotuseanythingAndroid-specific.Asamatteroffact,thismeasurementcodeisonlyusingthejava.lang.System,java.lang.Stringandjava.io.PrintStreampackages.Consequently,youcouldusesimilarcodeinanotherJavaapplicationthatisnotmeanttorunonanAndroiddevice.TheDebugandSystemClockclassesare,ontheotherhand,Android-specific.WhileSystem.currentTimeMillis()waslistedasamethodtomeasuretime,itisactuallynotrecommendedtousethismethod,fortworeasons:

Itsprecisionandaccuracy精度准确度maynotbegoodenough.

Changingthesystemtimecanaffecttheresults.

Instead,yourapplicationshoulduseSystem.nanoTime()asitoffersbetterprecisionandaccuracy.6.1.1System.nanoTime()

Becausethereferencetimeisnotdefined,youshouldonlyuseSystem.nanoTime()tomeasuretimeintervals,asshowninListing6–1.Togetthetime(asaclock),useSystem.currentTimeMillis()asitdefinesthereturnvalueasthenumberofmillisecondssinceJanuary1,197000:00:00UTC.Listing6–2showsyouhowtomeasure,roughly,thetimeittakesforSystem.nanoTime()tocomplete.Listing6–2.MeasuringSystem.nanoTime()privatevoidmeasureNanoTime(){finalintITERATIONS=100000;longtotal=0;longmin=Long.MAX_VALUE;longmax=Long.MIN_VALUE;for(inti=0;i<ITERATIONS;i++){longstartTime=System.nanoTime();longtime=System.nanoTime()-startTime;total+=time;if(time<min){min=time;}if(time>max){max=time;}}Log.i(TAG,"Averagetime:"+((float)total/ITERATIONS)+"nanoseconds");Log.i(TAG,"Minimum:"+min);Log.i(TAG,"Maximum:"+max);}OnaSamsungGalaxyTab10.1,theaveragetimeisabout750nanoseconds.

NOTE:HowmuchtimeacalltoSystem.nanoTime()takesdependsontheimplementationandthedevice.

Becausethescheduler调度器isultimatelyresponsibleforschedulingthreadstorunontheprocessingunits,theoperationyouwanttomeasuremaysometimesbeinterrupted,possiblyseveraltimes,tomakeroomforanotherthread.Therefore,yourmeasurementmayincludetimespentonexecutingsomeothercode,whichcanmakeyourmeasurementincorrect,andthereforemisleading.

Tohaveabetterideaofhowmuchtimeyourowncodeneedstocomplete,youcanusetheAndroid-specificDebug.threadCpuTimeNanos()method.

6.1.2Debug.threadCpuTimeNanos()

Becauseitmeasuresonlythetimespentinthecurrentthread,

Debug.threadCpuTimeNanos()shouldgiveyouabetterideaofhowmuchtimeyourowncodetakestocomplete.However,ifwhatyouaremeasuringisexecutedinmultiplethreads,asinglecalltoDebug.threadCpuTimeNanos()won’tgiveyouanaccurateestimate,andyouwouldhavetocallthismethodfromallthethreadsofinterestandsumtheresults.Listing6–3showsasimpleexampleofhowDebug.threadCpuTimeNanos()canbeused.TheusageisnodifferentfromSystem.nanoTime()’s,anditshouldonlybeusedtomeasureatimeinterval.Listing6–3.UsingDebug.threadCpuTimeNanos()longstartTime=Debug.threadCpuTimeNanos();//warning:thismayreturn-1ifthesystemdoesnotsupportthisoperation//simplysleepforonesecond(otherthreadswillbescheduledtorunduringthattime)try{TimeUnit.SECONDS.sleep(1);//sameasThread.sleep(1000);}catch(InterruptedExceptione){e.printStackTrace();}longduration=Debug.threadCpuTimeNanos()-startTime;Log.i(TAG,"Duration:"+duration+"nanoseconds");

WhilethecodewilltakeaboutonesecondtocompletebecauseofthecalltoTimeUnit.SECONDS.sleep(),theactualtimespentexecutingcodeismuchless.Infact,runningthatcodeonaGalaxyTab10.1showsthatthedurationisonlyabout74microseconds.ThisisexpectedasnothingmuchisdoneinbetweenthetwocallstoDebug.threadCpuTimeNanos()otherthanputtingthethreadtosleepforonesecond.

NOTE:RefertotheTimeUnitclassdocumentation.TimeUnitoffersconvenientmethodsforconvertingtimebetweendifferentunitsandalsoperformingthread-relatedoperationssuchas

Thread.join()andObject.wait().Ofcourse,youcanalsomeasuretimeinyourapplication’sCcodeusing“standard”Ctimefunctions,asshowninListing6–4.Listing6–4.UsingCTimeFunction#include<time.h>voidfoo(){doubleduration;time_ttime=time(NULL);//dosomethinghereyouwanttomeasureduration=difftime(time(NULL),time);//durationinseconds}

6.2Tracing方法调用跟踪

Onceyouidentifywhatistakingtoomuchtime,youprobablywanttobeabletoknowinmoredetailwhichmethodsaretheculprits×××.Youcandothisbycreatingtracefileswiththehelpofatracing-specificmethod,andthenanalyzethemwiththeTraceviewtool.6.2.1Debug.startMethodTracing()

AndroidprovidestheDebug.startMethodTracing()methodtocreatetracefilesthatcanthenbeusedwiththeTraceviewtooltodebugandprofileyourapplication.ThereareactuallyfourvariantsoftheDebug.startMethodTracing()method:startMethodTracing()startMethodTracing(StringtraceName)startMethodTracing(StringtraceName,intbufferSize)startMethodTracing(StringtraceName,intbufferSize,intflags)

ThetraceNameparameterspecifiesthenameofthefiletowritethetraceinformationinto写入跟踪信息的文件名.(Ifthefilealreadyexistsitwillbetruncated.)Youneedtomakesureyourapplicationhaswriteaccesstothisfile.(Bydefault,thefilewillbecreatedinthesdcarddirectoryunlessanabsolutepathisgiven.)ThebufferSizeparameterspecifiesthemaximumsizeofthetracefile.Traceinformationcanuseafairamountofspaceandyourstoragecapacitymaybelimitedsotrytouseasensiblevalue(defaultis8MB).Androidcurrentlydefinesonlyoneflag,Debug.TRACE_COUNT_ALLOCS,sotheflagsparametershouldbesettoeither0orDebug.TRACE_COUNT_ALLOCS(toaddtheresultsfromDebug.startAllocCounting()tothetrace,thatis,thenumberandaggregatesizeofmemoryallocations).AndroidalsoprovidestheDebug.stopMethodTracing()method,which,youwouldhaveguessed,stopsthemethodtracing.Theusageisverysimilartotimemeasurementsseenearlier,asshowninListing6–5.Debug.startMethodTracing(“/sdcard/awesometrace.trace”);//performoperationyouwanttotracehereBigIntegerfN=FputeRecursivelyWithCache(100000);Debug.stopMethodTracing();//nowthereshouldbeafilenamedawesometrace.tracein/mnt/sdcard,getitinEclipseDDMS

ThetracefilewillbesavedontoyourAndroiddevice(ortheemulator),soyouwillneedtocopythefilefromthedevicetoyourhostmachine,forexampleinEclipse(usingDDMS)orwiththe“adbpull”command.6.2.2UsingtheTraceviewTool

TheAndroidSDKcomeswithatoolnamedTraceview,whichcanusethesetracefilesandgiveyouagraphicalrepresentationofthetrace,asshowninFigure6–1.YoucanfindtheTraceviewtoolintheSDK’stoolsdirectoryandsimplytypetraceviewawesometrace.traceonacommandlinetostartTraceview.Figure6–1.Traceviewwindow

Thetracebasicallycontainsthelistofallthefunctioncallstogetherwithhowmuchtimethesecallstookandhowmanyweremade.Sevencolumnsaredisplayed:Name:thenameofthemethodIncl%:thepercentageoftimespentinthatmethod(includingchildrenmethods)此方法中占的时间百分比Inclusive:thetimeinmillisecondsspentinthatmethod(includingchildrenmethods)Excl%:thepercentageoftimespentinthatmethod(excludingchildrenmethods)Exclusive独家新闻:thetimeinmillisecondsspentinthatmethod(excludingchildrenmethods)Calls+RecurCalls/Total:thenumberofcallsandrecursivecallsTime/Call:theaveragetimepercallinmillisecondsForexample,atotalof14callstoBigInteger.multiply()weremadeforatotalof10.431milliseconds,or745microsecondspercall.BecausetheVMwillrunmoreslowlywhentracingisenabled,youshouldnotconsiderthetimevaluesasdefinitivenumbers.Instead,usethesetimevaluessimplytodeterminewhichmethodorrunisfaster.Ifyouclickonamethodname,Traceviewwillshowyoumoredetailedinformationforthatspecificmethod,asshowninFigure6–2.Thisincludes:Parents(themethodscallingthismethod)Children(themethodscalledbythismethod)Parentswhilerecursive(ifmethodisrecursive)Childrenwhilerecursive(ifmethodisrecursive)AsyoucanseeinFigure6–2,mostofthetimeisspentonfourmethods:BigInteger.multiply()BigInteger.pow()BigInteger.add()BigInteger.shiftLeft()

EventhoughweestablishedwherethebottleneckswereinChapter1already,Traceviewallowsyoutoveryquicklydeterminewheretheycanbewithouthavingtoperformanyexpansiveresearch进一步花精力研究.Inthisparticularcase,youcanquicklyseethatBigInteger.multiply()iswheremostofthetimeisspent,followedbyBigInteger.pow().Thisisnotsurprisingasmultiplicationsareintuitively直观的morecomplicatedthanadditionsandshiftsdonebyBigInteger.add()andBigInteger.shiftLeft().Figure6–2.Amethod’sdetailedinformation

Atthetopofthewindow,youcanseethetimelineforthemainthread.Youcanzoom急速上升inbyselectingacertainregioninthistimeline,andzoomoutbydouble-clickingonthetimescale.FamiliarizeyourselfwiththeTraceviewtoolandlearnhowtonavigatefromonemethodtoanother.

Hint:it’seasy.Justclickonamethod’sname!

BecausetheJust-In-Timecompilerisdisabledwhentracingisenabled,theresultsyougetcanbesomewhatmisleading.Infact,youmaythinkamethodtakesacertaintimewheninrealityitcanbemuchfastersinceitcanbecompiledintonativecodebytheDalvikJust-In-Timecompiler.Also,thetracewon’tshowyouhowmuchtimeisspentinnativefunctions.Forexample,Figure6–1showscallstoNativeBN.BN_mul()andNativeBN.BN_exp(),butifyouclickonthesemethods,youwon’tseewhatothermethodstheymaycall.6.2.3TraceviewinDDMS

AnotherwaytotracecallsanduseTraceviewistogenerateatracefiledirectlyfromtheEclipseDDMSperspective观点(视图).Afteryouselectaspecificprocess,youcanclickontheStartMethodProfilingicon,andthenclickagaintostopprofiling.Onceyoustopprofiling,thetracewillbevisibleintheDebugperspectiveinEclipseanditwillbelikeusingTraceview.Figure6–3showshowtostartmethodprofilingfromtheDDMSperspective,andFigure6–4showsyouthemethodprofilingviewintheDebugperspective.Figure6–3.StartingmethodprofilingfromtheDDMSperspectiveFigure6–4.MethodprofilingintheDebugperspectiveAsyoucanseeinFigure6–4,timelinesformultiplethreadscanbeshown.

Traceviewisnotperfect,howeveritcangiveyougreatinsightintowhatcodeisactuallyexecutedandwherethebottlenecksmaybe.Whenitistimetoachievebetterperformance,thisshouldbeoneofyourpreferredtoolstodetectwhereyoushouldfocusyourattention.

TIP:Remembertodeletethetracefileswhenyouaredonewithyourdebuggingandprofiling.YoucanusetheEclipseDDMSperspectivetodeletefilesfromyourdevice.6.2.4NativeTracing本地方法追踪

InadditiontoprofilingJavamethodswiththestartMethodTracing()APIs,Androidalsosupportsnativetracing(includingkernelcode).NativetracingisalsoreferredtoasQEMUtracing.InthissectionyoulearnhowtogeneratetheQEMUtracefilesandhowtoconvertthemintoafileTraceviewcaninterpret..TogenerateQEMUtraces,youhavetodotwothings:Starttheemulatorusingthe–traceoption(forexample,“emulator–tracemytrace–avdmyavd”).Startandthenstopnativetracing,eitherbycallingDebug.startNativeTracing()andDebug.stopNativeTracing(),orbypressingtheF9key(thefirsttimewillstarttracing,thesecondtimewillstoptracing).IntheAVD’stracesdirectoryonyourhostmachine,youwillthenfindamytracedirectorycontainingseveralQEMUemulatortracefiles:qtrace.bbqtrace.excqtrace.insnqtrace.methodqtrace.pidqtrace.staticNOTE:QEMUisanopen-sourceemulator.Refertoformoreinformation.GeneratingTraceFileForTraceviewTousethetracesinTraceviewlikewedidforJavamethods,youneedtogenerateatracefilethatTraceviewcanunderstand.Todothis,youwillusethetracedmdumpcommand(nottobeconfusedwiththedmtracedumpSDKtool,whichisatoolusedtocreatethecallstackasatreediagram).ThetracedmdumpcommandisdefinedintheAndroidsourcecode,inbuild/envsetup.sh.Foraccesstothiscommand,youhavetodownloadtheAndroidsourcecodeandcompileAndroid.TodownloadthefullAndroidcode,followtheinstructionson:/source/downloading.html.TocompileAndroid,followtheinstructionson/source/building.html

YoucanalsocompileyourownemulatorfromtheAndroidsourcecodeinsteadofrelyingontheonefromtheSDK.OnceAndroidiscompiled,youshouldhaveallthetoolsyouneedtocreatethetracefileTraceviewneeds.

IntheAVD’stracesdirectory,youcannowsimplyruntracedmdumpmytrace,whichwillcreateatracefileyoucanopenwithTraceview,asshowninFigure6–5.Makesureyourpathissetsothatallthecommandsexecutedbytracedmdumpcansucceed.Iftracedmdumpfailswitha“commandnotfound”errormessage,itislikelyyourpathisnotsetproperly.Forexample,tracedmdumpwillcallpost_trace,whichislocatedintheout/host/linux-x86/bindirectory.

Figure6–5.NativetracingwithTraceviewWhiletheuserinterfacestaysthesame,whatyouactuallyseeinFigure6–5isthelistofnativefunctionsbeingcalled,suchasvsnprintf()andsys_open(),respectively#10and#13.

Twofilesrepresentingthesamedataareactuallycreatedbytracedmdump:dmtrace

dmtrace.html

ThefirstfileistobeusedwithTraceviewwhilethesecondcanbeopenedwithanywebbrowser,includingLynx.

NOTE:Manyusersreportproblemswhenusingtracedmdump,anderrormessagesarenotalwaysveryclear.Ifyouencounteranerror,searchforasolutionontheInternetasitisverylikelysomeonehadthesameproblemandpublishedasolution.Sometimessimplyhavingareal-time,human-readabledescriptionofwhatishappeninginyourapplicationcanhelpyoutremendously.Loggingmessageshavebeenusedforaverylongtimebeforesophisticateddebuggingtoolswereinvented,andmanydeveloperswillheavilyrelyonlogstodebugorprofileapplications日志调试或者剖析应用.6.3Logging日志

Aswehaveseeninmanylistingsalready,youcanusetheLogclasstoprintoutmessagestoLogCat.InadditiontotheJavatraditionalloggingmechanismsuchasSystem.out.println(),Androiddefinessixloglevels,eachhavingitsownmethods:verbose(Log.v)debug(Log.d)info(Log.i)warning(Log.w)error(Log.e)assert(Log.wtf)Forexample,acalltoLog.v(TAG,“mymessage”)isequivalenttoacalltoLog.println(Log.VERBOSE,TAG,“mymessage”).

NOTE:TheLog.wtf()methodswereintroducedinAPIlevel8,butLog.ASSERTexistssinceAPIlevel1.IfyouwanttousetheASSERTloglevelbutwanttoguaranteecompatibilitywitholderAndroiddevices,useLog.println(Log.ASSERT,…)insteadofLog.wtf(…).YoucanthenuseLogCatinEclipse(Window

ShowView

LogCat)and/orinaterminal(adblogcat,orsimplylogcatfromanadbshell)andseethemessagesgeneratedwhileyourapplicationruns.Sincemanymessagesmaybedisplayed,manyofthemnotcomingfromyourapplication,youmaywanttocreatefilterssoyoucanfocusontheoutputthatisrelevanttoyou.Youcanfiltermessagesbasedontheirtags,prioritylevels,andPIDs.InEclipse,youcanusetheCreateFilterfeature,asshowninFigure6–6.Figure6–6.CreatingLogCatfilterwithEclipseEclipsecurrentlydoesnotsupportcreatingafilteronmultipletags,soyouwillhavetouseadblogcatinsteadifyouwanttodo

温馨提示

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

评论

0/150

提交评论