• No results found

4 Metod

4.2 Alternativa metoder

5.2.9 Mätscript

Mätningen av renderingstiderna använder Date.Now()för att samla in tiden från att data framgångsrikt hämtats från MongoDB till att funktionen som ritar ut heatmaps har körts klart. I figur 33 nedan används beforeSend tillsammans med Date.Now()för att spara tiden före AJAX-förfrågan görs. Värdet sparas sedan som en variabel i local storage.

Figur 33 beforeSend med Date.now()

När generateHeatmap() har laddat klart kallas print_time()funktionen och en ny Date.Now()kallas och skickas in i funktionen. Se figur 32 nedan för hur funktionen ser ut. Funktionen kollar om arrayen innehållande laddningstiderna är mindre än tio, ska tiderna fortsättas läggas in. När tio tider lagts in innehållet rensas local storage. Just talet tio användes under testningen av koden och pilotstudien. Den siffran kommer att varieras i det slutliga experimentet där större mängder tester kommer att genomföras. Den sparade tiden hämtas och tillsammans med sluttiden räknas variabeln measurement ut. Variablen innehåller tiden det tog för data att hämtas och skrivas ut i en heatmap. Tiden sparas i local storage och skrivs även ut i en div på sidan för att göra det möjligt för Tampermonkey scriptet att få tillgång till värdena.

Figur 34 Uträknande av laddningstid för heatmap generering

