• No results found

Generationsskräpsamling med explicit kontroll av hårdvarucache

N/A
N/A
Protected

Academic year: 2021

Share "Generationsskräpsamling med explicit kontroll av hårdvarucache"

Copied!
37
0
0

Loading.... (view fulltext now)

Full text

(1)

Examensarbete

Generationsskr¨

apsamling med explicit

kontroll av h˚

ardvarucache

av

Karl-Johan Karlsson LITH-IDA-EX--06/044--SE

(2)
(3)

Examensarbete

Generationsskr¨

apsamling med explicit kontroll av

ardvarucache

av Karl-Johan Karlsson LITH-IDA-EX--06/044--SE

Handledare : Tobias Nurmiranta

Institutionen f¨or datavetenskap vid Link¨opings universitet

Examinator : Erik Sandewall

Institutionen f¨or datavetenskap vid Link¨opings universitet

(4)
(5)

Avdelning, Institution Division, Department Datum Date Spr˚ak Language 4 Svenska/Swedish 2 Engelska/English 2 Rapporttyp Report category 2 Licentiatavhandling 4 Examensarbete 2 C-uppsats 2 D-uppsats 2 Ovrig rapport¨ 2

URL f¨or elektronisk version

ISBN

ISRN

Serietitel och serienummer Title of series, numbering

ISSN Titel Title F¨orfattare Author Sammanfattning Abstract Nyckelord Keywords

This report evaluates whether an interpreted high-level garbage col-lected language has enough information about its memory behaviour to make better cache decisions than modern general CPU hardware.

With a generational garbage collector, depending on promotion al-gorithm and generation size, around 90% of all objects never leave the first generation. This report is based on the hypothesis that, because of the low promotion rate, accesses to higher generations are sufficiently rare not to benefit from caching.

To test this hypothesis, we built an operating system with a Scheme interpreter in kernel mode, where the interpreter controls the cache. Generic x86 PC hardware was used, since it allows fine-grained control of cache decisions.

Measurements of execution time in this interpreter show that dis-abling the cache for generations higher than the first does not give any performance gain, but rather a performance loss of up to 50%.

We conclude that this interpreter design is not an improvement, but cannot conclude that the hypothesis is false in general. We suggest building a better CPU simulator to gather more data from which to make better caching decisions, moving internal interpreter data struc-tures into the garbage collected heap and modifying the hardware to allow control in the currently rigid dimension of where data is cached— for example separate control of instruction and data caches and separate data caches for different areas of memory.

AIICS,

Institutionen f¨or datavetenskap 581 83 LINK ¨OPING 2006-05-30 — LITH-IDA-EX--06/044--SE — http://www.ep.liu.se/exjobb/ida/2006/dd-d/044/

Generational garbage collection with explicit control of CPU cache Generationsskr¨apsamling med explicit kontroll av h˚ardvarucache

Karl-Johan Karlsson

memory management, garbage collection, operating systems, cache con-trol

(6)
(7)

Abstract

This report evaluates whether an interpreted high-level garbage collected language has enough information about its memory behaviour to make better cache decisions than modern general CPU hardware.

With a generational garbage collector, depending on promotion algo-rithm and generation size, around 90% of all objects never leave the first generation. This report is based on the hypothesis that, because of the low promotion rate, accesses to higher generations are sufficiently rare not to benefit from caching.

To test this hypothesis, we built an operating system with a Scheme interpreter in kernel mode, where the interpreter controls the cache. Generic x86 PC hardware was used, since it allows fine-grained control of cache decisions.

Measurements of execution time in this interpreter show that disabling the cache for generations higher than the first does not give any perfor-mance gain, but rather a perforperfor-mance loss of up to 50%.

We conclude that this interpreter design is not an improvement, but cannot conclude that the hypothesis is false in general. We suggest build-ing a better CPU simulator to gather more data from which to make bet-ter caching decisions, moving inbet-ternal inbet-terprebet-ter data structures into the garbage collected heap and modifying the hardware to allow control in the currently rigid dimension of where data is cached—for example separate control of instruction and data caches and separate data caches for differ-ent areas of memory.

Keywords: memory management, garbage collection, operating systems, cache control

(8)
(9)

Inneh˚

all

1 Introduktion 1

1.1 Motivering och bakgrund . . . 1

1.2 Rapportens uppl¨agg . . . 2

1.3 Tillg¨anglighet . . . 2

1.4 F¨orkunskapskrav . . . 2

1.5 Ordlista . . . 2

1.6 Introduktion till systemet . . . 3

1.7 Relaterade arbeten . . . 4 1.7.1 Mushroom . . . . 4 2 Systemarkitektur 6 2.1 Processarkitektur . . . 6 2.2 Bootprocess . . . 7 2.3 Sidtabell . . . 7 2.4 Cachekonfiguration . . . 8 2.5 Scheme-interpretator . . . 9 2.6 Skr¨apsamlare . . . 9 2.6.1 Skr¨apsamlarens uppgift . . . 9 2.6.2 Generationer . . . 10 2.6.3 Cheney-kopiering . . . 11 2.6.4 Rotm¨angd . . . 11 2.7 Intern representation . . . 13 vii

(10)

viii INNEH˚ALL 3 Implementationsdetaljer 15 3.1 OSKit . . . 15 3.1.1 C++ . . . 15 3.2 Begr¨ansningar . . . 16 4 Resultat 17 5 Slutsatser 20 5.1 Framtida arbete . . . 20 Litteraturf¨orteckning 23

(11)

Kapitel 1

Introduktion

1.1

Motivering och bakgrund

Examensarbetet ¨ar en utv¨ardering av huruvida interpretatorn f¨or ett h¨og-niv˚aspr˚ak har tillr¨ackligt mycket information om sitt eget minnesbeteende f¨or att kunna ta b¨attre beslut om vad som skall och inte skall cachas ¨an modern generell CPU-h˚ardvara.

Moderna minnessystem ¨ar uppbyggda av˚atminstone tre niv˚aer av minnen— cache, arbetsminne och h˚arddisk. N¨ar man g˚ar ned˚at i denna hierarki blir minnet billigare och st¨orre men ocks˚a l˚angsammare. En process kan v¨al-ja att ignorera dessa niv˚aer, men riskerar d˚a att r˚aka ut f¨or allvarliga prestandaproblem. Detta g¨aller s¨arskilt skr¨apsamlande processer, eftersom dessa har ett minnes˚atkomstm¨onster som radikalt skiljer sig fr˚an de hos icke skr¨apsamlande processer, som modern datorh˚ardvara ¨ar designad f¨or [3; 19; 21].

