Automaattinen muistinhallinta

Samankaltaiset tiedostot
Muistinsiivous. TIE448 Kääntäjätekniikka, syksy Antti-Juhani Kaijanaho. 30. marraskuuta 2009 TIETOTEKNIIKAN LAITOS. Muistinsiivous.

Luku 3. Muuttujat, arvot, oliot ja tyypit. 3.1 Arvot

11/20: Konepelti auki

Muistinhallinta ohjelmointikielissä

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

Sisällys. 7. Oliot ja viitteet. Olion luominen. Olio Java-kielessä

Concurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo

7. Oliot ja viitteet 7.1

Muistin siivous. Zoltán Varga

Objective-C. Ryhmä 35: Ilpo Kärki Aleksi Pälä

Osoitin ja viittaus C++:ssa

Tutoriaaliläsnäoloista

4.2 Muistinhallintaa avustava kirjasto Tutnew

List-luokan soveltamista. Listaan lisääminen Listan läpikäynti Listasta etsiminen Listan sisällön muuttaminen Listasta poistaminen Listan kopioiminen

Scheme-kesäkurssi luento 5

Esimerkkiprojekti. Mallivastauksen löydät Wroxin www-sivuilta. Kenttä Tyyppi Max.pituus Rajoitukset/Kommentit

Maastotietokannan torrent-jakelun shapefile-tiedostojen purkaminen zip-arkistoista Windows-komentojonoilla

Chapel. TIE Ryhmä 91. Joonas Eloranta Lari Valtonen

Prosessin reaalisaatioiden tuottaminen

Ohjelmointi 2. Jussi Pohjolainen. TAMK» Tieto- ja viestintäteknologia , Jussi Pohjolainen TAMPEREEN AMMATTIKORKEAKOULU

5. Luento: Rinnakkaisuus ja reaaliaika. Tommi Mikkonen,

Algoritmit 2. Luento 2 To Timo Männikkö

Ruby. Tampere University of Technology Department of Pervasive Computing TIE Principles of Programming Languages

Algoritmit 2. Luento 4 To Timo Männikkö

Algoritmit 1. Luento 6 Ke Timo Männikkö

Algoritmit 2. Luento 2 Ke Timo Männikkö

TKHJ:ssä on yleensä komento create index, jolla taululle voidaan luoda hakemisto

TIES542 kevät 2009 Suoraviivaohjelmat

Etsintä verkosta (Searching from the Web) T Datasta tietoon Heikki Mannila, Jouni Seppänen

Rakenteiset tietotyypit Moniulotteiset taulukot

MUISTINHALLINTA OHJELMOINTIKIELISSÄ

Ongelma(t): Jotta tietokone olisi mahdollisimman yleiskäyttöinen ja suorituskykyinen, niin miten tietokoneen resurssit tulisi tarjota ohjelmoijalle,

Algoritmi III Vierekkäisten kuvioiden käsittely. Metsätehon tuloskalvosarja 7a/2018 LIITE 3 Timo Melkas Kirsi Riekki Metsäteho Oy

Listarakenne (ArrayList-luokka)

Jaetun muistin muuntaminen viestin välitykseksi. 15. lokakuuta 2007

Rajapinnat ja olioiden välittäminen

2. Seuraavassa kuvassa on verkon solmujen topologinen järjestys: x t v q z u s y w r. Kuva 1: Tehtävän 2 solmut järjestettynä topologisesti.

Määrittelydokumentti

TIMMI-TILAVARAUSOHJELMISTO

Dynaaminen muisti. Pasi Sarolahti Aalto University School of Electrical Engineering. C-ohjelmointi Kevät 2017.

Muistinhallinta siivousmenetelmien avulla

Integrointialgoritmit molekyylidynamiikassa

2 Konekieli, aliohjelmat, keskeytykset

Sisällys. 18. Abstraktit tietotyypit. Johdanto. Johdanto

11. Javan toistorakenteet 11.1

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. IX Suunnittelumallit Proxy, Factory Method, Prototype ja Singleton

Tietojenkäsittelyn perusteet 2. Lisää käyttöjärjestelmistä

