• No results found

3.4 Etiska överväganden

4.1.2 DOD/DOTS implementeringen

För att kunna använda sig av DOTS och ECS installerades följande tilläggspaket med hjälp av pakethanteraren: Entities (preview) v 0.9.1, Hybrid Renderer (preview) v. 0.4.2 och Unity Physics (preview) v 0.3.2.

I DOD implementeringen representeras kuberna av entiteter. Entiteterna håller komponenter som i sin tur håller data. Samma kub spelobjekt som instansieras i OOP-versionen används även i denna implementering men här konverteras spelobjektet till en entitet innan den instansieras. Vid konverteringen kommer Mesh Filter och Mesh Renderer konverteras till komponenten RenderMesh [23] Box Collider till PhysicsShape samt Rigidbody till PhysicsBody [24].

Klassdiagrammet, fig 4.4, visar de fyra komponenterna och deras fyra system. Då komponenter är structs som endast kan hålla värdetyper och Material och Mesh är referenstyper så finns även två klasser som ärver från MonoBehaviour med i simuleringen. Detta medför att simuleringen inte är en renodlad DOD simulering. MonoBehaviour ärver i sin tur från klassen Behaviour som ärver från Component som i sin tur ärver från Object. Detta bygger upp en hierarki av klasser som ärver från varandra. Därav finns det även ett begränsat inslag av OOP även i denna simulering [25-28].

Figur 4.4: Visar de fyra komponenterna och dess fyra system som samverkar med varandra. Två klasser som ärver från MonoBehaviour är även med.

4.1.3 Objektstruktur

Om man jämför de två klassdiagrammen så ser man att alla klasser i OOP-implementeringen ärver från MonoBehaviour. Detta betyder att alla dessa klasser har denna arvshierarki som är fyra klasser djup, det vill säga MonoBehaviour, ​Behaviour, Component och Object. Tittar man på klassdiagrammet över DOD-implementeringen är det bara två klasser som har denna arvshierarki. Resterande klasser implementerar antingen interfacet IComponentData eller klassen SystemBase, beroende på om det är en komponent eller ett system.

4.2 Tidskomplexitet och minneskomplexitet

Granskar man min kod borde tidskomplexiteten vara linjär, O(n). Dock beror detta även på hur Unitys kod är skriven. Tittar man i figur 5.4 och 5.9, som visar processoranvändningens medelvärde i miljö 1 och 2, visar de att mätpunkterna lägger sig på linje, vilket även det indikerar på att tidskomplexiteten skulle vara linjär. Det syns även att DOD-grafen har ett lägre k-värde än OOP-grafen det vill säga DOD-linjens lutning är mindre än OOP-linjens. Troligtvis är både DODs och OOPs tidskomplexitet linjär. För att få en säkrare uppfattning om detta skulle dock antalet mätnivåer i experimentet behöva utökas ytterligare.

Minneskomplexiteten som visas av figur 5.5 och figur 5.14 visar att OOP-grafens punkter lägger sig på linje. Detta tyder på att minneskomplexiteten för OOP är linjär medan DOD-grafens k-värde är 0, d v s minneskomplexiteten för DOD ökar inte med antalet kuber.

5 Resultat

I detta kapitel presenteras resultatet av litteraturundersökning samt de mätvärden som uppmätts med hjälp av profileringsverktyget som finns inbyggt i Unity. För att kunna få ut ett medelvärde av antalet ms som processorn spenderar på varje frame har även paketet Profiler Analyzer v. 1.0.1 laddats ner med hjälp av pakethanteraren.

5.1 Systematisk litteraturundersökning

Artiklarna som används i litteraturundersökningen baserar sig på sökningar utförda i Google då sökningarna i Google Scholar och diva-portalen inte resulterade i några relevanta träffar.

Tabell 5.1: Visar de framkomna fördelarna med OOP.

I tabell 5.1 presenteras de fördelar som framkom vid användning av OOP. De fördelar samt nackdelar som endast uppkom i en enstaka artikel har inte tagits med i undersökningen då undersökningen är utförd på grå litteratur som anses ha mindre trovärdighet.