Eftersom dagens operativsystem ¨ar d˚aliga p˚a att b˚ade ge information om och ta emot instruktioner f¨or hur minneshierarkin skall sk¨otas inifr˚an ett program [15] m˚aste en stor del av systemet designas om f¨or att bli optimalt anpassat f¨or skr¨apsamlande processer. B˚ade ny h˚ardvara [22] och nya operativsystem [13] har f¨oreslagits. Nya s¨att att hantera cache har oftast handlat om att antingen bygga helt ny h˚ardvara [22] eller anpassa

(12)

2 1.2. Rapportens uppl¨agg

skr¨apsamlare f¨or befintlig cachedesign [3; 19; 21]. Intels x86-processorfamilj [7] ¨ar dock tillr¨ackligt anpassningsbar f¨or att ett nytt operativsystem skall kunna f˚a tillr¨acklig kontroll ¨over cacheanv¨andningen.

Resultaten kan ligga till grund f¨or design av framtida operativsystem f¨or interpreterade h¨ogniv˚aspr˚ak med skr¨apsamlat minne, som t.ex. Renaissance System [13].

1.2

Rapportens uppl¨

agg

Kapitel 2 beskriver systemets arkitektur och struktur. Detaljer i implemen-tationen beskrivs i kapitel 3. Resultat fr˚an testk¨orningar redovisas i kapitel 4. Till sist ger kapitel 5 en tolkning av resultaten och f¨oresl˚ar framtida ut¨okningar.

1.3

Tillg¨

anglighet

K¨allkoden till detta projekt finns tillg¨anglig genom HTTP och Subversion p˚a adressen <https://www.ferretporn.se/subversion/percent-scheme/>. Den f˚ar spridas enligt villkoren i GNU General Public License (se k¨allkoden f¨or detaljer).

1.4

orkunskapskrav

L¨asaren b¨or vara f¨ortrogen med grunderna inom operativsystemsdesign, ¨

aven om en del kommer att behandlas ¨oversiktligt i rapporten. ¨Aven allm¨an kunskap om skr¨apsamlande programmeringsspr˚ak f¨oruts¨atts.

1.5

Ordlista

fysisk adress (eng. ”physical address”) Minnesadress s˚asom minnesh˚ ard-varan ser den. Det slutliga steget efter ¨overs¨attning med segmentering och sidindelning.

(13)

Introduktion 3

linj¨ar adress (eng. ”linear address”) Minnesadress som har ¨oversatts med segmentering, men ¨annu inte med sidindelning. Eftersom segmenter-ing inte anv¨ands i detta projekt ¨ar det samma sak som en virtuell adress.

rotm¨angd (eng. ”root set”) De objekt i minnet som kan n˚as omedelbart fr˚an programmet, t.ex. v¨arden p˚a stacken och i globala variabler. Alla levande objekt kan n˚as fr˚an rotm¨angden.

sida (eng. ”page”) ¨Aven ”minnessida”. Den minsta uppdelningen av minne p˚a moderna processorer. P˚a x86 ¨ar de 4 kB stora [7].

sidkatalog (eng. ”page directory”) F¨orsta niv˚ans sidindelning. De 10 mest signifikanta bitarna i en linj¨ar adress ¨ar ett index i katalogen, vilket ger den fysiska adressen till en sidtabell. Se figur 2.1.

sidtabell (eng. ”page table”) Andra niv˚ans sidindelning. Efter att de 10 mest signifikanta bitarna har anv¨ants till sidkatalogen ¨ar n¨astf¨oljande 10 bitar ett index i sidtabellen, vilket ger den fysiska adressen till en minnessida. Sidtabellen inneh˚aller ¨aven n˚agra flaggor som ger infor-mation om minnessidan—relevant f¨or detta projekt ¨ar flaggan som s¨ager huruvida sidan har skrivits till (”dirty bit”), samt inst¨allningar-na f¨or hur sidan skall cachas. Se figur 2.1.

virtuell adress (eng. ”virtual address”) Minnesadress s˚asom den ses av applikationsprogram, innan n˚agon ¨overs¨attning har gjorts.

1.6

Introduktion till systemet

Examensarbetet ¨ar en utv¨ardering av en cachedesign f¨or en skr¨apsam-lande interpretator med operativsystemsst¨od. Spr˚aket som valts f¨or detta ¨

ar Scheme [1].

Systemet som skapats ¨ar f¨or det f¨orsta en Scheme-interpretator, vilken beskrivs n¨armare i avsnitt 2.5. Den intressanta delen av systemet ligger dock i skr¨apsamlaren. F¨or att kunna komma ˚at h˚ardvarun¨ara funktioner k¨ors interpretatorn i ett specialskrivet operativsystem (se avsnitt 2.1).

(14)

4 1.7. Relaterade arbeten

Skr¨apsamlaren (avsnitt 2.6) bygger p˚a en generationell arkitektur [19] och flyttar objekt med en Cheney-kopiator [4]. F¨ordelen med en genera-tionell skr¨apsamlare ¨ar att eftersom de flesta objekt d¨or unga [19] kan man samla st¨orre delen av allt skr¨ap (80–99 % beroende p˚a spr˚ak och befor-dringsalgoritm [8]) genom att skr¨apsamla oftare i bara den f¨orsta genera-tionen ¨an i h¨ogre generationer, vilket tar kort tid eftersom den ¨ar mycket mindre ¨an hela minnesrymden.

P˚a grund av detta kommer ocks˚a b˚ade interpretatorn och skr¨apsam-laren att g¨ora st¨orsta delen av sina minnesreferenser till objekt i f¨orsta generationen. Hypotesen som arbetet utg˚ar fr˚an ¨ar att man f˚ar ett b¨attre resultat av att statiskt lagra hela f¨orsta generationen i cache ¨an om man l˚ater h˚ardvaran v¨alja sj¨alv vilka delar av minnet som skall ligga i cache. Man kommer d˚a att f˚a prestandaf¨orluster vid ˚atkomst till annat minne, t.ex. ¨aldre generationer och stacken, men det skulle d˚a mer ¨an uppv¨agas av att de m˚anga referenserna till f¨orsta generationen g˚ar snabbare.

Systemet samlar statistik om exekveringstid och minnes˚atg˚ang f¨or varje ber¨aknat uttryck, vilket anv¨ants f¨or att producera resultaten i kapitel 4.

1.7

Relaterade arbeten

1.7.1

Mushroom