$.ajax({

url: "http://localhost:3000/data", type: 'GET',

dataType: 'json', // added data type beforeSend: function(){

// get time before GET let get_time = Date.now();

localStorage.setItem("get_time", get_time); },success: function(res) { generateHeatmap(res); generateMarkers(res); } }); function print_time(end_time){ if(array_data.length < 10){

var stored_time = localStorage.getItem("get_time"); var measurement = (end_time - stored_time);

array_data.push(Math.round(measurement)); localStorage.setItem("scrapedData", JSON.stringify(array_data)); //console.log(array_data); document.getElementById('data').innerHTML = array_data.join(" <br> "); document.getElementById('fab-btn').innerHTML = array_data.length ; } else{ console.log('Data finished'); localStorage.clear(); } }

27

Mätningarna på heatmap utritningen görs på samma sätt i både Leaflet och OpenLayers med undantag för att variablerna har andra namn. Se Appendix D och E.

Koden för mätningarna på renderingstider vid zoom skiljer sig lite beroende på om det gäller OpenLayers eller Leaflet, men uppbyggnaden är liknande. I figur 35 illustreras koden som används i Leaflet artefakten.

När ett tryck görs på zoomkontrollerna används Date.now()för att ta en starttid. Därefter används Leaflets inbyggda laddningsfunktion på variabeln tile_layer som innehåller OpenStreetMap plattorna som ska hämtas och laddas in. Laddningsfunktionen kan aktiveras vid olika händelser som loading, load, tileloadstart, tileloadend med fler. Enligt Forest Katsch (2014) används händelsen load när alla plattorna på kartan laddat in. Därför används Date.now()igen för att hämta en sluttid och räkna ut hur lång tid det tog från att zoomknappen trycktes på tills att kartans plattor har renderat klart på den nya zoomnivån. Därefter pushas mätvärdet in i en array kallad scrapedTileData och sparas i local storage.

Figur 35 Mätning av laddningstider vid zoom i Leaflet

I Appendix D, finns koden för den motsvarande funktionen i OpenLayers. Strukturen på koden är väldigt likvärdig och fungerar på samma sätt. Vid klick på zoomknapparna sparas en starttid och vid OpenLayers funktion moveend kallas funktionen zoom_time. Koden inuti funktionen är snarlik den i figur 35 ovan och fyller samma funktion.

$(".leaflet-control-zoom-in").add(".leaflet-control-zoom-out").click(function() { var tile_start = Date.now();

localStorage.setItem("tile_start", tile_start); });

tile_layer.on("load",function() {

if(localStorage.getItem("tile_start") != null){ var tile_end = Date.now();

var stored_time = localStorage.getItem("tile_start"); var completed_tile = (tile_end - stored_time);

tile_data.push(Math.round(completed_tile)); localStorage.setItem("scrapedTileData", JSON.stringify(tile_data)); console.log(tile_data); localStorage.removeItem('tile_start'); document.getElementById('tile_data').innerHTML = tile_data.join(" <br> "); } else {

console.log('Tile Data finished');

localStorage.removeItem('scrapedTileData'); localStorage.removeItem('tile_start'); }

28

Figur 36 POST-förfrågan i Tampermonkey för Leaflet

Laddningstiderna från testerna sparas med hjälp av Tampermonkey. I figur 36 ovan illustreras koden som använts för att hämta laddningstiderna från artefakten. Då resultaten skrivs ut i en div på sidan används två klickfunktioner för att hämta värdena från sidan och skicka vidare till en textfil på wwwlab-servern med ett knapptryck.

5.3 Progression

Experimentet skulle från början använda D3.js för att skapa heatmaps och markörer i OpenLayers respektive Leaflet. Då det visade sig att D3.js endast kunde rendera clustered heatmaps behövdes ett annat alternativ hittas. Alternativet blev heatmap.js för Leaflet och den inbyggda heatmap modulen för OpenLayers. Heatmap.js var tänkt att användas för både Leaflet och OpenLayers, då heatmap.js ska finnas som plugin för båda JavaScript-biblioteken enligt dokumentationen, men under implementationen upptäcktes det inte vara fallet och OpenLayers tycks ha tagits bort som plugin kring år 2012. Senare versioner av OpenLayers har en inbyggd modul för heatmaps som har en liknande struktur och uppbyggnad som heatmap.js. Tillvägagångssätten ansågs vara tillräckligt likvärdiga för att användas i implementationen av artefakterna.

5.3.1 Databas

För att få resultaten från databasen att skrivas ut på klient-sidan testades först en lösning med att skriva ut latitud och longitud i en lista. Testet lyckades, och koordinaterna skrevs ut i ett list element från variablerna #{flood.lat} och #{flood.long}med databindning i Jade, se figur 37 nedan.

(function() { const scraped_url='https://wwwlab.iit.his.se/a17alian/cms/scraped_receiver.php'; function ajaxCall(data) { try { GM_xmlhttpRequest({ method: 'POST', url: scraped_url, data: 'str=' + encodeURIComponent(data), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }); } catch (ex1) { console.log(ex1); } } $("#send_data").click(function() { ajaxCall($("#data").text()); alert('Render data sent'); });

$("#send_zoom_data").click(function() { ajaxCall($("#tile_data ").text()); alert('Zoom data sent');

}); })();

29

Figur 37 Kod för att skriva ut resultaten i en lista

Mycket tid spenderades sedan på att försöka förstår hur variablerna med resultatet kunde kopplas till html-elementen i Jade-filerna. Efter lite efterforskning blev förståelsen att svårigheterna låg i att skicka variablerna med resultatet direkt till HTML-elementen på samma sätt som för list-elementet i föregående figur 37. Nästa steg var då istället att försöka hitta ett sätt att få resultaten till scripten för OpenLayers respektive Leaflet kartorna. Problemet löstes tillslut genom att skapa en databasanslutning i data.js-filen med endpointen /data som returnerade resultaten som JSON. Sedan implementerades AJAX, se föregående figur 23, för att kunna skicka förfrågningar till /data från klient-sidan och därefter kunna använda resultatet för att skriva ut datapunkter i OpenLayers och Leaflet3.

5.3.2 OpenLayers

Vid implementeringen av OpenLayers uppstod problem med i koden från introduktionsguiden (OpenLayers 2020a). Guiden rekommenderar att installera OpenLayers via npm, men när applikationen sedan byggs kommer felmeddelandet i figur 38 upp i konsolen.

Figur 38 Error med npm installation

Trots att koden var identisk med den i introduktionsguiden kvarstod felmeddelandet.

Problemet löstes tillslut genom att använda CDN-länkarna4 till OpenLayers som fanns i kom-

igång guiden (OpenLayers 2020b).

Vid implementation av heatmaps i OpenLayers uppstod svårigheter då exemplet från dokumentationen (OpenLayers 2020c) behövde modifieras för att fungera i artefakten. I exemplet används en URL med KML-data som källa till vektor-lagret. Koden behövde modifieras till att använda ett GeoJSON objekt som källa. Det första som gjordes var att

3https://github.com/a17alian/exjobb_2020/commit/c104fa2

4https://github.com/a17alian/exjobb_2020/commit/6c4c1e1

body

block content ul

each flood, I in floods li#flood_item

#{flood.lat}, #{flood.long})

30

försöka ändra KML URL:en till att använda en GeoJSON fil5, vilket fungerade, se figur 39 för

utritade datapunkter.

Figur 39 Datapunkter med GeoJSON url

Steget därefter var att använda GeoJSON objekt som källa i heatmapLayer. Koden för det hittades i ett annat exempel i dokumentationen (OpenLayers 2020d). Problemet som uppstod då var att varken datapunkter eller felmeddelande skrevs ut. För att undersöka vad som orsakade problemet användes console.log() för att skriva ut värdet i geojsonObject både innanför och utanför toGeoJson funktionen, se figur 40.

Figur 40 Kod från console.log test

Resultatet i konsolen, se figur 41 nedan, visade att loggen som gjordes utanför funktionen returnerar värdet undefined och skrivs även ut innan den första loggen, trots att den ligger längre ned i koden. Loggen som kallas inuti funktionen innehåller det korrekta värdet och returnerar inte undefined.

5https://github.com/a17alian/exjobb_2020/commit/cf4bc33

Function toGeoJson(floods){

for(var i = 0; i < floods.length; i++;){

marker[i] = ol.proj.fromLonLat([floods.[i].long, floods[i].lat]); geojsonObject.features.push(marker[i]); } console.log(‘1’ + geojsonObject.festures[0]); return geojsonObject; } console.log(‘2 ‘ + geojsonObject.features[0]);

31

Figur 41 Resultat i konsolen

Utifrån resultatet av testet kan slutsatsen dras att informationen inte tycks fyllas tillräckligt fort i geojsonObject i for loopen innan objektet sätts som källa i heatmapLayer längre ned i koden, vilket resulterar i att datapunkterna aldrig skrivs ut. Lösningen på problemet var att implementera setTimeout() med en fördröjning på 200 millisekunder för att rita ut

kartkomponenterna6. Fördröjningen är viktig att ha i åtanke när OpenLayers laddningstider

mäts i experimentet. Koden resulterade nu i att datapunkterna skrevs ut men alla hamnade på samma ställe, se figur 42.

Figur 42 Problem med placering av datapunkter

Efter vidare efterforskningar kring problemet upptäcktes felet ligga i kartans projektion. Enligt

Grant Bartel (2017) på StackOverflow

använder view objektet en annan projektion

(EPSG:3857) medans koordinaterna använder en annan (EPSG:4326). Efter att

ol.proj.fromLonLat() lades till 7 för koordinaterna fungerade det att rita ut

datapunkterna på rätt ställe. Viktigt att vara uppmärksam på är att OpenLayers skriver koordinaterna i ordningen longitud först sedan latitud, till skillnad från Leaflet som gör tvärt om.

6https://github.com/a17alian/exjobb_2020/commit/084ffec

32

5.3.3 Leaflet

Implementeringen av Leaflet var till största del problemfri. En svårighet som uppstod var att få koden som stänger av hårdvaruaccelereringen att fungera. Det var otydligt om L_DISABLE_3D = true fungerade eller ej då inget felmeddelande skrevs ut om koden låg på fel plats. För att se om koden fungerade behövdes kart-elementen inspekteras i konsolen. Där gick det att se ifall CSS transformationer användes vid interaktion med kartan.

Figur 43 Kod för att stänga av hårdvaruaccelerering

Om koden för att stänga av hårdvaruaccelereringen ska fungera är det viktigt att se till att koden ligger över Leaflet scripten, se figur 43 ovan.

Vid implementeringen av Heatmap.js med Leaflet uppstod också svårigheter när data från databasen skulle användas istället för testdata. Dokumentationen (Wied 2020b) tillhandahåller exempelkod för att komma igång med heatmaps i Leaflet. I exemplet finns ett objekt kallat testData som innehåller en array med objekt innehållande koordinater. När objektet innehållande testdata användes för att skriva ut datapunkter fungerade det, men inte när data hämtades från databasen. Till en början befarades problemet ligga i hur nya objekt innehållande koordinaterna från databasen skapades i generateHeatmap funktionen, men upptäcktes tillslut finnas i heatmapLayer.setData(). I exemplet från dokumentationen ligger den biten av kod längre ner, men när den flyttades upp inuti generateHeatmap

funktionen kunde datapunkterna skrivas ut med värdena från databasen8.

5.4 Pilotstudie

För att avgöra om artefakterna i experimentet går att mäta och jämföras med varandra genomförs en pilotstudie. Pilotstudien kommer också undersöka om det uppstår svårigheter vid genomförandet av testningen och om mätscripten som skapats fungerar som avsett. Tabell 1 nedan listar hårdvaruspecifikationen för datorn som användes under pilotstudien samt experimentet. 8 https://github.com/a17alian/exjobb_2020/commit/9b0f8f4 doctype html html head title= title link(rel='stylesheet', href='/stylesheets/style.css') script(src="https://code.jquery.com/jquery-3.4.1.js") script(src='/javascripts/heatmap.js') script.

// Disable hardware acceleration for Leaflet L_DISABLE_3D = true;

link(rel='stylesheet', href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css") script(src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js")

33

Tabell 1 Hårdvaruspecifikation

MacBook Pro (Retina, 15 tum, mitten 2015)

Operativsystem macOS Catalina (Version 10.15.4)

Processor 2,2 GHz Quad-Core Intel Core i7

Grafik Intel Iris Pro 1536 MB

Minne 16 GB 1600 MHz DDR3

Testerna i pilotstudien baseras på två av utmaningarna med att visualisera Big Data som listades i föregående kapitel 3 Problemformulering. Skalbarhet i realtid och interaktiv skalbarhet. Ett av delmålen som sattes i början av rapporten var att fastställa en rangordning gällande vilka utmaningar som ska testas först. I följande tabell 2, nedan presenteras en överblick över samtliga mätningar i pilotstudien. ”Alla” datapunkter syftar på 4835 punkter (1.3MB data).

Tabell 2 Mätningar för pilotstudie

Jämförelse Mätning Javascript- Bibliotek

Lager Typ av

interaktio n

Antal datapunkter Ska testa

1 3x10 Leaflet.js Heatmap Markör Töm

cachemin ne & hård inladdning Alla Skalbarhet i realtid 3x10 OpenLayers

2 3x18 Leaflet.js Heatmap Markör Zoom-in Alla Interaktiv

skalbarhet

3x18 OpenLayers

3 3x18 Leaflet.js Heatmap Markör Zoom Ut Alla Interaktiv

skalbarhet

3x18 OpenLayers

5.4.1 Initial rendering

Det enklaste testet att göra är töm cache/hård inladdning då ingen ytterligare implementation utöver mätscriptet behövde göras. Den första jämförelsen ska kopplas till skalbarhet i realtid och mäta hur snabbt data bearbetas innan den skrivs ut. Då det inte finns något kortkommando för att tömma cache och göra en hård inladdning behövdes det göras för hand. Därför gjordes tio inladdningar i tre omgångar. Målet var att testa om det fanns stora variationer för att sedan kunna avgöra om det slutliga experimentet krävde en stor omgång tester eller inte. Om inte värdena spikade allt för mycket kan antalet tester fortsatt hållas relativt låga då inladdningen behöver göras för hand.

I figur 44 nedan redovisas laddningstiderna efter tömd cache och hårdinladdning när heatmap lagret är aktivt. Linjediagrammet visar en stor skillnad på inladdningen med Leaflet och OpenLayers där Leaflet visar en cirka fem gånger snabbare svarstid. Diagrammet visar inga avvikande värden då båda JavaScript-biblioteken presenterar stabila värden.

34

För att få en tydligare inblick i värdenas avvikelser från medelvärdet visualiseras resultaten också i ett stapeldiagram med medelvärde och standardavvikelse. Figur 45 stödjer de stabila standardavvikelserna resultatet i föregående figur 44 då konfidensintervallen är väldigt liten för både OpenLayers och Leaflet.

Figur 44 Laddningstider efter tömd cache/hård inladdning med heatmap lagret

Figur 45 Medelvärde med standardavvikelse vid initial rendering av heatmap

35

Figur 46 visar laddningstiderna efter tömd cache och hårdinladdning när markörlagret är aktivt. I resultatet för markörlagret är laddningstiderna mer likvärdiga då Leaflet mer än dubblerat laddningstiderna från föregående figur, men Leaflet visar fortfarande snabbast tid. Med heatmap lagret visar Leaflet ett stabilare resultat med jämna värden medan OpenLayers resultat är stabilare med markörlagret då Leaflet påvisar små ojämnheter. Ojämnheter som inte spikar drastiskt kommer att behållas. Avvikelserna i Leaflet kurvan resulterar i en marginellt större intervall i stapeldiagrammet, se figur 47, vilket bekräftar ojämnheterna i föregående figur.

Figur 46 Laddningstider efter tömd cache/hård inladdning med markörlagret

Figur 47 Medelvärde med standardavvikelse vid initial rendering av

36

5.4.2 Zoom-in

Nästa test i rangordningen fastställdes redan under implementationen då båda JavaScript- biblioteken inkluderade kontroller för zoom-in och zoom ut. Därför kunde interaktiv skalbarhet i form av zoom mätas utan någon större svårighet. Zoom interaktionen mättes i två steg. Zoom-in mättes genom att sätta kartornas zoomnivå på 18 vilket är längst ut och därefter mäts tiden från att ett klick görs på zoomknapparna till att kartans plattor har laddats in på den nya zoomnivån. Figur 48 nedan redovisar laddningstiderna vid zoom-in med heatmap lagret. Resultaten för zoom-in är betydligt mer ostabila och innehåller både låga och höga laddningstider. Även fast resultaten är ganska varierande finns ett mönster som förklarar varför linjediagrammet ser ut som det gör. Vid en viss zoomnivå slutade JavaScript- biblioteken att läsa in kartans plattor på nytt efter zoom. Variationen mellan höga och låga värden kan också ses i figur 49, nedan där standardavvikelserna för mätningen presenteras. Konfidensintervallen i stapeln för OpenLayers är större än den för Leaflet vilket stämmer överens med föregående figur som tydligt visar att skillnaden mellan OpenLayers lägsta och högsta värde är större än Leaflets.

37

Figur 49 Medelvärde med standardavvikelse vid zoom-in med heatmap lagret

Gällande zoom-in interaktionen med markörlagret som kan ses nedan i figur 50, påvisar Leaflet överlag lägre laddningstider än OpenLayers. Leaflets kurva är också mycket stabilare med mindre toppar och dalar. Det tillhörande stapeldiagrammet i figur 51 bekräftar också resultaten i linjediagrammet. Stapeln för Leaflets medelvärden är betydligt lägre än OpenLayers där Leaflet påvisar laddningstider som är cirka tre gånger snabbare. Konfidensintervallet för OpenLayers är större vilket bekräftas av variationen i det tillhörande linjediagrammet.

38

Figur 51 Medelvärde med standardavvikelse vid zoom-in med markörlagret

5.4.3 Zoom ut

Resultaten för zoom ut med heatmap lagret påvisar signifikanta spikar hos både OpenLayers och Leaflet som avviker från resterande siffror. Orsakerna till varför spikarna uppstod är okända men ett antagande kan göras att det kan orsakats av exempelvis dålig internetuppkoppling. Stapeldiagrammet i figur 53 påvisar relativt stora konfidensintervall till följd av spikarna i figur 52.

39

Figur 53 Medelvärde med standardavvikelse efter zoom ut med heatmap lagret

I figur 54 nedan visas resultaten för laddningstiderna efter zoom ut med markörlagret. Figuren visar att Leaflets inladdningstiderna är lägre än OpenLayers. Resultaten innehåller blandade höga och låga värden. OpenLayers resultatet innehåller ett avvikande resultat med en svarstid på över 3500 millisekunder vilket resulterar i en tydlig spik. Spikar som endast finns en av och som inte tycks vara del av något mönster kommer att tas bort i det slutliga experimentet. Det är en avvikelse som antagligen sker på grund av temporära anledningar som dålig internetuppkoppling, dålig uppkoppling mellan JavaScript-biblioteket och OpenStreetMap eller liknande. Figur 55 presenterar medelvärde med standardavvikelse för zoom ut med markörlagret.

40

Figur 55 Medelvärde med standardavvikelse för zoom ut med markörlagret

Några ytterligare observationer som gjort under pilotstudien gäller mätningarna vid zoom. Mätningar som kommer göras i det slutliga experimentet bör göras på olika delar av kartan. Anledningen till det är att laddningstiderna tycks påverkas baserat på om koordinaterna som zoomas in på ligger på ett ställe med många datapunkter eller inte. Mätningarna under pilotstudien gjordes på Turkiets koordinater då världskartan blev relativt centrerad, men vid in zoomning hamnade vyn inte vid några datapunkter. Det kan ha resulterat i att laddningstiderna blivit lägre än om in zoomningen hade skett på ett område med mycket datapunkter. I det slutliga experimentet ska kartans koordinater centreras på ett ställe med mycket data.

Optimeringar kommer också att göras på Tampermonkey scriptet för att automatisera klicken på zoomknapparna. Då antalet mätningar som gjordes under pilotstudien var relativt låga kunde mätningarna göras för hand, men det slutliga experimentet kommer att kräva fler mätningar och därav behöva automatiseras för att spara tid.

41

6

Utvärdering

Genomförandet av pilotstudien påvisade att testerna som gjordes var genomförbara och att resultaten var jämförbara med varandra. Resultaten av initial rendering efter tömd cache och hård inladdning visade att Leaflet hade snabbare utritningstid för både heatmap och markörlagret. För att ytterligare säkerställa resultaten från pilotstudien kommer flera mätningar att genomföras som utförts under en längre tid. Mätningar som görs under en längre tid är tänkt att garantera ett mer exakt och representativt medelvärde.

Under pilotstudien gjordes en observation gällande zoom-in mätningarna där misstankar fanns att laddningstiderna kan påverkas beroende på om zoom-in interaktionen sker på ett område med många datapunkter eller inte. Fyra stycken testfall kommer att genomföras på båda variationer av artefakten, vilket sammanlagt blir åtta mätserier för att undersöka den teorin.

Tabell 3 Testfall för zoom-in undersökning

Test Testfall Beskrivning

1 Testfall

1.1

Utritning av heatmap efter zoom-in på ett område med få datapunkter med 4835 punkter (1.3MB data)

1 Testfall

1.2

Utritning av heatmap efter zoom-in på ett område med många datapunkter med 4835 punkter (1.3MB data)

2 Testfall

2.1

Utritning av markörer efter zoom-in på ett område med få datapunkter med 4835 punkter (1.3MB data)

2 Testfall

2.2

Utritning av markörer efter zoom-in på ett område med många datapunkter med 4835 punkter (1.3MB data)

Områdena som fokuserades på var Azorerna som är en utanför Portugal i Norra Atlanten och Tuy Hoa som är en stad i Vietnam. Azorerna valdes som område för att testa att zooma in på ett fåtal datapunkter då det ligger i Norra Atlanten utan några omkringliggande punkter och Tuy Hoa valdes för att området omkring innehåller många datapunketer även in på en låg zoomnivå.

Figur 56 Azorerna (vänster) och Tuy Hoa (höger) på kartan

Resultatet av testet påvisade att laddningstiderna blev något högre när kartan zoomade in på området med minst datapunkter. Figur 57 nedan visar att laddningstiderna blev högre för

42

området med minst datapunkter i Leaflet med markörlagret. Detsamma gällde även heatmap lagret. Då resultatet påvisar en knapp märkbar skillnad tycks inte området som zoomas in på att ha någon markant påverkan, men för att få resultaten i alla mätningar så likvärdiga som möjligt kommer alla genomföras på samma punkt.

Figur 57 Leaflet zoom-in testresultat

För att göra mätningarna mer automatiserade jämfört med pilotstudien behövde testerna skrivas om. På grund av att det blev alldeles för svårt att genomföra den stora mängd mätningarna som behövdes göras för slutexperimentet med tömd cache hård inladdning som

Related documents