Då det var lättare att hitta information om OOP än DOD så baserar sig OOP underlaget på 17 artiklar ​[3], [29-44] medan DOD endast baserar sig på 4 stycken artiklar [3], [39], [42], [45].

De fördelar som är vanligast förekommande i artiklarna är att OOP gör att det är lätt att ​underhålla koden, återanvändning av kod vilket ofta sker genom arv, säkerhet i form av inkapsling samt att objekten som används reflekterar den mänskliga verkligheten.

En anledning till att OOP beskrivs som mer prestandakrävande är att OOP inte utnyttjar cachen lika effektivt som DOD. Detta beror bland annat på att objekten oftast är stora och innehåller mycket data. Är man intresserad av specifik data, som t ex endast en variabel, från ett objekt så kommer man

OOP fördel

Antal artiklar / Totalt antal

artiklar Artikel källa

Återanvändning av kod (arv) 9 / 17 [29-37]

Lätt att underhålla koden 8 / 17 [29-30], [33-38]

Säkerhet (inkapsling) 6 / 17 [29-32], [35-36]

Objekten som används reflekterar den

mänskliga verkligheten 6 / 17 [29], [31], [33], [35], [39-40] Parallell utveckling 4 / 17 [29], [33], [35-36] Sänker programmeringskostnaden 2 / 17 [37], [41] Bra för GUI-programmering 2 / 17 [3], [41]

ladda in all data från detta objekt. Detta resulterar i onödig data i cachen vilket leder till ineffektiv cachning [40, 42].

Återanvändning av kod i form av arv blir då något som även kan ses som negativt då det också är en bidragande faktor till att OOP blir än mer prestandakrävande i och med att även klasserna som ärvs läses in i cachen och därmed adderar ännu mer onödig data [3], [43-44]. Just prestandakrävande är också det som nämns som den vanligaste nackdelen med OOP vilket går att se i tabell 5.2.

Tabell 5.2: Visar de framkomna nackdelarna med OOP.

OOP-koden nämns som lätt att underhålla dock menar vissa på att det krävs ordentlig planering och kunskap för att undvika att den stora kodbasen blir rörig.

Något som också nämns är att OOP-koden upplevs som komplex att parallellisera. Detta tas också upp som motpol i DOD som anses lättare att parallellisera i jämförelse med OOP, se tabell 5.3. Detta motiveras med att risken med att processorn försöker få åtkomst till samma data samtidigt blir större med OOP än med DOD. Detta då DOD är skrivet med fokus på hur data generellt bearbetas och är därmed grupperad med liknande data [3, 39].

OOP nackdel

Antal artiklar / Totalt antal

artiklar Artikel källa

Prestandakrävande 11 / 17

[3], [29-31], [34-37], [39], [41],

[43], Koden har en tendens att bli rörig och

kräver därför ordentlig planering samt

kunskap 6 / 17

[29-31], [33], [35-36] OOP-program är mycket större än andra

program 4 / 17 [30], [35-37]

Parallellisera koden är komplext 3 / 17 [3], [39], [44]

Är inte en lämplig lösning för alla typer av

Tabell 5.3: Visar de framkomna fördelarna med DOD.

I tabell 5.3 går det att se att DOD ses som en cachevänligare kod än OOP som leder till färre cachemissar.

Tabell 5.4: Visar de framkomna nackdelarna med DOD.

I Mike Actons föreläsning säger han: “Programmerarens jobb är inte att skriva kod. Programmerarens jobb är att lösa data transformeringsproblem. Koden är verktyget som vi använder för att kunna lösa problemet”. Han menar på att i OOP så ligger mycket fokus på just koden medan DOD istället lägger fokuset på just data och hur det bearbetas [46].

5.2 Kontrollerade experiment

För att kunna utföra experimentet togs först tre mätnivåer fram med ett varierande antal kuber. Sedan utfördes mätningarna på alla tre nivåer i de tre olika miljöerna som finns presenterade i tabell 3.1 under rubriken metod. 5.2.1 Framtagning av mätnivåer