Mushroom-systemet [20] ¨ar ett system med egenutvecklad h˚ard- och mjuk-vara byggd f¨or att k¨ora Smalltalk-80. ¨Aven det skr¨apsamlar f¨orsta gener-ationen i cache f¨or att ¨oka prestanda [22], men eftersom det till stor del ¨

ar egenutvecklat har det mer kontroll ¨over minnessystemet ¨an vad detta projekt har.

Cachen i Mushroom ¨ar helt mjukvarukontrollerad, s˚atillvida att n¨ar en cache-miss sker k¨ors en mjukvarurutin som tar beslut om vad som skall ers¨attas i cachen och kan ¨andra i b˚ade utg˚aende och inkommande data. Detta g¨or att relationen mellan cache och minne i Mushroom ¨ar mer lik den mellan minne och disk ¨an mellan cache och minne i traditionella operativsystem—till exempel kan hanteraren undvika att skriva cachens inneh˚all till minnet om inneh˚allet ¨and˚a har skr¨apsamlats och aldrig kommer att anv¨andas mer.

(15)

Introduktion 5

Mjukvarukontrollen av cachen anv¨ands ocks˚a f¨or att hantera intergen-erationspekare. En bit i objektets huvud s¨ager om det ¨ar ”lokalt” eller inte. Ett objekt ¨ar lokalt n¨ar det skapas, men om en referens till det skrivs till minnet eller om dess huvud tvingas ur cache ¨ar det inte l¨angre lokalt. Ett icke-lokalt objekt kan aldrig bli lokalt igen. N¨ar cachen skr¨apsamlas l¨aggs de icke-lokala objekten till rotm¨angden. Trots att detta ¨ar en ¨overskattning av den egentliga m¨angd av objekt som refereras till av intergenerationspekare s˚a kan skr¨apsamlaren bli av med s˚a mycket som 90 % av allt skr¨ap innan det l¨amnar cachen [22].

¨

Aven n¨asta minnesniv˚a¨overg˚ang, mellan minnet och disken, s¨arbehand-las av Mushroom. Dels k¨ors skr¨apsamlaren f¨or minnet bara p˚a de objekt som finns i minnet och l¨agger aldrig tid p˚a att h¨amta in n˚agra objekt fr˚an disken, dels f¨ors¨oker systemet undvika att skr¨ap hamnar p˚a disken ¨

over huvud taget. F¨or att h˚alla kvar skr¨ap i minnet kan man f¨orst l¨agga m¨arke till att skr¨ap per definition aldrig kommer att anv¨andas igen, medan levande objekt antagligen kommer att anv¨andas. Mushroom grupperar objekt efter hur l˚ang tid som g˚att sedan de sist anv¨andes, och undviker att flytta de ¨aldsta grupperna till disk om de inte markerats som levande av skr¨apsamlaren.

(16)

Kapitel 2

Systemarkitektur

I detta kapitel beskrivs systemets arkitektur, s˚asom hur operativsystems-grunden och skr¨apsamlaren ¨ar designade. Resultaten kan f¨orst˚as utan att l¨asa detta kapitel, men det ¨ar viktigt f¨or att f¨orst˚a implementationen.

2.1

Processarkitektur

En x86-processor [7] kan k¨oras i fyra olika privilegiel¨agen, ring 0–3. Ring 0 kallas i allm¨anhet f¨or k¨arnl¨age (f¨or att operativsystemsk¨arnan k¨ors d¨ar) och ring 3 f¨or anv¨andarl¨age (f¨or att anv¨andarprogram k¨ors d¨ar). Kod som k¨ors i en ring med h¨ogre nummer kan bara anropa kod i och l¨asa minne fr˚an ringar med l¨agre nummer genom vissa v¨aldefinierade anropsst¨allen, specialinstruktioner eller avbrott, vilka alla tar v¨aldigt l˚ang tid j¨amf¨ort med direkt ˚atkomst. Dessutom kan vissa priviligierade instruktioner, t.ex. rdtsc (”read time-stamp counter”) som anv¨ands f¨or att samla information om skr¨apsamlarens prestanda, inte k¨oras alls i ringar ¨over 0.

Skr¨apsamlaren beh¨over kommunicera l˚agniv˚ainformation direkt med h˚ardvaran (se avsnitt 2.6.4), s˚a d¨arf¨or beh¨over den k¨oras i ring 0, och f¨or att minska komplexiteten f¨or hela systemet betydligt k¨ors all kod i ring 0 s˚a att inga privilegie¨overg˚angar beh¨over g¨oras.

Eftersom det endast ¨ar cacheminnet som ¨ar intressant i det h¨ar arbetet

(17)

Systemarkitektur 7

minimerades komplexiteten i systemet genom att skriva ett nytt opera-tivsystem, helt utan virtuellt minne och anv¨andarl¨age. Scheme-interpretatorn ¨

ar allts˚a en del av operativsystemets k¨arna, och det enda som k¨ors p˚a da-torn.

Ett realistiskt operativsystem skyddar sin k¨arna genom att k¨ora den i k¨arnl¨age och anv¨andarprogram i h¨ogre ringar, s˚a att anv¨andaren inte kan p˚averka operativsystemet. Trots detta ¨ar designvalet att bygga hela systemet i k¨arnl¨age motiverat, eftersom ett fullt operativsystem av pre-standask¨al beh¨over ha skr¨apsamlaren i en l˚ag ring, och prestandaresultat fr˚an detta system ¨ar d¨arf¨or relevanta.

2.2

Bootprocess

OSKit [18], som systemet bygger p˚a (se avsnitt 3.1), inneh˚aller ingen egen bootladdare, men den f¨oljer multiboot-standarden [14] och kan d¨armed bootas av alla bootladdare som ocks˚a f¨oljer den. Det h¨ar projektet anv¨ander GNU GRUB [5], ”the GRand Unified Bootloader”.

All assemblerkod som kr¨avs f¨or bootprocessen kommer fr˚an OSKit, s˚a projektets kod b¨orjar direkt med en main()-funktion i C++. Denna an-ropar n˚agra initialiseringsfunktioner fr˚an OSKit, varefter programmilj¨on ¨

ar redo att anv¨andas.

2.3

Sidtabell

Minnet p˚a x86-arkitekturen ¨ar uppdelat i sidor om 4kB eller 4MB [7], men i detta system anv¨ands endast 4kB-sidor.