Tietorakenteet ja algoritmit

4. Luento: Prosessit ja säikeets. Tommi Mikkonen,

Algoritmit 1. Luento 10 Ke Timo Männikkö

Tehtävän V.1 ratkaisuehdotus Tietorakenteet, syksy 2003

Kopioi cd-levyt kiintolevylle, niin fyysiset levyt joutavat eläkkeelle.

UML -mallinnus TILAKAAVIO

Käyttöohje. Boa Open Access. Helsinki Ohjelmistotuotantoprojekti HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos

samalla seuraavaan puoliavaruuteen (sukupolveen), jota siivotaan harvemmin.

Ohjelmoinnin perusteet Y Python

Sisällys. 11. Javan toistorakenteet. Laskurimuuttujat. Yleistä

Satunnaisalgoritmit. Topi Paavilainen. Laskennan teorian opintopiiri HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos

Dynaaminen muisti Rakenteiset tietotyypit

12. Javan toistorakenteet 12.1

Uuden tilikarttaversion käyttöönotto

Asetusvalikossa voidaan määrittää erilaisia tulostimen ominaisuuksia. Lisätietoja saat valitsemalla valikon vaihtoehdon:

Algoritmit 2. Luento 13 Ti Timo Männikkö

Algoritmit 2. Demot Timo Männikkö

Käyttöjärjestelmät: prosessit

18. Abstraktit tietotyypit 18.1

Algoritmit 1. Luento 4 Ke Timo Männikkö

ELM GROUP 04. Teemu Laakso Henrik Talarmo

SA / Opiskelijat / Korvaavuus

12. Javan toistorakenteet 12.1

Käännös, linkitys ja lataus

Oodilla on kaksi tukipuhelinnumeroa ja kaksi sähköpostiosoitetta. WinOodi -asiat: Puh

Opetussuunnitteluprosessi WebOodissa - OpasOodi

Ongelma(t): Miten tietokoneen käyttöjärjestelmä toimii sisäisesti, jotta resurssit saadaan tehokkaaseen käyttöön?

Version päivittäminen

Ohjelmointi 2 / 2008 Välikoe / Pöytätestaa seuraava ohjelma.

Hakupuut. tässä luvussa tarkastelemme puita tiedon tallennusrakenteina

Luento 3. Timo Savola. 7. huhtikuuta 2006

811312A Tietorakenteet ja algoritmit Kertausta jälkiosasta

1 eportfolio Kyvyt.fi - palvelun käytön aloittaminen

Teoria. Prosessin realisaatioiden tuottaminen

Arkkitehtuurien tutkimus Outi Räihä. OHJ-3200 Ohjelmistoarkkitehtuurit. Darwin-projekti. Johdanto

C++11 lambdat: [](){} Matti Rintala

Algoritmit 1. Luento 7 Ti Timo Männikkö

Harjoitustyö: virtuaalikone

Opettajan ohje kypsyysnäytteen toteuttamiseen ja arvioimiseen sähköisenä tenttinä

Työssäoppiminen ja sen kopiointi Wilmassa Wilmaohje Turun ammatti-instituutti Sami Mäkelä

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

Ohjelmoinnin perusteet Y Python

Ohjelmoinnin perusteet Y Python

Ohjelmistojen mallintaminen viikon 4 laskareiden mallivastauksia

Kooste. Esim. Ympyrän keskipiste voidaan ajatella ympyrän osaksi.

Sisältö. C-ohjelmointi Luento 5: Osoittimet. Keko (heap) Pino (stack) Muistinhallinta Java vs C. Prosessin rakenne

Automaattitilausten hallinta

Luku 6. Dynaaminen ohjelmointi. 6.1 Funktion muisti

Automaattitilausten hallinta. Automaattitilauksien uudistettu käsittely

Algoritmit 1. Luento 10 Ke Timo Männikkö

Jypelin käyttöohjeet» Miten saan peliin pistelaskurin?

Muistimoduulit. Käyttöopas

Osio 2: Luennot 4-7 Muistinhallinta