Mätnivåerna bestående av nivå 1, 2 och 3 togs fram genom att OOP-simuleringen kördes i miljö 2, den miljön med medel begränsade resurser. Nivåerna som sattes visas i tabell 5.5 nedan.

DOD fördel

Antal artiklar / Totalt antal

artiklar Artikel källa

Cachevänligare kod som leder till färre

cachemissar 3 / 4 [3], [39], [42]

Lättare att parallellisera i jämförelse med

OOP 2 / 4 [3], [39]

Lätt att förstå och underhålla koden 2 / 4 [3], [45]

Lätt att testa 2 / 4 [3], [45]

DOD nackdel

Antal artiklar / Totalt antal

artiklar Artikel källa

Tabell 5.5: Visar de tre olika nivåerna framtagna i miljö 2 med hjälp av OOP-simuleringen.

Nivåerna bestämdes genom att development builds skapades med olika antal kuber. Först togs nivå 2 fram då simuleringen laggar vid körningens början men sedan fortsätter utan lagg. Nivå 1 sattes vid 3000 kuber då simuleringen inte visade något påtagligt lagg. Nivå 3 sattes vid 7000 kuber då simuleringen visade mycket lagg under hela körningen.

5.2.2 Mätresultat

För att mätvärdena skulle bli så rättvisa som möjligt stängdes onödiga bakgrundsprocesser ner. Innan själva mätresultatet sparades på respektive nivåer kördes simuleringen 3 gånger för att se att värdena mellan varje gång inte visade för stora avvikelser. Efter detta sparades 5 stycken filer med mätningar på respektive nivå. Väntetiden mellan varje mätning var 1 minut. Detta tidsmått sattes för att varje mätning skulle gå så systematiskt till som möjligt. På dessa fem värden baserar sig medelvärdet. Om någon/några av mätvärdena på samma nivå stack ut för mycket uteslöts det ur medelvärdet då det kan tänkas vara felaktigt. Denna skillnad kan tänkas bero på att datorn kör bakgrundsprocesser.

Profileringsverktyget som användes vid mätningarna hade profilering över processor och minne. ​Från processor profileringen presenteras bilder med grafer över hur många ms processorn spenderar på varje frame. För att se exakt hur många ms processorn spenderar på en specifik frame måste man markera den i grafen. Då ett medelvärde är intressantare så valdes istället att ladda in filen från profilerings verktyget till profiler analyzer som genererar medeltiden som processorn spenderar på varje frame under hela körningen. Grafen är även indelad i olika färger. Dessa färger representerar vad det är som processorn lägger sin tid på. Generellt för alla mätningar är att OOP-mätningarna domineras av orange vilket står för tiden som simuleringen spenderar på fysik motorn (eng. physics engine) Man kan även se på de bilder där ovansidan av grafen syns att grafen är mörkblå i början av mätningarna. Den mörkblå färgen representerar tiden som läggs på att köra scripten. Den ljusgröna färgen allra högst upp i grafen, som endast tar upp en liten del av grafen, representerar grafik renderingen. DOD-mätningarnas

Nivåer Antal kuber

Nivå 1 3000

Nivå 2 5000

grafer är mestadels mörkblå vilket visar att simuleringen spenderar den mesta delen av tiden på att köra scripten. En liten del av grafen högst upp är även ljusgrön vilket visar tiden som läggs på grafik renderingen [47].

Medelvärdet av allokerat RAM-minne lästes av från parametern total system minnesanvändning i minnes profileringen. Denna parameter presenterar den totala storleken på minnet som simuleringen använder enligt operativsystemet [48].

5.2.2.1 Miljö 1

När man körde simuleringen på nivå 1 med 3000 rörliga kuber, dvs experiment OOP/M1/N1, kunde man se att OOP-versionen laggade påtagligt. Detta märktes både i långsamma blinkningar av kuberna samt ryckighet i bilden då kuberna rörde sig. I slutet laggar den mindre men lagget förekom ändå under hela körningen. Även i DOD-versionen, experiment DOD/M1/N1, så blinkade kuberna långsammare samt att kuberna rörde sig ryckigt. Detta märks dock endast i början av simuleringen.