Sidtabellen ¨overs¨atter linj¨ara adresser (som programmet ser) till fysiska adresser (som h˚ardvaran vill ha) vid varje minnesaccess. Strukturen, som syns i figur 2.1, ¨ar tv˚a niv˚aer djup, d¨ar de f¨orsta 10 bitarna i den linj¨ara adressen indexerar i f¨orsta niv˚an (sidkatalogen), n¨astf¨oljande 10 bitar in-dexerar i andra niv˚an (sidtabellen) och de sista 12 bitarna ger adressen p˚a sidan. F¨or att snabba upp denna process finns en separat cache f¨or sidtabellens inneh˚all, kallad TLB (Translation Lookaside Buffer).

(18)

8 2.4. Cachekonfiguration

Figur 2.1: ¨Overs¨attning fr˚an linj¨ar till fysisk adress med sidtabeller p˚a x86.

De allra flesta operativsystem idag anv¨ander sidtabellen f¨or att im-plementera virtuellt minne genom att den till˚ater att minnessidor lagras p˚a godtycklig fysisk plats. Detta projekt anv¨ander dock en linj¨ar 1-till-1-¨

overs¨attning mellan virtuell och fysisk adress, s˚a det enda som anv¨ands ¨ar de extra flaggorna i sidtabellen. Dessa flaggor st˚ar f¨or attribut s˚asom om sidan finns i minnet, om den ¨ar skrivbar, om endast operativsystemet eller ¨

aven anv¨andarprocesser f˚ar komma ˚at den och hur minne som t¨acks av den skall cachas.

2.4

Cachekonfiguration

x86-arkitekturen har m˚anga olika implementationer med m˚anga olika cache-parametrar [7]. Vanligast idag ¨ar att cachen ¨ar indelad i tv˚a niv˚aer, varav den snabbaste (”L1”, f¨or ”level 1”) ¨ar i storleksordningen 16–128kB och upp-delad i tv˚a lika stora delar f¨or instruktioner och data, medan n¨asta (”L2”) ¨

ar 128–1024kB stor och inneh˚aller b˚ade instruktioner och data. Det finns ¨

aven system med en ¨annu st¨orre L3-cache, men det ¨ar ¨annu inte s¨arskilt vanligt p˚a arbetsstationer [16].

Det implementerade systemet kan arbeta i tre l¨agen med avseende p˚a cachen. Referensl¨aget ¨ar att cachning till˚ats f¨or allt minne, d.v.s. att h˚

(19)

ard-Systemarkitektur 9

varan tar alla beslut sj¨alv. N¨asta l¨age ¨ar att cachning ¨ar p˚aslaget f¨or allt minne utom andra generationen. Sista l¨aget sl˚ar av cachning f¨or allt minne utom f¨orsta generationen, d.v.s. ¨aven kod och C++-data ¨ar ocachead. Oavsett l¨age ¨ar f¨orsta generationen precis s˚a stor som den st¨orsta cachen, d.v.s. L2 eller, om den finns, L3.

Cachepolicyn som anv¨ands i systemet ¨ar write back, d.v.s. att inneh˚allet i cachen inte skrivs tillbaka till minnet f¨orr¨an n˚agot annat minnesblock skall flyttas upp till cachen och tvingar ut det gamla. N¨ar cachning bara ¨ar p˚aslaget f¨or f¨orsta generationen finns det inget nytt minne som kan tvinga ut det gamla, s˚a hela f¨orsta generationen ligger alltid bara i cache.

Cachekonfigurationen uppr¨attas vid uppstart av systemet, efter att min-nesgenerationerna har definierats, genom att cachekonfigurationsflaggorna i sidtabellen st¨alls f¨or att antingen till˚ata eller f¨orbjuda cachning beroende p˚a om sidan i fr˚aga h¨or till f¨orsta generationen eller inte.

2.5

Scheme-interpretator

Interpretatorn ¨ar en enkel ¨overs¨attning fr˚an Scheme till C++ av %Scheme, en Scheme-i-Scheme-interpretator fr˚an kursen TDDA69 Data- och pro-gramstrukturer [6] p˚a Link¨opings universitet som i sin tur bygger p˚a den metacirkul¨ara evaluatorn som beskrivs av Abelson och Sussman [2]. Den implementerar st¨orre delen av det som ¨ar klassificerat som ”syntax” och ”library syntax” i Scheme-standarden [1].

2.6

Skr¨

apsamlare

2.6.1

Skr¨

apsamlarens uppgift

Skr¨apsamlaren ser till att minne som programmet allokerat men inte l¨angre anv¨ander ˚aterl¨amnas till systemet.

Om programmet inte kan referera till ett objekt i minnet g¨or det ingen skillnad huruvida det faktiskt finns eller inte, och det objektet ¨ar d˚a skr¨ap. Allts˚a kan problemet omformuleras till att hitta vilka objekt programmet kan respektive inte kan n˚a f¨or att referera till.

(20)

10 2.6. Skr¨apsamlare

Det finns vissa objekt—r¨otter—som alltid ¨ar tillg¨angliga. Beroende p˚a spr˚ak och interpretatorarkitektur kan de vara definierade olika, men typiskt ¨

ar att det g¨aller objekt som pekas p˚a fr˚an v¨arden i register och objekt p˚a stacken. Dessa objekt har sedan pekare till andra objekt, som har pekare i sin tur, o.s.v.. Att ett objekt ¨ar levande definieras som att det kan n˚as genom en s˚adan kedja av pekare fr˚an r¨otterna, och objekt som inte ¨ar n˚abara definieras som skr¨ap.

2.6.2

Generationer

I detta system sker skr¨apsamlingen generationellt [19], med tv˚a genera-tioner.

Objekt skapas i den f¨orsta generationen. N¨ar den ¨ar full skr¨apsamlas den, och de ¨overlevande objekten flyttas upp till den andra generationen. Den andra generationen best˚ar av tv˚a halvrymder varemellan de objekt som ¨overlever varje skr¨apsamling flyttas. Dessa skr¨apsamlas om det direkt efter en skr¨apsamling av f¨orsta generationen finns mindre ¨an 10% ledigt utrymme i andra generationen.

(21)

Systemarkitektur 11

2.6.3

Cheney-kopiering

Flyttningen av objekt mellan generationer och halvrymder utf¨ors med en Cheney-kopiator [4]. Denna skr¨apsamlingsalgoritm har f¨ordelen att den an-v¨ander konstant minnesutrymme, till skillnad fr˚an s˚adana algoritmer som f¨oljer objektgrafer rekursivt och d¨arf¨or beh¨over en stack [8].