Transkriptio:

Automaattinen muistinhallinta Timo Tapanainen (ttapanai@cs.helsinki.fi) Helsinki 12. huhtikuuta 2004 HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos

Sisältö 1 Johdanto...1 2 Automaattinen muistinhallinta...1 3 Roskienkeruu viitelaskurilla...2 4 Jäljittävä roskienkerääjät...3 4.1 Merkitse ja lakaise...3 4.2 Merkkaa ja tiivistä...3 4.3 Kopioiva kerääjä...4 5 Inkrementaalinen roskienkeruu...5 6 Sukupolvellinen roskienkeruu...5 7 Yhteenveto...6

1 1 Johdanto Dynaamisen muistin (keon) hallinta on monissa systeemi tason ohjelmointikielissä jätetty ohjelmoijan vastuulle. Ohjelmoijan täytyy eksplisiittisesti vapauttaa käyttämätön varattu muisti. Tällaista muistinhallintaa, jossa ohjelmoija on vastuussa muistinhallinnasta, kutsutaan mm. eksplisiittiseksi muistinhallinnaksi. Eksplisiittinen muistinhallinta vaatii ohjelmoijalta paljon ja siinä epäonnistuminen johtaa vaikeasti löydettäviin virheisiin. Varatun muistin vapauttamatta jättäminen johtaa muistivuotoon. Muistivuoto tarkoittaa sitä että muistin allokoija ei pysty tarjoamaan ohjelmalle vuotanutta muistia uudelleen, jolloin vaarana on muistin loppuminen. Muistin liian aikainen vapauttaminen johtaa taas roikkuvaan viitteeseen (dangling reference), jossa ohjelmalla on viite jo vapautettuun muistialueeseen. Roikkuvan viitteen käyttö johtaa odottamattomiin muutoksiin toisaalla ohjelmassa jos tuo vapautettu muistialue on otettu ohjelmassa uudelleen käyttöön. Muistivuotojen ja roikkuvien viitteiden korjaaminen on todella hankalaa niiden epäsäännöllisyyden vuoksi. Ne voivat ilmaantua esim. vasta kun ohjelma on ollut käynnissä kauan tai kun ohjelma on siirretään toiseen ympäristöön. Vaikka ohjelmoija muistaisikin vapauttaa varatun muistin, on tehtävä vielä päätös milloin ja missä tuo vapauttaminen tehdään. Koska ohjelmat ovat nykyään modulaarisia ei voida välttyä siltä että moduulien välillä välitetään olioviitteitä. Jotta muisti voitaisiin vapauttaa on tiedettävä varmasti että millään moduuleista ei enää ole viitettä vapautettavaan muistialueeseen. Näin muistin vapauttajan on tunnettava muiden moduulien toiminta jotta vapauttaminen olisi turvallista. Tämä lisää moduulien välistä riippuvuutta ja johtaa joskus myös hyvän ohjelmointitavan rikkomuksiin. Olioiden kopioiminen moduulien välillä on näistä yksi. 2 Automaattinen muistinhallinta Automaattisessa muistinhallinnassa ohjelmoija on vapautettu dynaamisen muistin hallinnasta. Ohjelmoijan ei tarvitse vapauttaa varaamaansa muistia, vaan tämä hoidetaan automaattisesti ajoaikaisen ympäristön toimesta. Muistin vapauttamisesta vastaa niin sanottu roskienkerääjä (garbage collector). Roskienkerääjän toiminta

