On olemassa useita erinomaisia artikkeleita, joissa puhutaan optimointitekniikasta nimeltä memoization. Voit tutustua niihin täällä ja täällä. Me aiomme antaa sinulle lyhyen yleiskatsauksen siitä, mitä memoisaatio on. Menemme hieman pidemmälle analysoimalla askel askeleelta, mitä ”memoizing”-koodi oikeastaan tekee, rivi riviltä. Artikkelin lopussa ymmärrät memoisaation täysin.

Memoisaatio on ohjelmointikäytäntö, jolla saadaan pitkät rekursiiviset/iteratiiviset funktiot toimimaan paljon nopeammin.

Miten, kysyt? Välimuistiin tallentamalla arvot, jotka funktio palauttaa sen ensimmäisen suorituksen jälkeen.

Kun syötämme saman arvon memoistettuun funktioon, se palauttaa välimuistiin tallennetun arvon sen sijaan, että funktio suoritettaisiin uudelleen, mikä lisää suorituskykyä. Enää ohjelmasi ei tarvitse laskea jokaista lukua uudelleen saadakseen tuloksen.

Kuulostaa mahtavalta, eikö? No, vielä parempaa on se, että ei ole vaikea ymmärtää, mitä memoize-funktio tekee, kunhan pilkkoo koodin.

Tässä on esimerkki perusfunktiosta memo:

Aloitetaan alusta…

Palautamme niin sanotun anonyymin sulkemisen. Anonyymi sulkeutumisemme pystyy perimään minkä tahansa muuttujan tai tässä tapauksessa funktion, joka välitetään memo:een. Voimme sitten leikkiä argumenttiobjektilla, jonka välitetty funktiomme tarjoaa.

Sivuhuomautus: Jos siis jokaisella funktiolla on argumenttiobjekti, miksi emme peri memo:n argumenttiobjektia? Se johtuu siitä, että sulkeutuvat funktiot eivät pääsääntöisesti peri ulomman funktion argumenttiobjektia. Käytämme tätä sääntöä hyödyksemme leikitellessämme funktiolla, jonka haluamme memoida.

Kerrotaanpa tarkalleen, mitä memoidaatio tekee tarkastelemalla hyvin yksinkertaista ja epäkäytännöllistä esimerkkiä. Muuten, sinun kannattaa kopioida/liimata tämä koodi, tai mikä tahansa koodi muutenkaan, saadaksesi oikeasti tuntuman siitä, miten se toimii.

Luulempa, että ymmärsimme tämän koodiesimerkin ytimen. Se puhuu käytännössä itsestään. Tarkennetaan sitä vielä hieman tarkastelemalla tilannekuvaa todellisesta memofunktiosta:

Nyt kun olemme eritelleet, mitä memofunktio tekee, luodaan funktiolauseke ja syötetään rekursiivinen Fibonacci-funktio memo :iin ja katsotaan, mitä tapahtuu.

//Now we'll test our code!
// =======TEST=======
fib(10)//On the first try we need to load//=> loading…//=> loading…//=> loading…//=> loading…//=> loading…//=> 4 loadings later we get...//=> 89// And on the second try…fib(10)//=> 89//No loading! Yaay!//The cool thing about memoizing the recursive Fibonacci algorithm is that once we make a call for the value of the nth number in the series, we are able to store all the previous numbers in the series.//So if we try...
fib(7) //=> 21
//We don't have to recalculate anything.//And if we want to try fib(11)...
fib(11)
//loading...
//=> 144
//Our memoized recursive function already cached fib(1-10),so all it needed to do was to calculate the cached values. // This is what the cache now looks like:
/*
{ '{"0":0}': 1,
'{"0":1}': 1,
'{"0":2}': 2,
'{"0":3}': 3,
'{"0":4}': 5,
'{"0":5}': 8,
'{"0":6}': 13,
'{"0":7}': 21,
'{"0":8}': 34,
'{"0":9}': 55,
'{"0":10}': 89,
'{"0":11}': 144}
*/

Johtopäätös

Memofunktio demystifioidaan, kun se kiehautetaan avain-arvopareihin. Teemme vain objektin luomisen, tarkistamme olemassa olevat arvot, jotka vastaavat käyttäjän syötettä, ja tallennamme uudet avain-arvoparit, jos niitä ei ole objektissamme.

Kaiken tämän datan tallentaminen tarkoittaa tietysti sitä, että käytämme muistia. On parasta toteuttaa memoizointi funktioihin, jotka ovat puhtaita ja sisältävät raskaita, toistuvia laskutoimituksia.

Bonus:

Hauskuuden vuoksi tässä on funktionaalinen versio memoizeristämme:

Vastaa

Sähköpostiosoitettasi ei julkaista.