Cheneys algoritm anv¨ander en k¨o ist¨allet f¨or en stack, vilket g¨or att objektgrafen traverseras i bredden f¨orst-ordning. Dessutom utnyttjar den det faktum att alla objekt som bes¨oks, och d¨armed hamnar i k¨on, ¨ar levande och skall flyttas till n¨asta generation. Den flyttar upp alla objekt den tr¨affar p˚a till n¨asta generation, och anv¨ander sedan objekten sj¨alva som k¨o med hj¨alp av tv˚a pekare som talar om var b¨orjan och slutet p˚a k¨on finns. P˚a s˚a s¨att anv¨ands bara konstant minne f¨or traverseringen (de tv˚a pekarna) och objekten kompakteras samtidigt i botten av n¨asta generation.

2.6.4

Rotm¨

angd

Skr¨apsamlaren baserar sitt beslut om huruvida ett objekt ¨ar skr¨ap eller inte p˚a om det kan n˚as fr˚an programmet eller inte. Rotm¨angden best˚ar av de objekt som kan n˚as omedelbart fr˚an programmet, utan att beh¨ova f¨olja pekare genom andra objekt.

I detta system best˚ar rotm¨angden av fyra delar—Scheme-stacken, den globala omgivningen, makrolistan och intergenerationspekare.

Scheme-stacken

De C++-funktioner som behandlar Scheme-objekt m˚aste till˚ata att alla objekt flyttas av skr¨apsamlaren. Detta inkluderar argument, mellanlagrade tempor¨ara v¨arden och returv¨arden. F¨or att skr¨apsamlaren skall slippa k¨na till hur C++-stacken ser ut och hur den kompilerade C++-koden an-v¨ander tempor¨arvariabler anv¨ands en separat Scheme-stack, som hanteras med explicita instruktioner fr˚an C++-kod. Ramarna ¨ar av fix storlek—fem argument och tv˚a tempor¨ara variabler—f¨or att underl¨atta hanteringen.

En C++-funktion som beh¨over behandla Scheme-objekt vilka kan flyt-tas av skr¨apsamlaren b¨orjar med en standardprolog som skapar en ny ram och l¨agger in alla sina argument i den. Ramen l¨aggs p˚a Scheme-stacken,

(22)

12 2.6. Skr¨apsamlare

varefter alla ber¨akningar h¨amtar v¨arden fr˚an ramen ist¨allet f¨or fr˚an C++-argumenten. Tempor¨ara v¨arden mellanlagras i ramen, och returv¨ardet l¨aggs i en av de tempor¨ara variablerna. Till sist plockar standardepilogen bort ramen fr˚an stacken och v¨ardet i den ena tempor¨ara variabeln returneras.

Alla sju platserna i en stackram initialiseras till ett v¨arde som aldrig kan vara en pekare till ett giltigt objekt, och skr¨apsamlaren kommer att hoppa ¨over detta v¨arde.

Global omgivning och makrolista

En omgivning representeras som en lista med ramar, ordnade fr˚an inner-sta till ytterinner-sta—den globala omgivningen ligger allts˚a sist i varje s˚adan lista. En ram representeras som ett punkterat par av tv˚a listor med namn respektive v¨arde f¨or alla bindningar i ramen.

En pekare till listan med den (Scheme-)globala omgivningen h˚alls i en (C++-)global variabel, och denna variabel ing˚ar i rotm¨angden. Eftersom omgivningar och ramar ¨ar vanliga Scheme-listor beh¨ovs ingen ytterligare s¨arbehandling.

Makrolistan ¨ar en associationslista fr˚an namn till lambdafunktioner som k¨ors f¨or att expandera makrot. C++-variabeln som h˚aller pekaren till denna lista ing˚ar i rotm¨angden.

Intergenerationspekare

Omedelbart efter att f¨orsta generationen har skr¨apsamlats ¨ar den tom, och alla objekt ligger antingen i rotm¨angden eller i andra generationen. Skr¨apsamlingen av andra generationen ¨ager d¨arf¨or rum vid s˚adana tillf¨allen, och beh¨over inte ta h¨ansyn till pekare mellan generationerna.

N¨ar f¨orsta generationen skr¨apsamlas finns det dock alltid (f¨orutom allra f¨orsta g˚angen) objekt i andra generationen, och om dessa inneh˚aller pekare in i f¨orsta generationen beh¨over de ing˚a i rotm¨angden.

Jones och Lins [8] beskriver ett antal olika s¨att att hitta s˚adana pekare. De flesta f˚angar skrivningar med en skrivbarri¨ar och kommer ih˚ag var inter-generationspekare har lagrats, s˚a att m¨angden objekt som beh¨over l¨aggas till rotm¨angden och s¨okas genom minimeras.

(23)

Systemarkitektur 13

Det finns en avv¨agning att g¨ora mellan arbetet som g¨ors i skrivbarri¨aren respektive i s¨okningen efter pekare. I stora drag kan man f˚a en mer precis h˚agkomst av var pekarna finns genom att tillbringa mer tid i skrivbarri¨aren, vilket d˚a g¨or att s¨okningen g˚ar snabbare. Zorn [23] beskriver och j¨amf¨or ett antal olika s¨att att implementera skrivbarri¨aren och g¨ora denna avv¨agning. I detta system anv¨ands en algoritm som liknar den som anv¨ands i LISP-maskinen Symbolics 3600 [10]. x86-processorn har h˚ardvarust¨od som g¨or skrivbarri¨aren gratis, medan markeringen ¨ar grov och kr¨aver genoms¨okning av stora minnesutrymmen.

Sidtabellen (se avsnitt 2.3) inneh˚aller en bit (”dirty bit”) som s¨ager hu-ruvida sidan har skrivits till. Denna s¨atts av h˚ardvaran vid alla skrivningar till en minnessida. Direkt efter en skr¨apsamling av f¨orsta generationen kan det inte finnas n˚agra intergenerationspekare, eftersom det inte finns n˚agra objekt i f¨orsta generationen som de kan peka p˚a. D˚a st¨angs biten av f¨or alla sidor som t¨acker andra generationen. N¨ar en skrivning sker kommer h˚ardvaran att s¨atta biten, oavsett vad som skrevs. N¨ar sedan f¨orsta genera-tionen skall skr¨apsamlas igen s¨oks alla markerade minnessidor genom efter intergenerationspekare, och alla s˚adana pekare l¨aggs till rotm¨angden.

2.7

Intern representation

Ett av de f¨orsta designval implementationen av en Scheme-interpretator st¨alls inf¨or ¨ar hur typning skall implementeras. Det finns tv˚a huvudalternativ— typade pekare och typade objekt. Med typade pekare reserveras ett antal av bitarna i varje pekare f¨or att tala om vilken typ objektet de pekar p˚a har. Typade objekt har dessa bitar i ett f¨alt i objekthuvudet ist¨allet.

Detta system anv¨ander typade objekt, fr¨amst f¨or att det d˚a blir en-klare att behandla objekt n¨ar skr¨apsamlaren sveper ¨over dem utan att f¨olja pekare. Hade typade pekare anv¨ants hade varje objekt i alla fall be-h¨ovt ha ˚atminstone sin storlek i huvudet, medan vissa operationer som bara beh¨over veta typen p˚a ett objekt hade g˚att fortare eftersom mindre data hade beh¨ovt h¨amtas fr˚an minnet. En annan nackdel med typade pekare ¨ar att om man vill slippa maskera bort typbitarna i pekarna f¨or varje opera-tion, vilket tar alldeles f¨or l˚ang tid, beh¨over man en noggrant designad och inflexibel minneslayout s˚a att typbitarna ¨ar en del av adressen.

(24)

14 2.7. Intern representation

De typer som finns ¨ar heltal, str¨angar, symboler och cons-celler. Det beh¨ovs allts˚a inget s¨att att hantera stora objekt, eftersom de m˚aste brytas ner till listor f¨orst. Objekten har 4 byte huvud och antingen 4 byte (heltal, str¨angar, symboler) eller 8 byte (cons-celler) data.

(25)

Kapitel 3

Implementationsdetaljer

3.1

OSKit

St¨orsta delen av l˚agniv˚afunktionaliteten i systemet ¨ar implementerad med hj¨alp av OSKit [18]. OSKit ¨ar ett bibliotek med funktioner avsedda att hj¨alpa utvecklare av operativsystem genom att ta hand om alla detaljer som kr¨avs f¨or att f˚a ett minimalt bootbart system, s˚a att utvecklaren kan koncentrera sig p˚a det som g¨or just dennes operativsystem unikt.

I detta projekt anv¨ands OSKit p˚a tv˚a s¨att—dels anv¨ands f¨ardig funk-tionalitet rakt av, t.ex. den allra f¨orsta bootkoden och konsoldrivrutinen, dels anv¨ands abstraktionslager till l˚agniv˚afunktionalitet, t.ex. minneshanter-ing och CPU-initialiserminneshanter-ing.

3.1.1

C++

OSKit ¨ar skrivet i C och assembler. Det tillhandah˚aller tv˚a standardbib-liotek f¨or C—ett minimalt som inte tillhandah˚aller t.ex. fil-I/O och flyttals-matematik, och ett (anpassat fr˚an FreeBSD 2.2.2) som inneh˚aller i stort sett allt ett C-standardbibliotek skall inneh˚alla.

C++-kompilatorn i GCC f¨orlitar sig mycket p˚a funktioner i C-biblioteket glibc, f¨or mycket f¨or att fungera omedelbart i denna begr¨ansade milj¨o.

(26)

16 3.2. Begr¨ansningar

Nicholas [11; 12] beskriver dock hur man minimerar dess beroenden till-r¨ackligt mycket f¨or att arv och undantag skall fungera, ¨aven om GNU STL [17] (C++:s standardbibliotek) och globala objekt ¨annu inte fungerar.

P˚a grund av fel i OSKits k¨allkod som f¨orst nyligen b¨orjat f˚angas av kom-pilator och l¨ankare kr¨avs ¨aven att man inte anv¨ander en f¨or ny och strikt toolchain. Vilka versioner som kr¨avs ¨ar n¨armare dokumenterat i k¨allkoden till detta projekt.

3.2

Begr¨

ansningar

Systemet finns implementerat enligt beskrivningen i denna rapport. Dock saknas optimering f¨or intergenerationspekare (avsnitt 2.6.4), p˚a grund av buggar som tog l¨angre tid ¨an planerat att l¨osa. Intergenerationspekare hit-tas ist¨allet genom att s¨oka i alla minnessidor som har anv¨ants i andra generationen, inte bara de som har skrivits i sedan senaste skr¨apsamlingen. Det saknas ¨aven svansrekursionsoptimering av Scheme-stacken.

(27)

Kapitel 4

Resultat

Figur 4.1 redovisar resultatet av att k¨ora fyra olika testprogram med de tre olika cache-inst¨allningar som beskrivs i avsnitt 2.4.

CPU:n som anv¨andes ¨ar en Intel Mobile Pentium 3 med 1 GHz klock-frekvens, med en L1-cache uppdelad p˚a 16 kB f¨or instruktioner och 16 kB f¨or data och en L2-cache p˚a 256 kB. F¨orsta generationen var lika stor som L2-cachen, eftersom L3-cache saknades. Varje program k¨ordes fyra g˚anger, och varje g˚ang noterades antalet CPU-cykler som kr¨avdes. Diagrammet visar medelv¨ardet samt standardavvikelsen f¨or de fyra k¨ortiderna.

Program 1 Transformerar en kort lista. F¨orsta generationen skr¨apsamlas en g˚ang under k¨orningen, strax innan den avslutas.

Program 2 Definierar en funktion som helt f˚ar plats i f¨orsta generationen. Program 3 Anv¨ander funktionen i program 2 f¨or att uppdatera ett v¨arde etthundra g˚anger. F¨orsta generationen skr¨apsamlas fem g˚anger under k¨orningen.