Figur 5.1: Visar diagram över hur många ms processorn spenderar på varje frame på nivå 1, M1/N1. Det övre diagrammet visar OOP-mätningen och de nedre DOD-mätningen.

Vid körningen på nivå 2 med 5000 rörliga kuber, dvs experiment OOP/M1/N2, såg man att OOP-versionen laggar mycket under hela körningen. Detta märks genom att kuberna blinkar ännu långsammare än de gjorde i nivå 1 samt att kuberna är ännu mer ryckiga när de rör sig. Det märks även att simuleringen kör längre tid. Detta då den avslutas efter 600 frames. Även DOD-versionen, experiment DOD/M1/N2, laggar under hela körningen dock mindre än i OOP-versionen.

Figur 5.2: Visar diagram över hur många ms processorn spenderar på varje frame på nivå 2, M1/N2. Det övre diagrammet visar OOP-mätningen och de nedre DOD-mätningen.

På nivå 3 med 7000 rörliga kuber, dvs experiment OOP/M1/N3, såg man att OOP-versionen laggar extremt mycket under hela körningen. Detta märks genom att kuberna inte blinkar alls när kubstrukturen rasar och kuberna är ännu mer ryckiga när de rör sig. Först när kuberna ligger på marken så börjar de blinka. Den absolut ​största ​skillnaden är dock hur länge simuleringen körs för att köra sina 600 frames. ​OOP-Simuleringen som endast körde i 30 sekunder på nivå 1 i denna miljö, kör på denna nivå i 5 min och 48 sekunder. Även DOD-versionen, experiment DOD/M1/N3, visade tydlig laggning under hela körningens gång. Både med långsamma blinkningar, ännu långsammare än föregående DOD-nivå samt ännu mer ryckiga kuber. I DOD-versionen blinkar dock kuberna samtidigt som kubstrukturen rasar. DOD-versionen tar dock endast 39 sekunder att köra. Vilket betyder att OOP-versionen tydligt tappar betydligt fler frames än DOD-versionen gör.

Figur 5.3: Visar diagram över hur många ms processorn spenderar på varje frame på nivå 3, M1/N3. Det övre diagrammet visar OOP-mätningen och de nedre DOD-mätningen.

I tabell 5.6 presenteras det exakta medelvärdet från alla fem mätningar på respektive nivå. Detta medelvärde är den tid, i ms, som processorn lägger under en frame. Dessa fem medelvärden används för att räkna ut ett medelvärde av hur många ms som processorn spenderar på en frame. Detta

finns uppritat i linjediagrammet som presenteras i figur 5.4.

Tabell 5.6: Visar OOP- och DOD-mätningen över processoranvändningen. Mätvärdet visar medelvärdet på hur många ms processorn måste jobba per frame.

Figur 5.4: Visar ett linjediagram över medelvärden från tabell 5.6.

Mätningen av medelvärdet på hur mycket RAM-minne som används vid körningen av applikationen på de tre olika nivåerna finns presenterade i tabell 5.6. De finns även presenterade i ett linjediagram i figur 5.4.

Mätvärdet visar medelvärdet av minnesanvändningen i GB.

Figur 5.5: Visar ett linjediagram över medelvärden från tabell 5.7. 5.2.2.2 Miljö 2

Vid körningen av simuleringen på nivå 1 med 3000 rörliga kuber, dvs experiment OOP/M2/N1, kunde man se att OOP-versionen har lite lagg då kuberna blinkar något långsammare vid simuleringens start. Detta är dock något som ögat inte hade registrerat om man inte hade haft blinkningarna. DOD-versionen, experiment DOD/M2/N1, visade inget lagg.

Figur 5.6: Visar diagram över hur många ms processorn spenderar på varje frame på nivå 1, M2/N1. Det övre diagrammet visar OOP-mätningen och de nedre DOD-mätningen.