2 perustuu keon objektien saavutettavuuteen eli siihen onko ohjelman nykytilasta vielä mahdollista päästä käsiksi keon objekteihin. Kaikki saavuttamattomissa olevat objektit ovat roskia ja ne voidaan poistaa roskienkerääjän toimesta. Roskienkerääjän toiminta voidaan jakaa kahteen loogiseen vaiheeseen. Ensimmäisessä vaiheessa roskienkerääjä erottelee saavutettavat objektit saavuttamattomista ja toisessa vaiheessa se poistaa saavuttamattomissa olevat objektit. Seuraavissa luvuissa tarkastellaan erilaisia roskienkeruu -algoritmeja. Luvussa kolme esitellään algoritmi jossa objektien saavutettavuus perustuu viitelaskureihin. Luvussa neljä tarkastellaan algoritmeja jotka päättelevät saavutettavuuden jäljittämällä. Luvussa viisi ja kuusi tarkastellaan mahdollisia laajennuksia roskienkeruu algoritmeihin. 3 Roskienkeruu viitelaskurilla Viitelaskuri tekniikassa objektien saavutettavuus päätellään objektiin liitetyn viitelaskurin perusteella. Viitelaskuri kertoo kuinka monta viitettä ohjelmasta on kyseiseen objektiin. Kun objektiin osoittava viite luodaan tai kopioidaan, kasvatetaan viitelaskuria ja vastaavasti viitteen poistaminen vähentää laskuria. Kun laskuri saavuttaa nollan, voidaan objekti poistaa. Ennen objektin poistamista on kuitenkin mukautettava sen viittaamien objektien viitelaskureita. Poistaminen voi siis johtaa lumivyöryn omaiseen objektien poistamiseen. Viitelaskureihin perustuvilla roskienkerääjillä on monia hyviä ominaisuuksia. Niiden toiminta on tyyliltään inkrementaalista, missä roskien kerääminen suoritetaan pienissä erissä. Tällöin roskien keruu on nopeaa ja se aiheuttaa yleensä vain pienen viiveen ohjelman suoritukseen. Tämä on toivottu ominaisuus etenkin reaaliaika sovelluksissa, missä pyritään suorituksen ennustettavuuteen. Viitelaskureiden käytössä on myös omat ongelmansa. Viitelaskuri tekniikalla ei pystytä vapauttamaan syklisiä rakenteita ja sitä vaivaa tehottomuus lyhyissä metodeissa. Välitettäessä kekoon osoittavia parametreja, on viitelaskureiden arvoja kasvatettava. Kun metodi päättyy, on näiden arvoja taas vähennettävä. Tämä voi aiheuttaa suhteettoman suuren kustannuksen muuten nopeissa metodeissa. Tähän on ehdotettu ratkaisuksi viivästettyjä viitelaskureita.

3 4 Jäljittävä roskienkerääjät Jäljittävässä roskienkeruussa objektien saavutettavuus päätellään ohjelman muistialueista tutkimalla. Muistialueista etsitään kekoon osoittavia viitteitä objektien saavutettavuuden selvittämiseksi. Etsintä aloitetaan niin sanotusta juuri joukosta (root set), joka käsittää staattiset muistialueet, pinon ja rekisterit. Kun näistä muistialueista löydetään kekoon osoittava viite, merkitään viitattu objekti saavutetuksi ja jatketaan muiden viitteiden etsintää juuri joukosta tai saavutetuista objekteista. Kun kaikki viittaukset on käyty läpi, voidaan kaikki saavuttamattomat objektit poistaa. Jäljittävillä roskienkerääjillä saavutettavien objektien löytäminen perustuu yllä mainittuun tapaan. Erot löytyvät lähinnä siitä miten saavuttamattomien objektien poistaminen tapahtuu. Seuraavissa aliluvuissa tarkastellaan jäljittäviä roskienkerääjiä, joilla on erilainen tapa roskien poistamiseen [Wil94]. 4.1 Merkitse ja lakaise Merkitse ja lakaise (mark-sweep) roskienkerääjä on yksinkertaisin jäljittävistä roskienkerääjistä. Merkintä vaiheessa kaikki saavutetut objektit merkitään lakaisu vaihetta varten. Lakaisu vaiheessa koko keko käydään läpi ja kaikkien merkitsemättömien objektien tila vapautetaan. Vapauttaminen tarkoittaa käytännössä sitä että vapautettava muistialue on jotenkin merkittämä allokoijan vapaiden muistialueiden listaan. Merkitse ja lakaise algoritmin suurimmat vaikeudet liittyvät muistin allokoijan toimintaan. Allokoijan on tasapainoiltava nopeuden ja muistin pirstoutumisen suhteen. 4.2 Merkkaa ja tiivistä Merkitse ja tiivistä (mark-compact) algoritmi ratkaisee merkkaa ja lakaise -algoritmin allokoijaan liittyvät ongelmat. Kun saavutettavat objektit on merkitty, tiivistetään keko kopioimalla merkityt objektit yhtenäiseksi muistialueeksi ja päivitetään muistialueiden viitteet osoittamaan objektien uusiin paikkoihin. Tiivistetty keko ei vaadi yhtä monimutkaista allokoijaa kuin merkkaa ja lakaise -algoritmissa, sillä nyt muistia voidaan varata lineaarisesti tiivistetyn keon päältä. Allokointi on siis erittäin nopeaa ja muisti ei pirstaloidu.

4 Merkkaa ja tiivistä algoritmin heikkoutena on mahdollinen hitaus. Algoritmi vaatii suoriutuakseen ainakin kolme keon läpikäyntiä. Merkkaus vaiheen jälkeen määritellään objektien uudet osoitteet ja kolmannella kerralla tehdään varsinainen kopiointi ja viitteiden päivitys määritettyjen osoitteiden mukaan. 4.3 Kopioiva kerääjä Kopioiva kerääjä (copy collector) tiivistää keon kuten merkkaa ja tiivistä -algoritmi, mutta siinä ei käytetä erillistä merkkaus vaihetta. Kopioivaa kerääjää käytettäessä keko on jaettu kahteen yhtenäiseen puoliavaruuteen (semispace): lähdeavaruuteen (fromspace) ja kohdeavaruuteen (tospace). Muistin varaukset tehdään vain lähdeavaruudesta. Kun lähdeavaruudesta ei kyetä enää varaamaan muistia, suoritetaan kopioiva kerääjä. Kopioiva kerääjä kopioi kaikki lähdealueen saavutettavat objektit kohdeavaruuteen. Kopioinnin jälkeen kohdeavaruus asetetaan lähdeavaruudeksi jonka jälkeen voidaan ohjelman suoritusta jatkaa. Kopioiva kerääjä siis käytännössä tiivistää keon puolikkaan keon toiseen puolikkaaseen. Kuten merkkaa ja tiivistä - algoritmissäkin, on ohjelman viitteet päivitettävä osoittamaan keon objektien uusiin paikkoihin. Yksinkertaisimpia kopioivan kerääjän toteutukset perustuvat Cheneyn algoritmiin [Che70]. Algoritmin ensimmäisessä vaiheessa käydään läpi juuri joukko, josta etsitään viitteitä kekoon. Kun viite löydetään, kopioidaan viitteen osoittama objekti lähdealueelta kohdealueelle, merkitään tuon objektin lähdealueelle edelleenvälitysosoitin (forwarding pointer) ja päivitetään viite osoittamaan objektin uuteen osoitteeseen. Edelleenvälitysosoitin sisältää merkinnän objektin siirrosta ja uuden objektin osoitteen. Kun algoritmissa kohdataan edelleenvälitysosoitin, riittää kun käsiteltävä viite päivitetään edelleenvälitysosoittimen sisältämällä osoitteella. Kun ensimmäinen vaihe on suoritettu, on kohdealueelle kopioitu kaikki juuri joukon suoraan osoittamat objektit. Seuraavassa vaiheessa viitteiden etsintää jatketaan kohdealueelta. Kohdealueen alusta edetään muistipaikka kerralla kohti kohdealueen loppua ja kun viite kohdataan, suoritetaan samat toimenpiteet kuin juuri joukon viitteen käsittelyssä. Kun kohdealueen viimeisen objektin viimeinen muistipaikka on käsitelty, on kaikki saavutettavat objektit kohdealueella ja kohdealueen vaihto lähdealueeksi voidaan tehdä.