Program 4 L¨aser v¨ardet som uppdaterades i program 3. Detta flyttades upp till andra generationen tidigt under k¨orningen av program 3. Att bara ha cachning p˚aslaget f¨or f¨orsta generationens minne ger k¨or-tider som ¨ar runt femhundra g˚anger l¨angre ¨an basfallet (se tabell 4.1. Detta

(28)

18 100000 1e+06 1e+07 1e+08 1e+09 1e+10 1e+11 1e+12 0 1 2 3 4 5 Tid (CPU−cykler) Program Cache för hela minnet

Cache av enbart första generationen Cache av allt utom andra generationen Standardavvikelse

Figur 4.1: K¨ortid f¨or olika testprogram med olika cacheinst¨allningar.

beror antagligen p˚a att inte ens L1-instruktionscachen ¨ar aktiv d˚a, vilket g¨or att varje instruktion resulterar i minst en cachemiss varf¨or CPU:ns pipeline ¨ar tom st¨orsta delen av tiden.

N¨ar cachning ¨ar avst¨angt enbart f¨or andra generationen p˚averkas pre-standa fortfarande negativt, dock inte tilln¨armelsevis lika mycket—bara upp till 56 %. Detta syns speciellt p˚a program tre, vars data flyttas upp till andra generationen tidigt under k¨orningen, och program fyra, vilket uteslutande arbetar p˚a data i andra generationen.

(29)

Resultat 19

Program Allt Endast f¨orsta Allt utom andra

1 1 477 1,01

2 1 511 1,03

3 1 509 1,14

4 1 465 1,56

(30)

Kapitel 5

Slutsatser

Modern cachedesign ¨ar resultatet av l˚ang tids datasamling och -analys. Det ¨

ar ¨aven en integrerad del av CPU-designen, i och med att l˚anga pipelines kr¨aver snabb cache f¨or att kunna fungera optimalt. Trots att denna design ¨

ar grundad p˚a program med explicit minneshantering ist¨allet f¨or skr¨apsam-ling fungerar den tillr¨ackligt bra f¨or att detta arbete inte skall ha lyckats g¨ora den b¨attre.

Detta negativa resultat beh¨over inte bero p˚a att hypotesen—att speci-fik manuell cachedesign kan bli b¨attre ¨an generisk—¨ar felaktig, utan kan ¨

aven bero p˚a begr¨ansningar i den nuvarande implementationen eller att det saknades tillr¨ackliga data f¨or att g¨ora en bra design.

5.1

Framtida arbete

Insamling av mer data

Det ¨ar sv˚art att f¨orutse resultatet av att ¨andra p˚a cacheinst¨allningar, men att ha mer bakgrundsinformation tillg¨anglig skulle kunna underl¨atta. En systemsimulator som klarar av att ge finkornig cachestatistik per minnes-sida skulle antagligen kunna producera s˚adan information. Dock m˚aste en s˚adan simulator f¨orst byggas, t.ex. genom att l¨agga till cachefunktionalitet till Bochs [9].

(31)

Slutsatser 21

Datainsamling skulle ¨aven kunna g¨oras p˚a st¨orre och mer realistiska exempelprogram ¨an de som tagits upp i denna rapport, men vi f¨orv¨antar oss inga st¨orre prestandaskillnader. Relevant f¨or prestanda skulle kunna vara att st¨orre program har fler tempor¨ara datastrukturer, och d¨arf¨or inte beh¨over l¨asa indata fr˚an ocachat minne lika ofta. D¨aremot kommer pro-grammet ta mer plats och d¨armed flyttas upp till ocachat minne tidigare. Flytta mer data till Scheme-heapen

I den nuvarande implementationen ¨ar minnet huvudsakligen uppdelat i fem delar: C++-kod, C++-stack, str¨angtabell, Scheme-stack och Scheme-heap. Om skr¨apsamlaren k¨anner till hur kompilatorn bygger C++-stacken beh¨ovs inte en speciell Scheme-stack, vilket minskar b˚ade dubbelarbete och min-nes˚atg˚ang. En ytterligare f¨orb¨attring skulle kunna vara att l¨agga str¨angta-bellen i Scheme-heapen, eller l¨agga str¨angar direkt i Scheme-heapen utan att anv¨anda en str¨angtabell alls.

Uppdelad cache mellan data och instruktioner

Att sl˚a av cachning f¨or instruktioner ger dramatiskt f¨ors¨amrad prestanda p˚a processorarkitekturer med l˚anga pipelines. En cachedesign som tar h¨ansyn till detta skulle kunna ha en instruktionscache som ¨ar p˚aslagen f¨or hela minnet, medan datacachen kontrolleras som i detta arbete. x86-h˚ardvara har redan ofta uppdelad instruktions- och datacache, ˚atminstone i L1, men de kan inte kontrolleras separat utan m˚aste st¨angas av samtidigt.

Flera oberoende cachar

En generalisering av arkitekturen med uppdelad data- och instruktions-cache ¨ar att ha flera stycken oberoende men generella cachar som kan pro-grammeras var f¨or sig efter vilken sorts minne de inneh˚aller, och att man f¨or varje minnessida v¨aljer vilken cache (om n˚agon) den skall hamna i. Mushroom-lik cachedesign

Mushroom-systemet (se avsnitt 1.7.1) hade total mjukvarukontroll ¨over cachen, vilket m¨ojliggjordes av att h˚ardvaran var specialbyggd. x86 till˚ater

(32)

22 5.1. Framtida arbete

inte att man behandlar cachen explicit p˚a det s¨attet, men man kan komma n¨ara genom att avdela ett omr˚ade av minnet som det enda som t¨acks av cachen och flytta objekt in i och ut ur detta omr˚ade. Man kan inte heller f˚anga cachemissar och hantera dem i mjukvara, men samma funktionalitet kan uppn˚as genom att g¨ora alla ocacheade minnessidor ol¨asbara och ist¨allet f˚anga sidfelen som uppst˚ar n¨ar programmet f¨ors¨oker l¨asa dem. Alternativt kan koden som l¨aser objekttabellen vid varje objektreferens ut¨okas till att ¨

(33)

Litteraturf¨

orteckning

[1] Revised5 Report on the Algorithmic Language Scheme, februari 1998. http://www.schemers.org/Documents/Standards/R5RS/.

[2] Abelson, Harold, Gerald Jay Sussman, och Julie Sussman: Structure and Interpretation of Computer Programs. The MIT Press, 1996. [3] Baker, Henry G.: Cache-Conscious Copying

Col-lectors. I Submission for GC’91 Workshop on

Garbage Collection in Object-Oriented Systems, 1991. http://citeseer.csail.mit.edu/baker91cacheconscious.html. [4] Cheney, C. J.: A nonrecursive list compacting algorithm.

Communi-cations of the ACM, 13(11):677–678, 1970.

[5] The Free Software Foundation: GRUB Manual, augusti 2005. http://www.gnu.org/software/grub/manual/.

[6] Haraldsson, Anders: TDDA69 Data- och programstrukturer, februari 2006. http://www.ida.liu.se/~TDDA69/.

[7] Intel corporation: IA-32 Intel Architecture Software Developer’s Man-ual, 2002.

[8] Jones, Richard och Rafael Lins: Garbage collection: Algorithms for automatic dynamic memory management. John Wiley & sons, 1996. [9] Lawton, Kevin, Bryce Denney, et al.: Bochs user manual, 2006.

http://bochs.sourceforge.net/.

(34)

24 LITTERATURF ¨ORTECKNING

[10] Moon, David A.: Garbage collection in a large LISP system. I Proceed-ings of the 1984 ACM Symposium on LISP and functional program-ming, sidor 235–246, Austin, Texas, USA, 1984.

[11] Nicolas, Eric: Linux technical study: Minimum

C program, januari 2005.

http://www.erik-n.net/studies/linux_boot_c/linux_boot_c.pdf.

[12] Nicolas, Eric: Linux technical study: Minimum

C++ program, januari 2005.

http://www.erik-n.net/studies/linux_boot_cpp/linux_boot_cpp.pdf.

[13] Nurmiranta, Tobias: System f¨or persistenta datastrukturer med skr¨ ap-samling baserat p˚a IA32-arkitekturen. Magisteruppsats, Link¨opings universitet, oktober 2002.

[14] Okuji, Yoshinori K., Bryan Ford, Erich Stefan Bo-leyn, och Kunihiro Ishiguro: Multiboot Specifica-tion manual. The Free Software Foundation, 2004. http://www.gnu.org/software/grub/manual/multiboot/.

[15] The Open Group: Single UNIX Specification, 2001. Specifikt funktio-nen posix madvise().

[16] Stallings, William: Computer organization and architecture: Designing for performance. Prentice Hall, 2006.

[17] Stroustrup, Bjarne: The C++ programming language. Addison Wesley, 2000.

[18] The Flux research group: The OSKit: The Flux operating sys-tem toolkit. teknisk rapport, Department of computer science, University of Utah, Salt Lake City, Utah, USA, mars 2002. http://www.cs.utah.edu/flux/oskit/.

[19] Ungar, David: Generation Scavenging: A Non-disruptive High Per-formance Storage Reclamation Algorithm. ACM SIGPLAN Notices, 19(5):157–167, maj 1984.

(35)

[20] Williams, Ifor och Mario Wolczko: An Object-Based Memory Architec-ture. I Dearle, Alan, Gail M. Shaw, och Stanley B. Zdonik (redakt¨or-er): Implementing Persistent Object Bases: Proceedings of the Fourth International Workshop on Persistent Object Systems, sidor 114–130. Morgan Kaufmann Publishers, Inc., 1991.

[21] Wilson, R. Paul, Michael S. Lam, och Thoma G. Moher: Caching Considerations for Generational Garbage Collection. I Proceed-ings of the 1992 ACM Conference on Lisp and Functional Pro-gramming, sidor 32–42, San Francisco, CA (USA), juni 1992. http://citeseer.csail.mit.edu/wilson92caching.html.

[22] Wolczko, Mario och Ifor Williams: Multi-level Garbage Collection in a High-Performance Persistent Object System. I Persistent object sys-tems. Springer-Verlag, september 1992.

[23] Zorn, Benjamin: Barrier Methods for Garbage

Col-lection. Teknisk rapport CU-CS-494-90, 1990.

(36)
(37)

LINKÖPING UNIVERSITY ELECTRONIC PRESS

Copyright

Svenska

Detta dokument h˚alls tillg¨angligt p˚a Internet - eller dess framtida ers¨attare - under 25 ˚ar fr˚an publiceringsdatum under f¨oruts¨attning att inga extraordin¨ara omst¨andigheter uppst˚ar.

Tillg˚ang till dokumentet inneb¨ar tillst˚and f¨or var och en att l¨asa, ladda ner, skriva ut enstaka kopior f¨or enskilt bruk och att anv¨anda det of¨or¨andrat f¨or ickekommersiell forskning och f¨or undervisning. ¨Overf¨oring av upphovsr¨atten vid en senare tidpunkt kan inte upph¨ava detta tillst˚and. All annan anv¨andning av dokumentet kr¨aver upphovsmannens medgivande. F¨or att garantera ¨aktheten, s¨akerheten och tillg¨angligheten finns det l¨osningar av teknisk och administrativ art.

Upphovsmannens ideella r¨att innefattar r¨att att bli n¨amnd som upphovsman i den omfat-tning som god sed kr¨aver vid anv¨andning av dokumentet p˚a ovan beskrivna s¨att samt skydd mot att dokumentet ¨andras eller presenteras i s˚adan form eller i s˚adant sammanhang som ¨ar kr¨ankande f¨or upphovsmannens litter¨ara eller konstn¨arliga anseende eller egenart.

F¨or ytterligare information om Link¨oping University Electronic Pressse f¨orlagets hem-sida http://www.ep.liu.se/

English

The publishers will keep this document online on the Internet or its possible replacement -for a period of 25 years from the date of publication barring exceptional circumstances.

The online availability of the document implies a permanent permission for anyone to read, to download, to print out single copies for your own use and to use it unchanged for any non-commercial research and educational purpose. Subsequent transfers of copyright cannot revoke this permission. All other uses of the document are conditional on the consent of the copyright owner. The publisher has taken technical and administrative measures to assure authenticity, security and accessibility.

According to intellectual property law the author has the right to be mentioned when his/her work is accessed as described above and to be protected against infringement.

For additional information about the Link¨oping University Electronic Pressand its pro-cedures for publication and for assurance of document integrity, please refer to its WWW home page: http://www.ep.liu.se/

c

Karl-Johan Karlsson Link¨oping, 5 juli 2006

References

Related documents

L˚ at y(t) vara andelen av populationen som ¨ar smittad efter tiden t dygn, r¨aknad fr˚ an uppt¨ack- ten... Observera att ¨amnets koncentration ¨ar samma som m¨angden av

[r]

Den ovanst˚ aende bevistekniken ¨ar ett modernt p˚ afund och knepet att skapa en l¨amplig tv˚ a- dimensionell f¨ordelning

I en produktionsprocess blir enheterna, oberoende av varandra, felak- tiga med sannolikhet 0.01 och 300 enheter tillverkas. I en urna finns vita och

Till exempel fick jag inte med n˚ agot Ljus- och Optikland i f¨ orsta f¨ ors¨ oket, och pilen mot Kosmologi, som ligger utanf¨ or den h¨ ar kartan, borde peka mer upp˚ at,

Endast definitioner och trigonometriska r¨ aknelagar f˚ ar anv¨ andas utan att de f¨ orst bevisas. Sida 2

¨ar en kompakt m¨angd och funktionen f ¨ar kontinuerlig p˚a denna, s˚a d¨arf¨or kan vi p˚a f¨orhand veta att f har ett minsta v¨arde p˚a denna m¨angd, vilket d˚a ocks˚a,

I en simbass¨ang finns ett halvcirkelformat f¨onster D med radie R och vars medelpunkt befinner sig p˚a djupet h, d¨ar h &gt; R, en-