Under körningen av av simuleringen på nivå 2 med 5000 rörliga kuber, dvs experiment OOP/M2/N2, kunde man se att OOP-versionen laggar påtagligt vid simuleringens start. Detta märks både genom att blinkningarna går långsammare samt att kuberna rörde sig ryckigt i början då kubbyggnaden

faller. I DOD-versionen, experiment DOD/M2/N2, förekom inget synligt lagg.

Figur 5.7: Visar diagram över hur många ms processorn spenderar på varje frame på nivå 2, M2/N2. Det övre diagrammet visar OOP-mätningen och de nedre DOD-mätningen.

På nivå 3 med 7000 rörliga kuber, dvs experiment OOP/M2/N3, kunde man se att OOP-versionen laggar påtagligt under hela simuleringens körning​. Detta märktes både i långsamma blinkningar av kuberna samt ryckighet i bilden då kuberna rörde sig. Eftersom simuleringen är skriven så att den avslutas efter 600 frames så blev det också en tydlig skillnad i hur länge simuleringen körs. Det är först på denna nivå som man märker av att DOD-versionen, ​experiment DOD/M2/N3, laggar. Detta märks dock bara i början av simuleringen då blinkningarna går långsammare samt att kuberna rör sig lite ryckigt. Den liknar lite OOP-versionens beteende i nivå 2. Om än är DOD-versionen på denna nivå något effektivare. Detta går även att se av mätningarna om man jämför dessa två grafer (dvs figur 5.7:s övre del med figur 5.8:s nedre del).

Figur 5.8: Visar diagram över hur många ms processorn spenderar på varje frame på nivå 3, ​M2/N3. ​Det övre diagrammet visar OOP-mätningen och de nedre DOD-mätningen.

Det exakta medelvärdet från alla fem mätningar på respektive nivå visas i tabell 5.8. Detta medelvärde är den tid, i ms, som processorn lägger under en

frame. Dessa fem medelvärden används för att räkna ut ett medelvärde av hur många ms som processorn spenderar på en frame. Detta finns uppritat i linjediagrammet som presenteras i figur 5.9.

Tabell 5.8: Visar OOP- och DOD-mätningen över processoranvändningen. Mätvärdet visar medelvärdet på hur många ms processorn måste jobba per frame.

Figur 5.9: Visar ett linjediagram över medelvärden från tabell 5.8.

Mätningen av medelvärdet på hur mycket RAM-minne som används vid körningen av applikationen på de tre olika nivåerna finns presenterade i tabell 5.9. Dessvärre ser man att medelvärdet av hur mycket RAM som används (GB) ökar för varje körning. Då denna mätning inte är tillförlitlig så kommer ingen tid läggas på att konstruera ett linjediagram. Dessa värden presenteras här i denna tabell men kommer dessvärre inte kunna användas vidare då de uppenbart är felaktiga. Denna mätning utfördes på Ubuntu 18.04 LTS med Gnome shell 3.28.2. Dessvärre är det en känd bugg att denna version samt senare versioner av Gnome har minnesläckage [49]. Detta är troligtvis

orsaken till de felaktiga mätvärdena. Då tiden för detta examensarbete är begränsad går det dessvärre inte att lägga mer energi på detta.

Tabell 5.9: Visar OOP- och DOD-mätningen över minnesanvändningen. Mätvärdet visar medelvärdet av minnesanvändningen i GB.

5.2.2.3 Miljö 3

Vid körningen av simuleringen på nivå 1 med 3000 rörliga kuber, ​dvs experiment OOP/M3/N1,​ syntes inget lagg i någon av de båda versionerna.

Figur 5.10: Visar diagram över hur många ms processorn spenderar på varje frame på nivå 1, M3/N1. Det övre diagrammet visar OOP-mätningen och de nedre DOD-mätningen.

Under körningen på nivå 2 med 5000 rörliga kuber, ​dvs experiment OOP/M3/N2, kunde man se att OOP-versionen laggade lite i början av körningen. Detta visade sig dock endast i att kuberna blinkade något långsammare i simuleringens början. I DOD-versionen, ​experiment DOD/M3/N2,​ syntes inget lagg.

