hold din flash - hukommelse af stabil med formål at samle projekterne

, hold din flash - projektet er hukommelse af stabil med objekt pooling,,,,, 1,,,,,,,,, 35,,,,,,, det cyber - mandag envato tuts + kurser vil blive reduceret til $3.- og' t miss.,, hukommelse anvendelse er et aspekt af udvikling, som du virkelig nødt til at være forsigtige med, eller det vil sløve din app, der tager en masse hukommelse eller endog bryder alt.denne lektion vil hjælpe dig med at undgå disse dårlige potentielle resultater.,,,, endelige resultat forpremiere, lad os tage et kig på det endelige resultat, vi arbejder hen imod:,, klik på det tidspunkt at skabe fyrværkeri virkning, og hold øje med mindet profiler i øverste venstre hjørne.,, trin 1: indførelse, hvis du nogensinde har profileret din ansøgning. ved hjælp af profileringsredskab eller anvendes en kode eller bibliotek, der fortæller dig det nuværende hukommelse anvendelse af din ansøgning, du har bemærket, at mange gange mindet anvendelse går op, og så går ned igen, hvis du ikke har din kode er superb!). - selv om disse stænger forårsaget af stor hukommelse brug ser kinda cool, er det ikke en god nyhed for deres anvendelse eller (derfor) deres brugere.bliv ved at forstå, hvorfor dette sker, og hvordan man undgår det.,, trin 2: god og dårlig anvendelse af billedet nedenfor, er et godt eksempel på dårlig hukommelse forvaltning.det er fra en prototype af en kamp.du skal se to vigtige ting: den store pigge på hukommelse anvendelse og mindet af peak.højdepunktet er næsten på 540mb!det betyder, at denne prototype være nået ved hjælp af 540mb af brugerens edb - ram - og det er noget, du helt sikkert vil undgå, er dette problem begynder, når du begynder at skabe en masse ting tilfælde i din ansøgning.uudnyttede tilfælde vil fortsætte med deres ansøgning er hukommelse, indtil en skraldemand løber, når de bliver deallocated - forårsager store spyd.en endnu værre situation opstår, når de tilfælde, vil ikke få deallocated, at deres ansøgning er hukommelse til praksis, bliver ved med at vokse, indtil noget uheld eller pauser.hvis du vil vide mere om dette problem, og at undgå den, læs det her hurtigt tip om skrald samling. i denne forelæsning, vil vi ikke løse nogen skraldemand spørgsmål.vi skal i stedet arbejde på at opbygge strukturer, som effektivt hold objekter i erindring, at dens anvendelse helt stabil, og således at de skraldemand fra rensning af hukommelse, at gennemførelsen hurtigere.tag et kig på hukommelsen anvendelse af samme model, men denne gang optimeret med teknikker vist her:,, al denne forbedring kan opnås ved hjælp af formål at samle.læs om at forstå, hvad det er, og hvordan det fungerer,.,, trin 3: pooler, formål at samle er en teknik, hvor et på forhånd fastsat antal objekter er oprettet, når ansøgningen er igangsat, og holdes i erindring under hele gennemførelsen levetid.formålet med pool giver objekter, når ansøgningen om dem, og nulstiller objekterne tilbage til den oprindelige tilstand, når ansøgningen er færdig med dem.der findes mange typer af objekt puljer, men vi vil kun se på to af dem: den statiske og dynamiske objekt pools., statisk objekt pool skaber et bestemt antal genstande og kun holder det beløb af genstande i hele anvendelsen liv.hvis en indsigelse er blevet anmodet om, men den pool, allerede har givet alle de genstande, poolen er tilbage for.ved anvendelse af denne slags pulje, er det nødvendigt at tage fat på spørgsmål såsom anmoder om en genstand, og får noget tilbage. den dynamiske objekt pool skaber også et bestemt antal genstande på initialization, men når et objekt er anmodet om, og poolen er tom, poolen skaber en anden instans automatisk og returnerer det objekt, øge den pool størrelse og tilføjelse af nye mål for det. i denne forelæsning vil vi bygge en enkelt ansøgning, der genererer partikler, når brugeren klik på skærmen.disse partikler har en begrænset levetid, og så vil blive fjernet fra skærmen, og vendte tilbage til poolen.for at gøre det, vil vi først skaber denne ansøgning uden genstand, sammenlægning og kontrollere hukommelse anvendelse, og derefter gennemføre formålet pool og sammenligne hukommelse anvendelse før.,, trin 4: første ansøgning, åben flashdevelop (se vejledningen) og skabe en ny as3 projekt.vi vil bruge en enkelt lille farvede. som partikel image, som vil blive udarbejdet med kode og vil bevæge sig i henhold til en tilfældig vinkel.skabe en ny klasse, som hedder partikel, der udvider sprite.jeg går ud fra, at du kan klare oprettelsen af en partikel, og fremhæve de aspekter, der vil følge de - partikel levetid og fjernelse fra skærmen.du kan få den fulde kildekode af denne forelæsning på toppen af side, hvis du har problemer med at skabe de - partikel. private var _lifetime: int; offentlige funktion ajourføring (timepassed: uint): ugyldig (//at partikel flytte x + = matematik. - (_angle) * _speed * timepassed /1000; y + = matematik. synd (_angle) * _speed * timepassed /1000; //små lettelser til bevægelse ser ret _speed - = 120 * timepassed /1000; //tager sig af liv og fjernelse _lifetime - = timepassed; hvis (_lifetime < = 0) (forælder. removechild (det);), kode ovenfor er den kode, der er ansvarlig for partikel er fjernet fra skærmen.vi skaber en variabel, _lifetime, at begrænse antallet af miliseconds, at partikler vil være på skærmen.- påbegynd udeblivelsesdom dens værdi til 1000 om entreprenøren.det, update(), funktion kaldes hvert billede og modtager de beløb, miliseconds, der gik fra rammer, således at det kan nedsætte partikel levetid værdi.når denne værdi til 0 eller mindre partikel automatisk anmoder sine forældre for at fjerne den fra skærmen.resten tager sig af de - partikel er bevægelighed. nu skal vi gøre en masse af de opstår, når et klik med musen er opdaget.gå til vigtigste.: private var _oldtime: uint; private var _elapsed: uint; private funktion lokalitet (e: begivenhed = null): ugyldig (removeeventlistener (event.added_to_stage, lokalitet); //indgangssted fase. addeventlistener (mouseevent.click, createparticles); addeventlistener (event.enter_frame, updateparticles); _oldtime = gettimer();} privat funktion updateparticles e: begivenhed): ugyldig (_elapsed = gettimer() - _oldtime; _oldtime + = _elapsed; (var - jeg: int = 0. jeg < numchildren; jeg + +) (hvis (getchildat (i) er partikel) (partikel (getchildat (i) ajourføring (_elapsed)).;}}} privat funktion createparticles e: mouseevent): ugyldig (for (var - jeg: int = 0. jeg < 10 - + +) (addchild (nye partikel (stage.mousex, fase.mousey)}}, koden for ajourføring af partikler skal være bekendt: det er rødderne af en simpel tidsbaseret loop, der almindeligvis anvendes i spil.glem ikke de import - erklæringer:, import flash.events.event; import flash.events.mouseevent; import flash. utils. gettimer;, nu kan du teste din ansøgning og profil ved hjælp af flashdevelop er indbygget profiler.og nogle gange på skærmen.her er, hvad min hukommelse anvendelse lignede:,, jeg klikkede indtil skraldemand begyndte at løbe.den ansøgning, der er skabt i 2000 partikler, der er indsamlet.er det begyndt at ligne mindet udnyttelse af prototype?det ligner det, og det er bestemt ikke godt.for at gøre arbejde lettere, vil vi tilføje den nytte, som blev nævnt i det første skridt.her er koden til at tilføje, i de vigtigste.:, privat funktion lokalitet (e: begivenhed = null): ugyldig (removeeventlistener (event.added_to_stage, lokalitet); //indgangssted fase. addeventlistener (mouseevent.click, createparticles); addeventlistener (event.enter_frame, updateparticles); addchild (nye stats()); _oldtime = gettimer();} glem ikke at indføre, net.hires.debug.stats, og den er klar til at blive brugt.,, løntrin 5: definition af en poolable objekt, anvendelse, vi byggede i trin 4 var ret simpelt.det var kun en enkelt partikel virkning, men skabte en masse problemer i hukommelsen.i dette skridt, vil vi begynde at arbejde på en genstand pool for at ordne det problem. det første skridt hen imod en god løsning er at tænke på, hvordan ting kan forenes, uden problemer.i en genstand pool, må vi altid sørge for, at de mål, der er klar til brug, og at den ting tilbage, er fuldstændig "isoleret fra resten af anvendelsen (dvs. indeholder ingen henvisninger til andre ting.for at tvinge hver samlet mod til at kunne gøre det, skal vi skabe et interface,.denne grænseflade definerer to vigtige funktioner, at målet må være, renew(), og destroy(),.på den måde kan vi altid kalde disse metoder uden at bekymre sig om, hvorvidt formålet har dem (fordi den vil have).det betyder også, at enhver genstand, vi ønsker at forene skal gennemføre denne grænseflade.så her er det:, pakke (offentlig grænseflade ipoolable {funktion bliver destroyed(): boolean; funktion renew(): ugyldig; funktion destroy(): ugyldig;}}, da vores partikler vil blive poolable, vi får dem til at gennemføre, ipoolable,.vi flytter alle koden fra deres atomkraftværker til, renew(), funktion og fjerne eventuelle eksterne henvisninger til formålet i, destroy(), funktion.her er, hvad det skal ligne: /* grænseflade ipoolable * /offentlige funktion bliver destroyed(): boolean {tilbage _destroyed;} offentlig funktion renew(): ugyldig (hvis (!_destroyed) {tilbage;} _destroyed = falske grafik. beginfill (uint (matematik. random() * 0xffffff), 0, 5 + (matematik. random() * 0, 5) grafik. drawrect (- 1,5 - 1,5, 3, 3); grafik. endfill(); _angle = matematik. random() * math.pi * 2. _speed = 150; //pixel pr. sekund _lifetime = 1000; //miliseconds} offentlig funktion destroy(): ugyldig (hvis (_destroyed) {tilbage;} _destroyed = sandt, grafik. clear();}, konstruktøren også burde ikke kræve nogen argumenter for mere.hvis du vil give nogen oplysninger til det formål, de bliver nødt til at gøre det gennem funktioner.på grund af den måde, som, renew(), funktion virker nu, er vi også nødt til at fastsætte, _destroyed, rigtigt, konstruktøren, således at den funktion, kan gennemføres, med det, vi netop har tilpasset vores, partikler, klasse til at opføre sig som en, ipoolable,.på den måde, den genstand, pool, vil være i stand til at skabe en pulje af partikler, trin 6: fra genstanden pool, er det nu på tide at skabe en fleksibel objekt pool, som kan samle nogen genstand, vi ønsker.denne pulje vil handle lidt ligesom en fabrik: i stedet for at bruge den nye nøgleord for at skabe ting, du kan bruge, vil vi i stedet kalde en metode i poolen, der vender tilbage til os et objekt. i forbindelse med enkelhed, objektet pool vil være en singleton.på den måde kan vi få adgang overalt i vores kodeks.start ved at skabe en ny klasse, som hedder "objectpool" og at tilføje den kode for at gøre det til en singleton:, pakke (offentlige klasse objectpool {menig static var _instance: objectpool, menig static var _allowinstantiation: boolean, offentlige statisk funktion bliver instance(): objectpool (hvis (!_instance) (_allowinstantiation = sandt. _instance = nye objectpool(); _allowinstantiation = falske} tilbage _instance;} offentlig funktion objectpool() (hvis (!_allowinstantiation) {kaste nye fejl ("prøver at instantiate en singleton!");}}}}, variable, _allowinstantiation, er kernen i denne singleton gennemførelse: det er privat, så kun de egen klasse kan ændre, og det eneste sted, hvor det bør ændres for at skabe de første tilfælde af det. vi skal nu beslutte, hvordan man holder puljer i denne klasse.fordi det vil være global (dvs. kan samle en genstand i din ansøgning), skal vi først komme med en måde at altid have et entydigt navn for hver pool.hvordan man gør det?der er mange måder, men det bedste, jeg har fundet indtil nu, er at anvende genstande "egen klasse navne som pool - navn.på den måde, vi kunne have en partikel "pool" fjende "pool, og så...men der er et andet problem.klasse navne kun skal være entydig i deres pakker, f.eks. en klasse "baseobject" inden for "fjender" pakke og en klasse "baseobject" inden for "struktur" pakke ville være tilladt.det ville give anledning til problemer i poolen, tanken om at anvende klasse navne som identifikatorer for puljer, stadig er stor, og det er her, flash. utils. getqualifiedclassname(), kommer til at hjælpe os.i denne funktion skaber en snor med fuld klasse navn, herunder eventuelle pakker.så nu kan vi bruge hver genstand er kvalificeret klasse navn som identifikator for deres respektive pools!det er, hvad vi vil gøre i det næste trin, trin 7: oprettelse af puljer, nu hvor vi har en måde at identificere puljer, det er tid til at tilføje den kode, der skaber dem.vores formål pool bør være fleksibel nok til at støtte både statisk og dynamisk puljer (, vi talte om det i fase 3, husker du?vi er også nødt til at være i stand til at opbevare størrelsen af hver pool, og hvor mange aktive genstande, der er i hver enkelt.en god løsning, for det er at skabe en privat lektion med alle disse oplysninger og opbevare alle pools i genstanden:, pakke (offentlige klasse objectpool {menig static var _instance: objectpool, menig static var _allowinstantiation: boolean; private var _pools: formål; offentlige statisk funktion bliver instance(): objectpool (hvis (!_instance) (_allowinstantiation = sandt. _instance = nye objectpool(); _allowinstantiation = falske} tilbage _instance;} offentlig funktion objectpool() (hvis (!_allowinstantiation) {kaste nye fejl ("prøver at instantiate en singleton!");) _pools = {}}}} klasse poolinfo {offentlige var poster: vector. < ipoolable > offentlige var itemclass: klasse; offentlige var størrelse: uint; offentlige var aktive: uint; offentlige var isdynamic: boolean, offentlig funktion poolinfo (itemclass: klasse, uint, isdynamic størrelse:: boolean = sandt) (this.itemclass = itemclass; poster = nye vektor. < ipoolable > (størrelse,!isdynamic); this.size = størrelse; this.isdynamic = isdynamic; aktive = 0, initialize();} privat funktion initialize(): ugyldig (for (var - jeg: int = 0. jeg < størrelse; jeg + +) {genstande [i] = nye itemclass();}}}, kode ovenfor giver private klasse, der indeholde alle oplysninger om en pool.vi gjorde det også, _pools, objekt til at holde alle objekt puljer.i det følgende vil skabe den funktion, der registrerer en pool i klassen: offentlig funktion registerpool (objectclass: klasse størrelse: uint = 1, isdynamic: boolean = sand): ugyldig (hvis (!(describetype (objectclass). implementsinterface. (@ type = "ipoolable"). length() > 0)) (kaste nye fejl ("kan ikke samle noget, der ikke gennemfører ipoolable!"); tilbage;} var qualifiedname: string = getqualifiedclassname (objectclass); hvis (!_pools [qualifiedname]) (_pools [qualifiedname] = nye poolinfo (objectclass, størrelse, isdynamic)}}, koden er lidt mere indviklet, men gå ikke i panik.- det er forklaret her.for det første, hvis udtalelse ser underligt ud.du har aldrig set disse funktioner, så her er, hvad det betyder:,, describetype() funktion skaber en xml - indeholder alle oplysninger om de ting vi har passeret den. i tilfælde af en klasse, det er indeholdt i, fabrik, tag. indenfor, xml - beskriver alle grænseflader, at klasse gennemfører med, implementsinterface, tag. har vi en hurtig søgning for at se, om det, ipoolable, grænseflade er blandt dem.hvis du er, så ved vi, at vi kan tilføje, at klasse til poolen, fordi vi vil være i stand til at afgive det som en, iobject,.,, kode efter denne kontrol giver en indrejse i, _pools, hvis man ikke allerede findes.efter det, poolinfo, konstruktøren kalder, initialize(), funktion inden for denne klasse, effektivt at skabe den pool med den størrelse, vi ønsker.det er nu klar til at blive brugt.,, trin 8: et objekt, i det sidste skridt, vi var i stand til at skabe den funktion, der registrerer et objekt pool, men nu er vi nødt til at få en genstand for at bruge det.det er meget enkelt: vi får en genstand, hvis puljen ikke er tomt og returnerer det.hvis den pool er tom, skal vi kontrollere, om det er dynamisk, hvis vi øger dets størrelse og skabe et nyt mål og returnerer det.hvis ikke, vi er.du kan også vælge at smide en fejl, men det er bedre at vende tilbage, for din kode arbejde omkring denne situation, når det sker.), her er den, getobj(), funktion: offentlig funktion getobj (objectclass: klasse): ipoolable {var qualifiedname: string = getqualifiedclassname (objectclass); hvis (!_pools [qualifiedname]) (kaste nye fejl ("kan ikke få en ting fra en pulje, der ikke er blevet registreret!"); tilbage;} var returnobj: ipoolable; hvis (poolinfo (_pools [qualifiedname]). aktive = = poolinfo (_pools [qualifiedname]). størrelse) (hvis (poolinfo (_pools [qualifiedname]). isdynamic) (returnobj = nye objectclass(); poolinfo (_pools [qualifiedname]). poolinfo størrelse + +. (_pools [qualifiedname]). punkter. tryk (returnobj)} {tilbage, for ellers;) andet (returnobj = poolinfo (_pools [qualifiedname]). punkter [poolinfo (_pools [qualifiedname]). aktive] returnobj. renew();} poolinfo (_pools [qualifiedname]). aktive + +. tilbage returnobj;}, i den funktion, som vi først kontrollere, at poolen eksisterer.hvis denne betingelse er opfyldt, vi undersøger, om den pool er tomme. hvis det er, men det er dynamisk, skaber vi et nyt mål, og der tilsættes i poolen.hvis puljen ikke er dynamisk, stopper vi den kode, der bare vende tilbage for.hvis poolen stadig har et objekt, får vi den genstand, nærmest begyndelsen af poolen og ring, renew(), om det.det er vigtigt: det er grunden til, at vi kalder, renew(), på en genstand, som allerede var i poolen, er at sikre, at dette mål vil blive givet på en "anvendelige" stat. du tænker sikkert på: hvorfor du ikke også anvende det cool kontrol med, describetype() i denne funktion?- svaret er enkelt:, describetype(), skaber en xml -, hver gang vi kalder det, så er det meget vigtigt at undgå oprettelsen af genstande, som bruger en masse hukommelse, og at vi ikke kan kontrollere.- kun for at tjekke, om poolen virkelig eksisterer, er nok: hvis klasse gik ikke gennemføre, ipoolable, betyder det, at vi ikke ville være i stand til at skabe en pool for det.hvis der ikke er en pool for det, så vi griber denne sag i vores, hvis erklæring i begyndelsen af funktion. nu kan vi ændre vores vigtigste klasse og anvende objekt pool!tjek det ud, privat funktion lokalitet (e: begivenhed = null): ugyldig (removeeventlistener (event.added_to_stage, lokalitet); //indgangssted fase. addeventlistener (mouseevent.click, createparticles); addeventlistener (event.enter_frame, updateparticles); _oldtime = gettimer(); objectpool. f.eks. registerpool (partikel, 200, sande)} private funktion createparticles e: mouseevent): ugyldig (var - tempparticle: partikel; (var - jeg: int = 0. jeg < 10 - + +) (tempparticle = objectpool. f.eks. getobj (partikel) som partikel. tempparticle. x = e.stagex; tempparticle. y = e.stagey; addchild (tempparticle);), ramte udarbejde og profil mindet anvendelse.her er, hvad jeg har:,,, det er ret cool, er det ikke?,, trin 9: tilbage objekter til poolen, vi har gennemført et objekt pool, som giver os objekter.det er fantastisk!men det er ikke slut endnu.vi er stadig kun få genstande, men aldrig vender tilbage til dem, når vi har ikke brug for dem mere.tid til at tilføje en funktion til at returnere objekter derinde, objectpool. som: offentlig funktion returnobj (mål: ipoolable): ugyldig (var - qualifiedname: string = getqualifiedclassname (mål); hvis (!_pools [qualifiedname]) (kaste nye fejl ("kan ikke returnere en genstand fra en pulje, der ikke er blevet registreret!"); tilbage;} var objindex: int = poolinfo (_pools [qualifiedname]). punkter. indexof (mål); hvis (objindex > = 0) (hvis (!poolinfo (_pools [qualifiedname]). isdynamic) (poolinfo (_pools [qualifiedname]). items.fixed = falske} poolinfo (_pools [qualifiedname]). punkter. splejsning (objindex, 1) mål nr. destroy(); poolinfo (_pools [qualifiedname]). punkter. tryk (mål); hvis (!poolinfo (_pools [qualifiedname]). isdynamic) (poolinfo (_pools [qualifiedname]). items.fixed = sandt.} poolinfo (_pools [qualifiedname]). aktive...;}}, lad os gå gennem funktion: den første er at kontrollere, om der er en pool af den genstand, der blev vedtaget.du er vant til at kode - den eneste forskel er, at vi nu er ved hjælp af et objekt i stedet for en time til at få kvalificeret navn, men det ændrer ikke på output). dernæst får vi indeks for det punkt i poolen.hvis det ikke er i poolen, vi bare ignorere det.når vi kontrollerer, at formålet er i poolen, må vi bryde vandet når formålet er i øjeblikket på og genindsætter målet ved udgangen af det.og hvorfor?fordi vi regner det brugte genstande fra begyndelsen af poolen, er vi nødt til at omorganisere poolen for at få alle tilbage og ubrugte objekter til udgangen af det.og det er, hvad vi gør i denne funktion. for statisk objekt puljer, skaber vi en vektor, genstand, der er fast længde.på grund af det, det kan vi ikke, splice(), og push(), ting tilbage.planen til dette, er at ændre de faste ejendom af disse, vektor, s, falske, fjerne objektet og lægger det tilbage, og så ændrer ejendom tilbage til sand.vi er også nødt til at reducere antallet af aktive objekter.efter det, vi har gjort, at objekt. nu har vi skabt den kode til at vende tilbage til en genstand, kan vi gøre vores partikler afkast sig til poolen, når de når til slutningen af deres levetid.indenfor, partikel. som: offentlige funktion ajourføring (timepassed: uint): ugyldig (//at partikel flytte x + = matematik. - (_angle) * _speed * timepassed /1000 år + = matematik. synd (_angle) * _speed * timepassed /1000; //små lettelser til flytning ser _speed - = 120 * timepassed /1000; //tager sig af liv og fjernelse _lifetime - = timepassed; hvis (_lifetime < = 0) (forælder. removechild (dette). objectpool. f.eks. returnobj (i)), bemærker, at vi har tilføjet en opfordring til, objectpool. f.eks.. returnobj() derinde.det er det, der gør den ting tilbage, sig til poolen.nu kan vi teste og profil vores app:,, og så går vi!stabil hukommelse, selv når hundredvis af kilometer blev foretaget.,, indgåelse, nu ved du, hvordan til at oprette og anvende en genstand pool for at holde din app 's hukommelse af stabile.klasse vi byggede bygget kan anvendes overalt, og det er simpelt at tilpasse deres kode til det: i begyndelsen af din app, skabe objekt pools for alle slags ting du pool, og når der er en ny, nøgleord (dvs. oprettelse af en instans), erstatter den med en ringe den funktion, der er genstand for dig.glem ikke at gennemføre de metoder, som den grænseflade, ipoolable, kræver.- din hukommelse af stabile, er meget vigtigt.det sparer en masse problemer senere i deres projekt, når det begynder at falde fra hinanden med ikke - genanvendt tilfælde stadig svarer til tilfælde lyttere, genstande, udfylder den hukommelse du har til rådighed til brug og med en skraldemand løber, og at alt ned.en god anbefaling er altid at bruge formål at samle fra nu af, og du ser dit liv bliver meget lettere, bemærker også, at selv om denne forelæsning var rettet mod flash, de koncepter, der er udviklet i det globale: du kan bruge det på air apps, mobile applikationer og andre steder, hvor det passer.tak for det!,

Bad memory usage
Good memory usage
Unhandled memory usage
Very good memory usage
Awesome memory usage



Previous:
Next Page: