版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
【移动应用开发技术】UsingMemoryEfficiently(ProAndroidAppsPerformanceOptimization)
UsingMaoemoryEfficiently
高效使用内存4.1AWordOnMemory4.2DataTypes4.2.1ComparingValues值的比较4.2.2OtherAlgorithms4.2.3SortingArrays4.2.4DefiningYourOwnClasses4.3AccessingMemory访问内存4.4
LayingOutYourData排布数据4.5
GarbageCollection垃圾收集4.51MemoryLeaks4.5.2References4.6APIs4.7LowMemory内存少的时候
Applicationsspendasignificantpartoftheirtimedealingwithdatainmemory(应用生命期的绝大部分时间都是用来处理内存中的数据).Whilemanydevelopersareawareoftheneedtotrytouseaslittlememoryaspossibleondeviceslikephonesortablets,notallrealizetheimpactofmemoryusageonperformance(并不是所有人都意识到内存对性能的影响).Inthischapter,youwilllearnhowchoosingtherightdatatypeandhowarrangingyourdatainmemory如何在内存中排布数据canboostyourapplication’sperformance.Also,wewillreviewabasicyet虽然基本还是oftenoverlookedfeatureofJava:memorymanagementusing.garbagecollectionandreferences垃圾回收和内存管理.4.1AWordOnMemory
Nomatterhowmuchanapplicationisgiven,itcouldalwaysaskformore.TherearetwobigdifferencesbetweenanAndroiddevice,likeaphoneortablet,andatraditionalcomputer:Theamountofphysicalmemory物理内存的大小Theabilitytodovirtualmemoryswapping虚拟内存交换的能力
Typically通常情况下,today’scomputerscomeinstalledwithseveralgigabytesofRAM(fewcomeinstalledwithonly1GBorless),howeverAndroiddevicesoftenhaveamaximumof512MBofRAM.Toaddinsulttoinjury雪上加霜的是,computersuseswapping内存交换能力,whichAndroiddevicesdon’thave,togivethesystemandapplicationstheillusionofmorememory内存可用的假象.Forexample,anapplicationcouldstilladdressup寻址to4GBofmemoryevenwithasystemthathasonly256MBofRAM.YourAndroidapplicationsimplydoesnothavethisluxury特遇,andthereforeyouhavetobemorecarefulabouthowmuchmemoryyourapplicationuses必须小心内存的使用量.NOTE:YoucanfindapplicationsonAndroidMarketthatenableswapping,buttheyrequirerootaccessandadifferentLinuxkernel内核.AssumetheAndroiddevicesyourapplicationswillberunningondonothaveswappingcapabilities假定运行在不具备内存交换功能的设备上.
TheJavalanguagedefinesthesizeofmostprimitivetypes,asshowninTable4–1,togetherwiththeirmatchingnativetypes.IfyouareprimarilyfamiliarwithC/C++code,thenyouneedtopayextraattentiontotwothings:Java’scharis16-bit(UTF-16).Java’slongis64–bit(whileClongisusually32-bitandClonglongisusually64–bit).Table4–1.JavaPrimitiveTypesJavaprimitivetypeNativetypeSizebooleanjboolean8bits(VMdependent)bytejbyte8bitscharjchar16bitsshortjshort16bitsintjint32bitslongjlong64bitsfloatjfloat32bitsdoublejdouble64bits
Agoodruleofthumb翻阅istouseaslittlememoryaspossible,whichisjustcommonsenseasyourAndroiddeviceandapplicationshavealimitedamountofmemory.ButinadditiontoreducingtheriskofanOutOfMemoryErrorexception,usinglessmemorycanalsoincreaseperformance.
Performancedependsmostlyonthreethings:
HowtheCPUcanmanipulateacertaindatatype
Howmuchspaceisneededtostoredataandinstructions
Howdataislaidoutinmemory数据在内存中的布局
Wewillcovereachone逐一讲解oftheseitems,lookingatbothnativecodeandJavacode,measuringexecutiontimes,andcomparingseveralimplementationsofsimplealgorithmstoimproveperformance.4.2DataTypes
Youalreadygotanaperuofthefirstpoint,howtheCPUcanmanipulateacertaindatatype,inChapter2withthenativecodeversionofcomputeIterativelyFaster(),whichusedtwoaddinstructionstoaddtwo64–bitintegers,asshowninListing4–1.Listing4–1.AddingTwo64–bitIntegers448:e0944002addsr4,r4,r244c:e0a55003adcr5,r5,r3
BecausetheARMregistersare32-bitwide,twoinstructionsareneededtoaddtwo64–bitintegers;thelowest32-bitintegersarestoredinoneregister(r4),andthehighest32-bitarestoredinanotherregister(r5).Addingtwo32-bitvalueswouldrequireasingleinstruction.
Let’snowconsiderthetrivial简单Cfunction,showninListing4–2,whichsimplyreturnsthesumoftwo32-bitvaluespassedasparameters.Listing4–2.SumofTwoValuesint32_tadd_32_32(int32_tvalue1,int32_tvalue2){returnvalue1+value2;}TheassemblycodeforthisfunctionisshowninListing4–3.Listing4–3.AssemblyCode000016c8<add_32_32>:16c8:e0810000addr0,r1,r016cc:e12fff1ebxlr
Asexpected,onlyoneinstructionisneededtoaddthetwovalues(andbxlristheequivalentofreturn).Wecannowcreatenewfunctionsthatareverymuchlikeadd_32_32,butwithdifferenttypesforvalue1andvalue2.Forexample,add_16_16addstwoint16_tvalues,asshowninListing4–4,andadd_16_32addsanint16_tvalueandanint32_tvalue,asshowninListing4–5.Listing4–4.add_16_16’sCandAssemblyint16_tadd_16_16(int16_tvalue1,int16_tvalue2){returnvalue1+value2;}000016d0<add_16_16>:16d0:e0810000addr0,r1,r016d4:e6bf0070sxthr0,r016d8:e12fff1ebxlrListing4–5.add_16_32’sCAndAssemblyint32_tadd_16_32(int16_tvalue1,int32_tvalue2){returnvalue1+value2;}000016dc<add_16_32>:16dc:e0810000addr0,r1,r016e0:e12fff1ebxlr
Youcanseethataddingtwo16-valuesrequiredanadditionalinstructioninordertoconvert转换theresultfrom16-bitto32-bit.
Listing4–6showsfivemorefunctions,repeatingbasicallythesamealgorithmbutfor
differentdatatypes.Listing4–6.MoreAssemblyCode000016e4<add_32_64>:16e4:e0922000addsr2,r2,r016e8:e0a33fc0adcr3,r3,r0,asr#3116ec:e1a00002movr0,r216f0:e1a01003movr1,r316f4:e12fff1ebxlr000016f8<add_32_float>:16f8:ee070a10fmsrs14,r016fc:eef87ac7fsitoss15,s141700:ee071a10fmsrs14,r11704:ee777a87faddss15,s15,s141708:eefd7ae7ftosizss15,s15170c:ee170a90fmrsr0,s151710:e12fff1ebxlr00001714<add_float_float>:1714:ee070a10fmsrs14,r01718:ee071a90fmsrs15,r1171c:ee377a27faddss14,s14,s151720:ee170a10fmrsr0,s141724:e12fff1ebxlr00001728<add_double_double>:1728:ec410b16vmovd6,r0,r1172c:ec432b17vmovd7,r2,r31730:ee366b07fadddd6,d6,d71734:ec510b16vmovr0,r1,d61738:e12fff1ebxlr0000173c<add_float_double>:173c:ee060a10fmsrs12,r01740:eeb77ac6fcvtdsd7,s121744:ec432b16vmovd6,r2,r31748:ee376b06fadddd6,d7,d6174c:ec510b16vmovr0,r1,d61750:e12fff1ebxlr
NOTE:Thegeneratednativecodemaydifferfromwhatisshownhereasalotdependsonthecontextoftheaddition加法的上下文而定.(Codethatisinlinemaylookdifferentasthecompilermayreorderinstructionsorchangetheregisterallocation.)
Asyoucansee,usingasmallertypeisnotalwaysbeneficialtoperformanceasitmayactuallyrequiremoreinstructions,asdemonstratedinListing4–4.Besides,ifadd_16_16werecalledwithtwo32-bitvaluesasparameters,thesetwovalueswouldfirsthavetobeconvertedto16-bitvaluesbeforetheactualcall,asshowninListing4–7.Onceagain,thesxthinstructionisusedtoconvertthe32-bitvaluesinto16-bitvaluesbyperforminga“signextend符号扩展”operation.Listing4–7.Callingadd_16_16WithTwo32-BitValues00001754<add_16_16_from_32_32>:1754:e6bf0070sxthr0,r01758:e6bf1071sxthr1,r1175c:eaffffdbb16d0<add_16_16>4.2.1ComparingValues值的比较
Let’snowconsideranotherbasicfunction,whichtakestwoparametersandreturns0or1dependingonwhetherthefirstparameterisgreaterthanthesecondone,asshowninListing4–8.Listing4–8.ComparingTwoValuesint32_tcmp_32_32(int32_tvalue1,int32_tvalue2){return(value1>value2)?1:0;}
Again,wecanseetheassemblycodeforthisfunctionanditsvariants变种inListing4–9.Listing4–9.ComparingTwoValuesInAssembly00001760<cmp_32_32>:1760:e1500001cmpr0,r11764:d3a00000movler0,#0;0x01768:c3a00001movgtr0,#1;0x1176c:e12fff1ebxlr00001770<cmp_16_16>:1770:e1500001cmpr0,r11774:d3a00000movler0,#0;0x01778:c3a00001movgtr0,#1;0x1177c:e12fff1ebxlr00001780<cmp_16_32>:1780:e1500001cmpr0,r11784:d3a00000movler0,#0;0x01788:c3a00001movgtr0,#1;0x1178c:e12fff1ebxlr00001790<cmp_32_64>:1790:e92d0030push{r4,r5}1794:e1a04000movr4,r01798:e1a05fc4asrr5,r4,#31179c:e1550003cmpr5,r317a0:e3a00000movr0,#0;0x017a4:ca000004bgt17bc<cmp_32_64+0x2c>17a8:0a000001beq17b4<cmp_32_64+0x24>17ac:e8bd0030pop{r4,r5}17b0:e12fff1ebxlr17b4:e1540002cmpr4,r217b8:9afffffbbls17ac<cmp_32_64+0x1c>17bc:e3a00001movr0,#1;0x117c0:eafffff9b17ac<cmp_32_64+0x1c>000017c4<cmp_32_float>:17c4:ee070a10fmsrs14,r017c8:eef87ac7fsitoss15,s1417cc:ee071a10fmsrs14,r117d0:eef47ac7fcmpess15,s1417d4:eef1fa10fmstat17d8:d3a00000movler0,#0;0x017dc:c3a00001movgtr0,#1;0x117e0:e12fff1ebxlr000017e4<cmp_float_float>:17e4:ee070a10fmsrs14,r017e8:ee071a90fmsrs15,r117ec:eeb47ae7fcmpess14,s1517f0:eef1fa10fmstat17f4:d3a00000movler0,#0;0x017f8:c3a00001movgtr0,#1;0x117fc:e12fff1ebxlr00001800<cmp_double_double>:1800:ee060a10fmsrs12,r01804:eeb77ac6fcvtdsd7,s121808:ec432b16vmovd6,r2,r3180c:eeb47bc6fcmpedd7,d61810:eef1fa10fmstat1814:d3a00000movler0,#0;0x01818:c3a00001movgtr0,#1;0x1181c:e12fff1ebxlr00001820<cmp_float_double>:1820:ee060a10fmsrs12,r01824:eeb77ac6fcvtdsd7,s121828:ec432b16vmovd6,r2,r3182c:eeb47bc6fcmpedd7,d61830:eef1fa10fmstat1834:d3a00000movler0,#0;0x01838:c3a00001movgtr0,#1;0x1183c:e12fff1ebxlr1840:e3a00001movr0,#1;0x11844:e12fff1ebxlr
Usingthelongtypeappearstobeslowerthanusingtheshortandinttypesbecauseofthehighernumberofinstructionshavingtobeexecuted.Similarly,usingthedoubletypeandmixingfloatanddoubleseemstobeslowerthanusingthefloattypealone.NOTE:Thenumberofinstructionsaloneisnotenoughtodeterminewhethercodewillbeslowerornot.Becausenotallinstructionstakethesameamountoftimetocomplete,andbecauseofthecomplexnatureoftoday’sCPUs,onecannotsimplycountthenumberofinstructionstoknowhowmuchtimeacertainoperationwilltake.4.2.OtherAlgorithms
Nowthatwehaveseenwhatdifferencedatatypescanmakeonthegeneratedcode,itistimetoseehowslightly轻微moresophisticatedalgorithmsperformwhendealingwithmoresignificantamountsofdata.
Listing4–10showsthreesimplemethods:onethatsortsanarraybysimplycallingthestaticArrays.sort()method,onethatfindstheminimumvalueinanarray,andonethataddsalltheelementsinanarray.Listing4–10.Sorting,Finding,andSumminginJavaprivatestaticvoidsort(intarray[]){Arrays.sort(array);}privatestaticintfindMin(intarray[]){intmin=Integer.MAX_VALUE;for(inte:array){if(e<min)min=e;}returnmin;}privatestaticintaddAll(intarray[]){intsum=0;for(inte:array){sum+=e;//thiscouldoverflowbutwe’llignorethat}returnsum;}
Table4–2showshowmanymillisecondseachofthesefunctionstooktocompletewhengivenanarrayofonemillionrandomelements.Inadditiontothese,theresultsforthevariantsofthesemethods(usingshort,long,float,anddoubletypes)arealsoshown.RefertoChapter6formoreinformationonhowtomeasureexecutiontimes.Table4–2.ExecutionTimesWith1,000,000-ElementArrayJavaprimitivetypesortfindMinaddAllshort932725int7533130long1,2405754float1,0804133double1,3585855Wecanmakeacoupleofcommentsontheseresults:Sortingtheshortarrayismuchfasterthansortinganyoftheotherarrays.(sort数组排序永远快于其他数组排序)Workingwith64–bittypes(longordouble)isslowerthanworkingwith32-bittypes.4.2.3SortingArrays
Sortinganarrayof16-bitvaluescanbemuchfasterthansortinganarrayof32-or64–bitvaluessimplybecauseitisusingadifferentalgorithm.WhiletheintandlongarraysaresortedusingsomeversionofQuicksortalgorithm,theshortarraywassortedusingcountingsort,whichsortsinlineartime.Usingtheshorttypeinthatcaseiskillingtwobirdswithonestone:lessmemoryisconsumed(2megabytesinsteadof4forthearrayofintvalues,and8megabytesforthearrayoflongvalues)andperformanceisimproved.NOTE:ManywronglybelieveQuicksortisalwaysthemostefficientsortingalgorithm.YoucanrefertoArrays.javaintheAndroidsourcecodetoseehoweachtypeofarrayissorted.
Alesscommonsolutionistousemultiplearraystostoreyourdata用多个数组储存数据.Forexample,ifyourapplicationneedstostoremanyintegersallintherange0to100,000,thenyoumaybetemptedtoallocateanarrayof32-bitvaluesforstorageastheshorttypecanbeusedonlytostorevaluesfrom-32,768to32,767.Dependingonhowvaluesaredistributed,
youmayendupwithmanyvaluesequaltoorlessthan32,767.Insuchanevent,itmaybebeneficialtousetwoarrays:oneforallthevaluesbetween0and32,767(thatis,anarrayofshortvalues),andoneforallvaluesgreaterthan32,767(anarrayofintvalues).Whilethismostlikelywouldresultinagreatercomplexity复杂,thememorysavingsandpotentialperformanceincreasemaymakethatsolutionworthwhile,andperhapsevenallowyoutooptimizetheimplementationofcertainmethods.Forexample,amethodthatfindsthemaximumelementmayonlyhavetogothroughthearrayofintvalues.(Onlyifthearrayofintvaluesisemptywoulditgothroughthearrayofshortvalues.只有Int数组是空的时候才遍历short数组)
OneofthetypesthatwasnotshowninListing4–9andTable4–2isthebooleantype.Infact,sortinganarrayofbooleanvaluesmakeslittlesense.However,theremaybeoccasionswhereyouneedtostorearatherlargenumberofbooleanvaluesandrefertothembyindex.Forthatpurpose,youcouldsimplycreateanarray.Whilethiswouldwork,thiswouldresultinmanybitsbeingwastedas8bitswouldbeallocatedforeachentryinthearraywhenactuallyabooleanvaluecanonlybetrueorfalse.Inotherwords,onlyonebitisneededtorepresentabooleanvalue.Forthatpurpose,theBitSetclasswasdefined:itallowsyoutostorebooleanvaluesinanarray(andallowsyoutorefertothembyindex)whileatthesametimeusingtheminimumamountofmemoryforthatarray(onebitperentry).IfyoulookatthepublicmethodsoftheBitSetclassanditsimplementationinBitSet.java,youmaynoticeafewthingsthatdeserveyourattention:
BitSet’sbackend后端isanarrayoflongvalues.Youmayachievebetterperformanceusinganarrayofintvalues.(Testsshowedagainofabout10%whenswitchingtoanintarray.)
Somenotesinthecodeindicatesomethingsshouldbechangedforbetterperformance(forexample,seethecommentstartingwithFIXME).
Youmaynotneedallthefeaturesfromthatclass.Forallthesereasons,itwouldbeacceptableforyoutoimplementyourownclass,possiblybasedonBitSet.javatoimproveperformance.4.2.4DefiningYourOwnClasses
Listing4–11showsaverysimpleimplementationthatwouldbeacceptableifthearray
doesnotneedtogrowafterthecreationoftheobject,andiftheonlyoperationsyouneedtoperformaretosetandgetthevalueofacertainbitinthearray,forexampleasyouimplementyourownBloom花filter.WhenusingthissimpleimplementationversusBitSet,testsshowedperformanceimprovedbyabout50%.WeachievedevenbetterperformancebyusingasimplearrayinsteadoftheSimpleBitSetclass:usinganarrayalonewasabout50%fasterthanusingaSimpleBitSetobject(thatis,usinganarraywas4timesfasterthanusingaBitSetobject).Thispracticeactuallygoesagainsttheencapsulation封装principleofobject-orienteddesignandlanguages,soyoushoulddothiswithcare.Listing4–11.DefiningYourOwnBitSet-likeClasspublicclassSimpleBitSet{privatestaticfinalintSIZEOF_INT=32;privatestaticfinalintOFFSET_MASK=SIZEOF_INT-1;//0x1Fprivateint[]bits;SimpleBitSet(intnBits){bits=newint[(nBits+SIZEOF_INT-1)/SIZEOF_INT];}voidset(intindex,booleanvalue){inti=index/SIZEOF_INT;into=index&OFFSET_MASK;if(value){bits[i]|=1<<o;//setbitto1}else{bits[i]&=~(1<<o);//setbitto0}}booleanget(intindex){inti=index/SIZEOF_INT;into=index&OFFSET_MASK;return0!=(bits[i]&(1<<o));}}
Alternatively另外,ifmostbitsaresettothesamevalue,youmaywanttouseaSparseBooleanArraytosavememory(possiblyatthecostofperformance).Onceagain,youcouldusetheStrategypatterndiscussedinChapter2toeasilyselectoneimplementationortheother.
Allinall,theseexamplesandtechniquescanbesummarizedasfollows:Whendealingwithlargeamountsofdata,usethesmallesttype用最小的数据类型possiblethatmeetsyourrequirements.Forexample,chooseanarrayofshortvaluesoveranarrayofintvalues,forbothperformanceandmemoryconsumptionreasons基于性能和空间考量.Usefloatinsteadofdoubleifyoudon’tneedtheextraprecision(anduseFloatMathclassifneeded).Avoidconversionsfromonetypetoanother.Trytobeconsistentanduseasingletypeinyourcomputations,ifpossible.Reinvent重建thewheelifnecessarytoachievebetterperformance如果有必要取得更好性能,推倒重来,butdoitwithcare.
Ofcourse,theserulesarenotsetinstone.Forexample,youmayfindyourselfinasituationwhereconvertingfromonetypetoanothercouldactuallygivebetterperformance,despitetheconversionoverhead类型转换后的性能超过开销.Bepragmatic务实andfixaproblemonlywhenyoudeterminethereisaone.Moreoftenthannot,usinglessmemoryisagoodruletofollow.Inadditiontosimplyleavingmorememoryavailableforothertasks,usinglessmemorycanimproveperformanceasCPUsusecachestoquicklyaccessdataorinstructions.4.3AccessingMemory访问内存
Aswesawearlier,manipulatinglargertypescanbemorecostlybecauseofthehighernumberofinstructionsinvolved指令较多.Intuitively此外,moreinstructionsoftenresultinlowerperformancesimplybecauseoftheextraworktheCPUhastoperformtoexecutethem.Inadditiontothat,codeanddatabothreside驻留inmemory,andaccessingmemoryitselfhasacost访问内存本身也有开销.
Becauseaccessingmemoryisacostlyoperation,aCPUcachesthememorythatwasrecentlyaccessed,whetheritwasmemorythatwasreadfromormemorythatwaswrittento.Infact,aCPUtypicallyusestwocachesorganizedinahierarchy层级:Level1cache(L1)Level2cache(L2)
TheL1cacheisthefasterbutalsothesmallerofthetwo.Forexample,theL1cachecouldbe64kilobytes(32kilobytesfordatacache,and32kilobytesforinstructioncache)whereasanL2cachecouldbe512kilobytes.
NOTE:SomeprocessorsmayalsohaveaLevel3cache,typicallyseveralmegabytes几兆字节insize,butyouwon’tfindthatonembeddeddevicesyet.
Whendataorinstructionscannotbefoundinacache,acachemissoccurs.Thisiswhendataorinstructionsneedtobefetched命中frommainmemory.Thereareseveralkindsofcachemisses:
Readmissininstructioncache
Readmissindatacache
Writemiss写未命中
Thefirsttypeofcachemissisthemostcritical最关键,astheCPUhastowaituntiltheinstructionisreadfrommemorybeforeitcanbeexecuted.Thesecondtypeofcachemisscanbeascriticalasthefirsttype,althoughtheCPUmaystillbeabletoexecuteotherinstructionsthatdonotdependonthedatabeingfetched.Thiseffectivelyresultsinanout-of-orderexecutionoftheinstructions(CPU指令乱序执行时出现).Thelasttypeofcachemissismuchlesscritical,astheCPUcantypicallycontinueexecutinginstructions.Youwillhavelittlecontroloverwritemisses几乎无法控制写为明证,butyoushouldnotworryaboutitmuch.Yourfocusshouldbeonthefirsttwotypes,whicharethekindsofcachemissesyouwanttoavoid.TheCache’sLineSize缓存行的大小
Besidesitstotalsize,anotherimportantpropertyofacacheisitslinesize.Eachentryinthecacheisaline,whichcontainsseveralbytes.Forexample,acachelineonaCortexA8L1cacheis64bytes(16words).Theideabehindthecacheandcachelineistheprincipleoflocality:ifyourapplicationreadsfromorwritestoacertainaddress,itislikelytoreadfromorwritetothesameaddress,oraclose-enoughaddressinthenearfuture.Forexample,thisbehaviorwasobviousinthe
implementationofthefindMin()andaddAll()methodsinListing4–9.
Thereisnoeasywayforyourapplicationtoknowthesizeofacacheandthesizeofacacheline.However,knowingthecachesexistandhavingsomeknowledgeabouthowcachesworkcanhelpyouwritebettercodeandachievebetterperformance.Thefollowingtipscanhelpyoutakeadvantageofthecachewithouthavingtorecoursetolow-leveloptimization不必诉诸底层的优化手段,asshowninChapter3withthePLDandPLIassemblyinstructions.Toreducethenumberofcachereadmissesfromtheinstructioncache:
CompileyournativelibrariesinThumbmode.ThereisnoguaranteethiswillmakeyourcodefasterthoughasThumbcodecanbeslowerthanARMcode(becausemoreinstructionsmayhavetobeexecuted).RefertoChapter2formoreinformationonhowtocompilelibrariesinThumbmode.
Keepyourcoderelativelydense保持代码相对密集.WhilethereisnoguaranteedenseJavacodewillultimatelyresultindensenativecode,thisisstillquiteoftenatrueassumption.
Toreducethenumberofcachereadmissesfromthedatacache:
Again,usethesmallesttypepossiblewhenstoringalargeamountofdatainarrays大量数据存储在数组中,使用尽可能小的数据类型.
Choosesequentialaccessoverrandomaccess.Thismaximizesthereuseofdataalreadyinthecache,andcanpreventdatafrombeingremovedfromthecacheonlytobeloadedinthecacheagainlater.防止数据中清除后再次载入
NOTE:ModernCPUsarecapableofprefetching预取memoryautomaticallytoavoid,oratleastlimit,
cachemisses.防止缓存未命中的情况
Asusual,applythesetipsonperformance-criticalsectionsofyourapplication在应用性能关键处使用这些代码,whichusuallyisonlyasmallpartofyourcode.Ontheonehand,compilinginThumbmodeisaneasyoptimizationthatdoesnotreallyincreaseyourmaintenanceeffort.Ontheotherhand,writingdensecodemaymakethingsmorecomplicatedinthelongrun.Thereisnoone-size-fits-alloptimization没有一个放之四海皆准的方法,andyouwillhavetheresponsibilityofbalancingthemultipleoptionsyouhave.
Whileyoudon’tnecessarilyhavecontroloverwhatgoesintothecache,howyoustructureanduseyourdatacanhaveanimpactonwhatendsupbeinginthecache,andthereforecanimpactperformance.Insomecases,youmaybeabletoarrangeyourdatainaspecificmannertomaximizecachehits,albeit虽然possiblycreatinggreatercomplexityandmaintenancecost.4.4
LayingOutYourData排布数据
Onceagain,theprincipleofencapsulation封装willbebroken.Let’sassumeyourapplicationneedstostorerecordsofsomesort,andeachrecordcontainstwofields:anidandavalue.Averyobject-orientedapproachistodefineaRecordclass定义一个记录类,asshowninListing4–12.Listing4–12.RecordClasspublicclassRecord{privatefinalshortid;privatefinalshortvalue;//andpossiblymorepublicRecord(shortid,shortvalue){this.id=id;this.value=value;}publicfinalshortgetId(){returnid;}publicfinalshortgetValue(){returnvalue;}publicvoiddoSomething(){//dosomethinghere}}
NowthattheRecordclassisdefined,yourapplicationcouldsimplyallocateanarray,savetherecordsinthatarray,andprovideadditionalmethods,asshowninListing4–13.Listing4–13.SavingRecordspublicclassMyRecords{privateRecord[]records;intnbRecords;publicMyRecords(intsize){records=newRecord[size];}publicintaddRecord(shortid,shortvalue){intindex;if(nbRecords<records.length){index=nbRecords;records[nbRecords]=newRecord(id,value);nbRecords++;}else{index=-1;}returnindex;}publicvoiddeleteRecord(intindex){if(index<0){//throwexceptionhere–invalidargument}if(index<nbRecords){nbRecords--;records[index]=records[nbRecords];records[nbRecords]=null;//don’tforgettodeletereference122CHAPTER4:UsingMemoryEfficiently}}publicintsumValues(intid){intsum=0;for(inti=0;i<nbRecords;i++){Recordr=records[i];if(r.getId()==id){sum+=r.getValue();}}returnsum;}publicvoiddoSomethingWithAllRecords(){for(inti=0;i<nbRecords;i++){records[i].doSomething();}}}
Allofthiswouldworkandwouldresultinaprettycleandesign.However,therearedrawbacks缺陷thatmaynotbevisibleuntilyouactuallyrunthecode:
Anewobjectiscreatedeverysingletimearecordisaddedtothearray.Whileeachobjectislightweight轻量级,memoryallocationsarestillsomewhatcostlyandcouldbeavoided.
CallstogetId()andgetValue()couldbeavoidedifidandvaluewerepublic.
IfyouareallowedtomodifytheRecordclass,makingidandvaluepublicisobviously
trivial简单.TheimplementationofsumValues()wouldthenbeslightlymodified,asshowninListing4–14.Listing4–14.ModifiedsumValues()publicintsumValues(intid){intsum=0;for(Recordr:records){if(r.id==id){sum+=r.value;}}returnsum;}
However,thisalonedoesnotreducethenumberofallocationsatall;recordobjectsstillneedtobecreatedasrecordsareaddedtothearray.NOTE:YoucouldavoidallocationseasilyinC/C++,butinJavaallobjectsareactuallyreferences引用andhavetobecreatedwiththenewoperator操作符.
Sinceallobjectsareallocatedintheheap,andyoucanonlystorereferencestoobjectsinthearray,youcanmodifytheMyRecordsclasstouseanarrayofshortvaluestoremovetheallocations.ThemodifiedclassisshowninListing4–15.Listing4–15.ModifiedMyRecordsClassUsingaShortArraypublicclassMyRecords{privateshort[]records;intnbRecords;publicMyRecords(intsize){records=newshort[size*2];}publicintaddRecord(shortid,shortvalue){intindex;if(nbRecords<records.length){index=nbRecords;records[nbRecords*2]=id;records[nbRecords*2+1]=value;nbRecords++;}else{index=-1;}returnindex;}publicvoiddeleteRecord(intindex){if(index<0){//throwexceptionhere–invalidargument}if(index<nbRecords){nbRecords--;records[index*2]=records[nbRecords*2];records[index*2+1]=records[nbRecords*2+1];}}publicintsumValues(intid){intsum=0;for(inti=0;i<nbRecords;i++){if(records[i*2]==id){sum+=records[i*2+1];}}returnsum;}publicvoiddoSomethingWithAllRecords(){Recordr=newRecord(0,0);for(inti=0;i<nbRecords;i++){r.id=records[i*2];r.value=records[i*2+1];r.doSomething();}}}
Let’simaginethat,lateron,youfindoutthesethingsabouthowtheMyRecordsclassisused:sumValues()iscalledmuchmoreoftenthandoSomethingWillAllRecords().Only
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年广西事业单位特殊岗位聘用合同实施细则
- 2025年度智能电网项目工程承包合同书
- 2025年度化妆品广告设计制作合同
- 2025年度智能交通管理系统采购与维护合同
- 2025年度拱门空飘安装与施工监理合同
- 2025年度借条续签合同范本:个人耐用消费品贷款合同续约
- 2025年度企业跨境贸易风险防范合同范本
- 2025年度草莓干线上线下融合营销推广合同
- 2025年度荒山林地油茶种植承包合同标准范本
- 2025年度环保印刷广告合作合同范本
- 2025江苏南京市金陵饭店股份限公司招聘高频重点提升(共500题)附带答案详解
- 公共政策分析 课件汇 陈振明 第0-9章 导论、绪论:政策科学的“研究纲领”- 政策监控
- 2025年牛津译林版英语七年级下册全册单元重点知识点与语法汇编
- 《小学作文指导》课件
- 小学六年级数学方程应用题100道及答案解析
- 《插画设计》课程标准
- 高考作文答题卡(作文)
- 在乡村治理中深化推广运用清单制、积分制、一张图工作方案
- GB/T 3921-2008纺织品色牢度试验耐皂洗色牢度
- 梅毒的诊断与治疗课件
- 工程伦理第二讲工程中的风险、安全与责任课件
评论
0/150
提交评论