Figur 5.11: Visar diagram över hur många ms processorn spenderar på varje frame på nivå 2, M3/N2. Det övre diagrammet visar OOP-mätningen och de nedre DOD-mätningen.

Körningen av OOP-versionen på nivå 3, med 7000 rörliga kuber, ​dvs experiment OOP/M3/N3, visade tydlig lagg i början av körningen. Detta visade sig både genom att kuberna blinkade långsammare samt att de rörde sig ryckigare. DOD-versionen, ​experiment DOD/M3/N3, visade dock inget synligt lagg.

Figur 5.12: Visar diagram över hur många ms processorn spenderar på varje frame på nivå 3, M3/N3. Det övre diagrammet visar OOP-mätningen och de nedre DOD-mätningen.

Det exakta medelvärdet från alla fem mätningar på respektive nivå finns presenterade i tabell 5.10. Medelvärdet från dessa mätvärden finns presenterade i linjediagrammet, figur 5.13.

Tabell 5.10: Visar OOP- och DOD-mätningen över processoranvändningen. Mätvärdet visar medelvärdet på hur många ms processorn måste jobba per frame.

Figur 5.13: Visar ett linjediagram över medelvärden från tabell 5.10.

Tabell 5.11 presenterar mätningen av medelvärdet på hur mycket RAM-minne som används vid körningen av applikationen på respektive nivåerna. De finns även presenterade i ett linjediagram i figur 5.14.

Tabell 5.11: Visar OOP- och DOD-mätningen över minnesanvändningen. Mätvärdet visar medelvärdet av minnesanvändningen i GB.

Figur 5.14: Visar ett linjediagram över medelvärden från tabell 5.11.

Från början var meningen att även grafikkortsanvändningen skulle mätas. Detta valdes att utelämnas då GPU-profilern kräver mycket resurser och därför är avstängd som standardläge i profileringsverktyget [50].

Vid körningen av developement builden för DOTS simuleringen dyker ett felmeddelande upp: Could not open file C:/Users/<path to build>/StreamingAssets\livelink-bootstrap for read. Simuleringen körs dock som den ska och detta meddelande är en bugg som inte påverkar någonting [51].

6 Analys

Detta kapitel presenterar en analys av de resultat som finns redovisade i föregående kapitel.

6.1 Systematisk litteraturundersökning

En systematisk litteraturundersökning utfördes för att ta reda på för- och nackdelar med respektive designteknik. Denna metod ska leda fram till svaren på frågorna “vilka kända för- och nackdelar finns det med de respektive teknikerna?” samt “ökar DOD komplexiteten på koden?”.

I OOP-undersökningen där 17 artiklar användes uppgavs den allra vanligaste fördelen vara att OOP möjliggör återanvändning av kod. Denna fördel nämns i 9 av de 17 artiklarna. Just arv som är ett sätt att återanvända kod medför dock även att prestandan försämras. Vilket dessutom var den vanligaste nackdelen som nämndes med OOP, prestandakrävande (11/17). På andra plats, bland OOP:s fördelar, kom lätt att underhålla koden (8/17). Lätt är ju dock ett värdeord så det den ena tycker är lätt kan den andra tycka är svårt och vise versa. Det som uppfattas som lätt eller svårt bottnar ju även delvis i tidigare kunskaper och erfarenheter. Som motpol till denna fördel uppkom även som den andra vanligaste nackdelen att koden har en tendens att bli rörig och kräver därför ordentlig planering samt kunskap (6/17). Återigen så uppkommer ett godtyckligt ord, rörig, i detta sammanhang. Relaterat till denna nackdel var att OOP-program är mycket större än andra program (4/17).

På delad tredjeplats av OOP:s fördelar kom att objekten som används reflekterar den mänskliga verkligheten (6/17) samt säkerhet som representeras bl a i form av inkapsling. Dessa är dock ännu något som bidrar till att OOP blir mer prestandakrävande då objekten som byggs upp använder

Related documents