5 5 Inkrementaalinen roskienkeruu Jäljittävät roskienkerääjät suorittavat roskienkeruun kokonaisuudessaan yhdessä vaiheessa. Kun allokoija ei pysty suorittamaan muistin varausta, käynnistetään roskienkerääjä. Roskienkeruun jälkeen allokoijalla on taas riittävästi vapaata muistia varauksen suorittamiseen, jonka jälkeen ohjelman suoritus jatkuu. Roskienkeruun aiheuttama viive on erityisen ongelmallinen reaaliaika sovelluksille. Tämän ongelman ratkaisemiseksi on kehitetty inkrementaalisia roskienkerääjiä, jotka suorittavat roskienkeruun pienissä osissa. Tämä aiheuttaa ohjelmalle useampia pysähdyksiä, mutta nämä ovat lyhyitä. Inkrementaalisissa roskienkerääjissä ohjelman ja roskienkerääjän toiminta on limittäistä. Tällöin on huolehdittava että ohjelman tekemät muutokset objekteihin huomioidaan roskienkeruussa. Jos esimerkiksi roskienkerääjä on käsitellyt objektin A, jonka jälkeen se siirtyy käsittelemään A:n osoittamia objekteja B ja C. Jossain vaiheessa palataan suorittamaan ohjelmaa, joka muuttaa A:n viittauksen C:hen viittaukseksi muualta saavuttamattomaan objektiin D. Jos roskienkerääjä ei havaitsisi A:n muuttumista, se poistaisi objektin D, jolloin ohjelmalla olisi roikkuva viite. C:n poistamatta jättäminen ei haittaisi sillä se poistettaisiin seuraavalla roskienkeruu kerralla. Roskienkerääjän ja ohjelman toiminnan koordinoimiseen käytetään luku ja kirjoitus esteitä. Käytännössä näitä tekniikoita käyttämällä roskienkerääjä havaitsee ohjelman tekemät muutokset muistialueille. 6 Sukupolvellinen roskienkeruu Sukupolvelliset roskienkerääjät jakavat keon eri sukupolviin. Uudet objektit allokoidaan nuorimmasta sukupolvesta ja kun tuo sukupolvi on täynnä, suoritetaan sille roskienkeruu. Kun nuorimman sukupolven objektit ovat selvinneet tietystä määrästä roskienkeruuta, siirretään ne seuraavaan sukupolveen. Sukupolvien täyttyminen siis laukaisee roskienkeruun, jolloin on mahdollista että objektit siirtyvät vanhempiin sukupolviin. Keon jakaminen sukupolviin tehostaa roskienkeruuta, koska tarkasteltavana on kulloinkin vain yksi sukupolvi. Lisäksi etuna on lyhyt ikäisten objektien tehokas roskienkeruu, koska nuorin sukupolvi tarkistetaan useimmin. Sukupolvien käyttö on yleistä kopioivissa roskienkerääjissä, koska ne vähentävät kopioinnin määrää.

6 7 Yhteenveto Tässä dokumentissa esiteltiin roskienkeruussa käytetyt perusalgoritmit. Viitelaskureihin perustuvat roskienkerääjät päättelevät objektien saavutettavuuden viitelaskureita käyttämällä. Viitelaskureita käyttävien roskienkerääjien toiminta on inkrementaalista mikä on erityisesti reaaliaika sovelluksissa haluttua. Viitelaskureiden suurin heikkous on kyvyttömyys poistaa syklisiä rakenteita. Jäljittävät roskienkerääjät päättelevät objektien saavutettavuuden juuri joukon viitteitä seuraamalla. Näistä merkitse ja lakaise -algoritmi aiheuttaa keon pirstaloitumista ja hidastaa sekä monimutkaistaa allokoijan toimintaa. Kopioivat roskienkerääjät eivät kärsi edellä mainituista ongelmista, mutta niiden toiminta on hitaampaa objektien kopioimisen ja viitteiden päivittämisen vuoksi. Kopioivien roskienkerääjien toimintaa voidaan kuitenkin tehostaa jakamalla keko sukupolviin.

7 Viitteet [Che70] [Wil94] C. J. Cheney. A nonrecursive list compacting algorithm. Communications of the ACM, 13(11):677 678, 1970. Paul R. Wilson. Uniprocessor garbage collection techniques. Technical report, University of Texas, January 1994.