PDA

View Full Version : MGMapsista (mutta enemmän Java vs C++ optimoinnista)


zimon
13.02.08, 01:49
Tämän voisi kai siirtää "Asian vierestä" osioon, koska niin paljon OT:ta jo. Voi sitten jossain vaiheessa MGMapsista uuden ketjun laittaa jossa ohjeet miten kartat PC:lla ladataan verkossa ja pistetään puhelimen muistiin, tai miten MGMapsin navigointia käytetään.

http://www.mgmaps.com/download.php

En tiedä miten uusi ominaisuus on tuo että tallettaa haetut kartat muistikortille, mutta itse vasta huomasin.

Muutenkin tuntuu olevan melko hyvä GPS-karttaohjelma, osiltaan parempi kuin Nokian oma Maps (jopa v2.0 beta).
http://www.mgmaps.com/doc.php#usage

Mahdollistaa mm. KLM-tiedostojen näyttämisen kartalla puhelimessa suoraan, eli esim tuollaisen minkä SportsTracker osaa outputata.

Vielä kun saavat tuohon reitinhaun ja sen "Seuranta-ominaisuuden" jonka Nokia törkeästi Maps:sta poisti jälkeenpäin (n95:n ennen syksyä ostaneita ajatellen), ja PC-sovelluksen jolla karttoja voi cachettaa suoraan muistikortille kotonaan ennen reissua, niin alkaa olla loistava ohjelma.
edit: MGMapsissa on Seuranta-ominaisuus, eli reitin haku ja piirtäminen kartalle kahden pisteen välillä. Onnistuu jos target-piste on Favoriteissa nimettynä. Ja karttojen etukäteen talletus muistikortillekin on siis jo toteutettu.

Lisäksi MUTU on sellanen, kun tämäkin on Javaa, että mielummin sitä pitää muutamaa Java-sovellusta jatkuvasti käynnissä luurissa, kuin muutamaa S60-natiivisovellusta. S60-natiivisovellukset tuntuu syövän RAM-muistin loppuun paljon nopeammin, vaikka luulisi että niissäkin hyvin paljon koodia on jaettu kirjastoista.

Yksi Nokia Mapsiinkin toivomani ominaisuus tuossa MGMapsissa on myös: voi näytön kääntää kaikkiin neljään suuntiin, eli esim N95:ssa jossa GPS-antenni on luurin pohjassa, voi heikoissa olosuhteissa olla apua kääntää näyttö 180 astetta ja pitää näppäimistö auki ylöspäin, jolloin antenni sojottaa esteettä ylöspäin kädessä. (käännön pikanäppäin on 7)

diiptoitl
13.02.08, 10:05
Ei pysty klm-muodossa tallennettuja reittejä katselemaan.

edit: No places tulee kun yrittää noita availla

sovelias
13.02.08, 10:24
Lisäksi MUTU on sellanen, kun tämäkin on Javaa, että mielummin sitä pitää muutamaa Java-sovellusta jatkuvasti käynnissä luurissa, kuin muutamaa S60-natiivisovellusta. S60-natiivisovellukset tuntuu syövän RAM-muistin loppuun paljon nopeamminNiin no, pelkkä virtuaalikoneen vie monessa koneessa RAM muistia senverran että siihen tilaan mahtuisi liuta natiiveja sovelluksia. Tosin tuoreimmissa alustoissa/koneissa virtuaalikoneet ja muistin hallinta kehittyneet paljon (ja uusissa koneissa muistia reippaasti enemmän), eli tuoreissa koneissa muistiongelmat vähäksi aikaa historiaa, kunnes joku devaaja päättää sen ulosmitata.

Toki jos vertaa rekkan kulutusta mopoon, eli esim. Natiivia selainta, proxy pohjaiseen java selaimeen.

Cythraul
13.02.08, 15:19
Vielä kun saavat tuohon reitinhaun ja sen "Seuranta-ominaisuuden" jonka Nokia törkeästi Maps:sta poisti jälkeenpäin (n95:n ennen syksyä ostaneita ajatellen), ja PC-sovelluksen jolla karttoja voi cachettaa suoraan muistikortille kotonaan ennen reissua, niin alkaa olla loistava ohjelma.

Ai kuten gmapmakerin? Ongelmahan tässä on se että googlen kartat koostuvat älyttömästä määrästä pieniä tiedostoja, jotka muistikorttien antiikkisessa tiedostojärjestelmässä vievät enemmän tilaa kuin mikä niiden koko oikeasti on. Josta seuraa että varsinkaan tarkimmilla zoomaustasoilla ei 2 gigan kortille mahdu kuin pari kaupunkia kerrallaan. Ja kymmenien tuhansien tiedostojen liikuttelu Vistassa ei ole kaikkein hauskin mahdollinen kokemus -- saisi se SP1 tulla hiljalleen...

Muutenhan niitä tarkimpia tasoja ei edes tarvitsisi mihinkään, mutta kun monissa paikoissa detaljeja (kauppoja, mäkkäreitä yms.) tulee näkyviin vasta jossain toisiksi lähimmässä zoomissa.

Lisäksi MUTU on sellanen, kun tämäkin on Javaa, että mielummin sitä pitää muutamaa Java-sovellusta jatkuvasti käynnissä luurissa, kuin muutamaa S60-natiivisovellusta. S60-natiivisovellukset tuntuu syövän RAM-muistin loppuun paljon nopeammin, vaikka luulisi että niissäkin hyvin paljon koodia on jaettu kirjastoista.

MGmaps ei ainakaan omalla N95:lla pysy samaan aikaan käynnissä kameran tai (myös javapohjaisen) dictionaryformids-sanakirjan kanssa, mikä itseäni ainakin harmittaa jonkun verran. Mulla tosin on pari ylimääräistä koko ajan päällä olevaa taustalla, eli jollain muulla voi ehkä toimia.

zimon
13.02.08, 18:27
Niin no, pelkkä virtuaalikoneen vie monessa koneessa RAM muistia senverran että siihen tilaan mahtuisi liuta natiiveja sovelluksia. Tosin tuoreimmissa alustoissa/koneissa virtuaalikoneet ja muistin hallinta kehittyneet paljon (ja uusissa koneissa muistia reippaasti enemmän), eli tuoreissa koneissa muistiongelmat vähäksi aikaa historiaa, kunnes joku devaaja päättää sen ulosmitata.


Esim tässä nimenomaisessa tapauksessa, MGMaps kuluttaa Java-virtuaalikoneineen vähemmän RAM-muistia kuin Nokia Maps. Ja kun virtuaalikone on sitten ladattuna jo muistiin, niin lisä java-sovellukset taustalle eivät niin paljon haittaa.

Katsoin Y-Tasks Memory profilerilla, eli se itsessään jo lataa S60-natiivikirjastoja muistiin aika tavalla josta Nokia Maps voi hyötyä muistinkulutuksessaan:

Traced with Y-Tasks' Trace in N95: free/total RAM memory (memory consumption)
MGMaps running: 18681856/58720256 = 32% (-4648960)
MGMaps exited: 23851008/58720256 = 41%
Talktimer started and running: 21979136/58720256 = 37% (-1351680)
Talktimer & MGMaps running: 16900096/58720256 = 29% (-6430720)
MGMaps running, Talktimer exited: 18771968/58720256 = 32% (-4558848)
MGMaps exited: 23777280/58720256 = 40%
Talktimer started and running: 22048768/58720256 = 38% (-1282048)
Talktimer exited: 23371776/58720256 = 40%
Nokia Maps started and running: 17420288/58720256 = 30% (-5910528)
Nokia Maps exited: 22323200/58720256 = 38%

When no MGMaps, Talktimer or Nokia Maps were running, avg free memory:
23330816, values in parenthesis are memory consumption compared to this avg.

Talktimer and MGMaps are Java-applications. Nokia Maps is a native S60 application.

MGMaps vie Java-virtuaalikoneineen siis noin 4.6 MB.
Jos toinen Java-sovellus (Talktimer) käynnistetään taustalle, muistia kuluu lisää 1.8 MB. Sikäli hassua, että jos ainoastaan Talktimer on käynnissä, niin muistia kuluu 1.3 MB. Selvästikään Java-virtuaalikoneesta ei ladata koko konetta muistiin, vaan muistinhallinta tosiaan osaa ajaa sitä koodia ilmeisesti FLASH-muistilta suoraan.

Nokia Maps kulutti RAM-muistia 5.9 MB, eli 1.3 MB enemmän mitä MGMaps Java-virtuaalikone-instansseineen.

(offtopic alkaa)
Java-bytekoodi on tiiviimpää (korkeamman tason) kieltä kuin S60 natiivikonekieli, joten samalla tavumäärällä saadaan enemmän aikaan. Ja kun Java-virtuaalikonekin on saatu fiksuksi muistinhallinnaltaan näköjään, niin edelleen voimassa on MUTU että Java-sovellukset on parempi vaihtoehto luurissa taustalla oleviksi muistinkulutukseltaan. Siinä ikäänkuin pakotetaan uudelleenkäyttämään Java-kirjastoissa olevaa koodia korkeammalla tasolla, mitä S60-natiivisovelluksissa.

Ihan esimerkkinä, sama asia tehtynä Javalla ja C/C++:lla vie yleensä vähemmän kooditilavuutta, selvästi enemmän toiminnallisuutta tulee siis "ilmaiseksi" jostain piilosta Java-sovellukseen.
Ja mitä monimutkaisempia ja enemmän korkean tason olioita vaativia sovelluksia, sitä enemmän Java hyötyy. Hyötyy myös nopeudessa, jos Java-virtuaalikone on tarpeeksi kehittynyt ja osaa optimoida lennossa koodia paljon tehokkaammin mitä konekielelle koskaan voidaan tehdä.
(offtopic loppuu)


Ei pysty klm-muodossa tallennettuja reittejä katselemaan.
edit: No places tulee kun yrittää noita availla

Huomasin saman. Pystyy näyttämään vaan klm-tiedostossa olevia paikkamerkintöjä, ei reittimerkintöjä. Eiköhän reititkin ole tulossa, koska jo alkuun KLM-tiedostojen parsimisessa on päässyt.


Ai kuten gmapmakerin? Ongelmahan tässä on se että googlen kartat koostuvat älyttömästä määrästä pieniä tiedostoja, jotka muistikorttien antiikkisessa tiedostojärjestelmässä vievät enemmän tilaa kuin mikä niiden koko oikeasti on.

Se onkin FAT-tiedostojärjestelmän lähes pahin heikkous. Saisi Nokia tukea EXT2:sta, niin päästäisiin tuosta ongelmasta. Nyt tuokin tekijä joutunee kiertämään FAT:n heikkouden laittamalla pikku kartanpalaset esim zip-tiedostoon, jota Java tukee ihan heittämällä.

Tuo MGMaps tukee myös jollakin tavalla custom-karttoja. En vielä ole selvittänyt miten. Jos joku jo tietää, voisi kertoa.

Cupero
13.02.08, 18:59
Tuo MGMaps tukee myös jollakin tavalla custom-karttoja. En vielä ole selvittänyt miten. Jos joku jo tietää, voisi kertoa.

Microsoftin MapCruncherin avulla saa esimerkiksi maastokartat toimimaan MGMapsissa. Asiasta löytyy ketju ohjelman foorumilta.

Toinen vastaavaa ohjelma, jossa pystyy käyttämään yhtä aikaa omia karttoja ja online-karttoja, on MapNav http://mapnav.spb.ru
Omien karttojen kalibrointi osottautui kinkkisemmäksi kuin MGMapsissa, mutta esimerkiksi kuljettu jälki näkyy ohjelmassa.

hiphei
13.02.08, 21:19
(offtopic alkaa)
Hyötyy myös nopeudessa, jos Java-virtuaalikone on tarpeeksi kehittynyt ja osaa optimoida lennossa koodia paljon tehokkaammin mitä konekielelle koskaan voidaan tehdä.
(offtopic loppuu)
OT: Konekielellä ei nykyisin tehdä muuta kuin korkeintaan pala boottikoodia. Ja se Java-runtimea ajetaan Symbianin päällä, joten suorituskyvyssä se ei siksi hyödy.
Symbian on Java (pdf) (http://www.symbian.com/files/rx/file7415.pdf)

zimon
13.02.08, 22:47
OT: Konekielellä ei nykyisin tehdä muuta kuin korkeintaan pala boottikoodia. Ja se Java-runtimea ajetaan Symbianin päällä, joten suorituskyvyssä se ei siksi hyödy.
Symbian on Java (pdf) (http://www.symbian.com/files/rx/file7415.pdf)
OT jatkuu
Käytännössä C/C++ ohjelmat ovat konekielellä koodisivuilla. Siis samankokoinen koodisivu konekieltä (C/C++ kieltä) sisältää vähemmän logiikkaa ja toimintaa mitä Java-bytekoodi.

Ohjelman koodin uudellenkäyttöaste Javassa on siis suuremmalla tasolla. Ensin bytekoodi käyttää Java-virtuaalikoneen ja Java-kirjastojen jaettua koodia, jonka jälkeen vielä Java-kirjastot ja -virtuaalikone käyttää Symbianin ohjelmakirjastoja.
Koodia tulee yhteiskäytettyä ja jaettua koodarin tietämättäänkin paljon enemmän mitä C/C++.

Yksinkertaistettu esimerkki:
On tiiviimpää sanoa vain MKJTV robotille, kuin sanoa "nouse seisomaan, nosta vasenta jalkaa, vie sitä eteenpäin, astu alas, ......, ota voipaketti hyllyltä, ...., ota tuote hihnalta, laita se muovikassiin ....... jne.", vaikka jälkimmäinen kompressoitaisiin.

Tässä Bot-virtuaalikone tietää että bytekoodi-käskyt M=mene, K=kauppa, J=jonnekin, T=tuo, V=voi

Ja mitä tulee Java-koodin optimoimiseen verrattuna C/C++/Assembly kieleen, niin modernit Java-kääntäjät ja -tulkki voi tehdä paljon sellaisia optimointitemppuja joita C-kääntäjä tai Assembleri ei koskaan voi tehdä, ja siten teoriassa ja myös joissain tapauksissa käytännössä jo Java-ohjelma tomii nopeammin kuin C/C++-ohjelma. Tulevaisuudessa kun lisätään Java-virtuaalikoneeseen ajoaikaista profilointia ja optiomointia, Java vaan nopeutuu lisää. Java-kielen osoittemuus ja roskienkeruu mahdollistaa koodin ja datan uudelleenjärjestelyn ja morphauksen ajoaikana. Sitä ei voi C/c++/Asembly/konekielelle tehdä osoittimien vuoksi.

hiphei
14.02.08, 01:09
Ja mitä tulee Java-koodin optimoimiseen verrattuna C/C++/Assembly kieleen, niin modernit Java-kääntäjät ja -tulkki voi tehdä paljon sellaisia optimointitemppuja joita C-kääntäjä tai Assembleri ei koskaan voi tehdä, ja siten teoriassa ja myös joissain tapauksissa käytännössä jo Java-ohjelma tomii nopeammin kuin C/C++-ohjelma.
Juu juu... on se kumma juttu kun sitten kaikkea maailmassa ei tehdä Javalla... mihin tässä enää sitten muita kieliä tarvitaankaan... etenkin kun se Java-virtuaalikone on nimenomaan tehty ja käännetty C++:lla siihen puhelimeen...
Mikään universaali tulkattava kieli, jota emuloidaan toisen ohjelmointikielen päällä ei voi olla yhtään nopeampaa kuin suoran natiiville käyttöjärjestelmälle koodattu. Virtuaalikoneen tarjoamien muistirakenteiden kautta aloittelijakin voi saada aikaiseksi tehokkaampaa koodia, mutta ei mitään sellaista mitä ei pystyisi natiivilla käyttöjärjestelmän kielellä tekemään. Javalla koodatessa on vain vaikeampaa ottaa huomioon käyttöjärjestelmän ja prosesssorin erityispiirteitä, koska siinä välissä on enemmän wrappareita.

zimon
14.02.08, 01:45
Juu juu... on se kumma juttu kun sitten kaikkea maailmassa ei tehdä Javalla... mihin tässä enää sitten muita kieliä tarvitaankaan... etenkin kun se Java-virtuaalikone on nimenomaan tehty ja käännetty C++:lla siihen puhelimeen...
Mikään universaali tulkattava kieli, jota emuloidaan toisen ohjelmointikielen päällä ei voi olla yhtään nopeampaa kuin suoran natiiville käyttöjärjestelmälle koodattu. Virtuaalikoneen tarjoamien muistirakenteiden kautta aloittelijakin voi saada aikaiseksi tehokkaampaa koodia, mutta ei mitään sellaista mitä ei pystyisi natiivilla käyttöjärjestelmän kielellä tekemään. Javalla koodatessa on vain vaikeampaa ottaa huomioon käyttöjärjestelmän ja prosesssorin erityispiirteitä, koska siinä välissä on enemmän wrappareita.

Lyhyesti näin myöhään; olet väärässä.
http://www.kano.net/javabench/
http://www.kano.net/javabench/data

hiphei
14.02.08, 10:56
Lyhyesti näin myöhään; olet väärässä.
En ole. Ja tuossa vähän perusteellisempia linkkejä:
http://en.wikipedia.org/wiki/Comparison_of_Java_and_C%2B%2B
http://www.javaworld.com/jw-02-1998/jw-02-jperf.html
Ja sitten on vielä syytä muistaa, ettei nuo PC-maailmassa saadut suhteellisen tasavertaiset suorituskykytulokset päde mobiililaitteille, joissa ei sitä JIT:iä sitten löydykään.

sovelias
14.02.08, 21:18
Esim tässä nimenomaisessa tapauksessa, MGMaps kuluttaa Java-virtuaalikoneineen vähemmän RAM-muistia kuin Nokia MapsTaitaa olla toinen muutenkin raskaampi, ja toki riippuu testiympäristöstä.

MGMaps vie Java-virtuaalikoneineen siis noin 4.6 MB.
Jos toinen Java-sovellus (Talktimer) käynnistetään taustalle, muistia kuluu lisää 1.8 MB. Sikäli hassua, että jos ainoastaan Talktimer on käynnissä, niin muistia kuluu 1.3 MB.En tiedä millä ajoit testin. ehkä sellaisella alustalla jossa ei tarvitse ladata RAMiin kaikkea, tosin jos sinusta on hienoa että pienen java kikkareen käynistäminen on hidasta ja sen lisäksi vie yli puolitoista megaa tilanteessa jossa javavirtuaalikone on jo kerran käynnistetty ilmeisesti suht hyvällä S60 java alustalla.

S60 3rd FP1 koneella.

Talktimen käynnitys reilu 5MB

Talktimen käynnissä olessa MGMmapsin käynnisty
vie vielä lisää RAMi vajaa 6MB

Niin ja samaisella koneella Nokia Mapsin käynnistys vie vajaa 5MB

Kokeiles paljonko natiivi laskin, ja paljonki jokin J2mE laskin ....

Minusta java on hieno homma, mutta ei sillä mitään taivasta ole, mutta helpottaa jonkinverran devaajan touhuja.

zimon
14.02.08, 23:23
OFFTOPICia vahvasti, mutta pitää perustella miksi GPS-navigaatio-ohjelman tekeminen Javalla ei ole yhtään huono idea.


Mikään universaali tulkattava kieli, jota emuloidaan toisen ohjelmointikielen päällä ei voi olla yhtään nopeampaa kuin suoran natiiville käyttöjärjestelmälle koodattu. Virtuaalikoneen tarjoamien muistirakenteiden kautta aloittelijakin voi saada aikaiseksi tehokkaampaa koodia, mutta ei mitään sellaista mitä ei pystyisi natiivilla käyttöjärjestelmän kielellä tekemään. Javalla koodatessa on vain vaikeampaa ottaa huomioon käyttöjärjestelmän ja prosesssorin erityispiirteitä, koska siinä välissä on enemmän wrappareita.

Jos luit antamasi linkit ymmärtävästi, huomannet olleesi väärässä edellisessä.

Java nimenomaan voi olla ja on nopeampi C++:sta ja C:sta käännettyjä ohjelmia joissakin asioissa.
http://en.wikipedia.org/wiki/Comparison_of_Java_and_C%2B%2B#Performance

Juttu johtuu em. asiasta, jossa C++/C/konekielen osoittimien käyttö estää optimoinnin tapauksissa jossa koodia tai dataa kannattaisi siirtää eri järjestykseen ja paikkaan ajoaikana, jotta se mahtuu vaikka L2 cacheen jatai jokin ehdollinen koodi suoritetaan usein ja vie paljon aikaa, mutta järjestämällä ehtolauseet uudestaan tuo sama koodi suoritetaankin harvoin.

Tälläinen ajoaikainen optimointi ei ole riippuvainen siitä onko käytössä JIT-tulkki vai ei.

Yksinkertainen esimerkki jossa selviää osoittimien aiheuttama ongelma optimoinnissa:

Kuvittele looppia, jossa seuraava koodi tehdään vaikka N*24*60*60*25*640*480 kertaa

JOS lohkoA && lohkoB && lohkoC on TOTTA, TEE
lohkoD
MUUTEN TEE
lohkoE


Lohkot on esim koodilohkoja, funktio tai metodikutsuja tms. koodia.

Koodilohkot A, B, ja C sekä lohkot E ja F olkoon kaikki sellaisia joiden suhteellista ajoaikaa ei pysty ennustamaan koodatessa, koska ne riippuu vaikka käyttäjän asetuksista, WLAN-verkon ruuhkautumisesta yms. epädeterministisistä seikoista.

Ohjelman ajoaikana JVM profiloi että lohkoA vie suoritusaikaa 10 aikayksikköä ja on totta tilastollisella todennäköisyydellä 30%, lohkoB vie 3 aikayksikköä ja on totta tilastollisesti 15% ja lohkoC vie 5 aikayksikön ja on tosi 80%:sti.

(jos laskin oikein nopeasti), painotetut keskiarvot miten paljon menee aikaa tuossa ehtolausekkeessa on siten järjestyksestä riippuen seuraavat:
ABC 11.06 aikayksikköä
ACB 10.74
BAC 4.6
BCA 3.75
CAB 12.62
CBA 7.74

Joten JVM:n kannattaa ajoaikana optimoida koodia niin, että suoritetaankin metodit ehtolausekkeessa järjestyksessä: lohkoB, lohkoC, lohkoA.
Se voi sen tehdä, koska Javassa ja sen bytekoodissa lohkoissa ei ole osoitteita muuttujiin, funktioihin ja metodeihin, vain referenssejä.

Kaikki suuret ja sisimmät luupit kannattaa profiloida ja uudelleenjärjestellä, mutta vasta ajoaikana tiedetään miten hitaita tai nopeita mitkäkin toiminnot koodissa on.

Samaa uudelleenjärjestelyä voidaan tehdä olioille ja muille muistirakenteille. Profiloidaan mitä olioita käytetään yleensä lähekkäin ajallisesti, joten ne kannattaa JVM:n järjestää muistiroskien-kerääjällä fyysisesti lähekkäin toisiaan, jolloin CPU:n cacheen tulee vähemmän cache-missejä.

Kummatkin optimoinnit ovat mahdottomia konekieleksi käännetyllä koodilla, mitä c/C++:sta käännetyt ohjelmat ovat. Tai no voidaan tehdä konekielitasolla koodimorphausta, mutta se sitten menee jo niin monimutkikkaaksi että tuhlataan aikaa.

Lisäksi Javalla koodatessa ei tarvitse huomioida käyttöjärjestelmän ja prosessorin erityispiirteitä. Jos JVM on kunnolla tehty, se osaa optimoida käynnistyshetkellä ko. alustalle, esim optimoida tietyn kokoiselle L2-cachelle ja käyttää CPU:n sisäisiä rekisterejä viisaasti.

Java-ohjemille voidaan tehdä paljon optimointeja käännösaikana, käynnistysaikana sekä ajoaikana, joita c/C++/Assembly-ohjelmille ei voida tehdä.

Näistä syistä johtuvat noi tulokset, joissa ihan oikeasti Java tietyissä tehtävissä on nopeampi kuin c/C++, vaikka se äkkiäajateltuna tökkiikin maalaisjärkeä vastaan:
http://members.lycos.co.uk/wjgoh/Java%20vs%20C%20benchmarks.doc
(tuoreempi kielien benchmark kuin edellinen mainittu)

Tulevaisuudessa varmasti myös mobiililaitteissa JVM:ssa on yhä enemmän ajoaikaista optimointia, koska niin vaan kannattaa tehdä. Säästää akkuakin mitä tehokkaammin koodia ajetaan ja optimoidaan.

Optimointien lisäksi taaskin kun Javassa ei käytetä osoitteita, muistiroskien kerääjä voi tiivistää käytettyjä muistialueita niin ettei tapahdu muistin fragmentoitumista, eli samalla tavalla defragmentoida mitä FAT/NTFS-levylle joutuu tekemään. Mm. Firefoxin yms. c/C++:lla tehtyjen pitkään ajettavien ohjelmien muistinvuotamiset osaksi johtuvat muistin fragmentoitumisesta, kun jatkuvasti pienikokoisia olioita luodaan ja tuhotaan sieltä täältä, mutta elävänä olevien olioiden paikkaa muistissa (heap:ssa) ei voida muuttaa.

Javalla ei kannata tehdä kaikkea, esim. laiteajureita, koska ne yleensä ovat niin yksinkertaisia ettei korkean tason kielestä ole apua ja jouduttaisiin jokatapauksessa menemään konekielimoduleihin Javan JNI-metodien kautta kun käytetään laitteen rekistereitä suoraan.

zimon
14.02.08, 23:45
En tiedä millä ajoit testin. ehkä sellaisella alustalla jossa ei tarvitse ladata RAMiin kaikkea, tosin jos sinusta on hienoa että pienen java kikkareen käynistäminen on hidasta ja sen lisäksi vie yli puolitoista megaa tilanteessa jossa javavirtuaalikone on jo kerran käynnistetty ilmeisesti suht hyvällä S60 java alustalla.

N95 (S60 3rd FP1) ja muistinkulutuksen mittaamiseen käytin Y-tasks ohjelman Trace-modulilla.
http://www.drjukka.com/YTasks.html


Kokeiles paljonko natiivi laskin, ja paljonki jokin J2mE laskin ....

pitää ensin asentaa joku natiivi funktiolaskin. Käytössä erinomainen Java-funktiolaskin nimeltä Calc.
http://midp-calc.sourceforge.net/Calc.html

Toki kun testit tein, niin olin jo luurin boottaamisen jälkeen käyttänyt Java-ohjelmia, joten ei tiedä paljon siellä JVM:sta oli jäänyt roikkumaan. Voisi olla hyödyllistä ajaa kaikki testit suoraan bootin jälkeen, mutta toisaalta jos Java ohjelmaa kerrankin luurissa kuitenkin käyttää, niin tavallaan se JVM on pakollinen muistinkuluttaja.

Kuitenkaan mittaushetkellä ei ollut muita Java-ohjelmia ajossa, ellei sitten S60:ssa itsessään ole jotain java-kikkareita piiloprosesseina.

marko69
15.02.08, 08:12
OT jatkuu.
OFFTOPICia vahvasti, mutta pitää perustella miksi GPS-navigaatio-ohjelman tekeminen Javalla ei ole yhtään huono idea.
Yksinkertainen esimerkki jossa selviää osoittimien aiheuttama ongelma optimoinnissa:

Kuvittele looppia, jossa seuraava koodi tehdään vaikka N*24*60*60*25*640*480 kertaa


Lohkot on esim koodilohkoja, funktio tai metodikutsuja tms. koodia.

Koodilohkot A, B, ja C sekä lohkot E ja F olkoon kaikki sellaisia joiden suhteellista ajoaikaa ei pysty ennustamaan koodatessa, koska ne riippuu vaikka käyttäjän asetuksista, WLAN-verkon ruuhkautumisesta yms. epädeterministisistä seikoista.

Ohjelman ajoaikana JVM profiloi että lohkoA vie suoritusaikaa 10 aikayksikköä ja on totta tilastollisella todennäköisyydellä 30%, lohkoB vie 3 aikayksikköä ja on totta tilastollisesti 15% ja lohkoC vie 5 aikayksikön ja on tosi 80%:sti.

(jos laskin oikein nopeasti), painotetut keskiarvot miten paljon menee aikaa tuossa ehtolausekkeessa on siten järjestyksestä riippuen seuraavat:
ABC 11.06 aikayksikköä
ACB 10.74
BAC 4.6
BCA 3.75
CAB 12.62
CBA 7.74

Joten JVM:n kannattaa ajoaikana optimoida koodia niin, että suoritetaankin metodit ehtolausekkeessa järjestyksessä: lohkoB, lohkoC, lohkoA.
Se voi sen tehdä, koska Javassa ja sen bytekoodissa lohkoissa ei ole osoitteita muuttujiin, funktioihin ja metodeihin, vain referenssejä.

Kaikki suuret ja sisimmät luupit kannattaa profiloida ja uudelleenjärjestellä, mutta vasta ajoaikana tiedetään miten hitaita tai nopeita mitkäkin toiminnot koodissa on.

Huono esimerkki. C/C++ takaa, että ehtolausekkeet tehdään tietyssä järjestyksessä (vasemmalta oikealle) ihan senkin vuoksi, että ehdossa a voidaan muuttaa jotain yhteistä arvoa ja ehdossa b sitä samaa arvoa käytetään (singleton pattern, globaalit, tietokanta, muut tiedostot jne.). Tämän vuoksi ehtojen suoritusjärjestyksen muuttamisesta seuraa arvaamatonta käyttäytymistä.

Tulevaisuudessa varmasti myös mobiililaitteissa JVM:ssa on yhä enemmän ajoaikaista optimointia, koska niin vaan kannattaa tehdä. Säästää akkuakin mitä tehokkaammin koodia ajetaan ja optimoidaan.

Natiivikääntäjät ei kehity?

Optimointien lisäksi taaskin kun Javassa ei käytetä osoitteita, muistiroskien kerääjä voi tiivistää käytettyjä muistialueita niin ettei tapahdu muistin fragmentoitumista, eli samalla tavalla defragmentoida mitä FAT/NTFS-levylle joutuu tekemään. Mm. Firefoxin yms. c/C++:lla tehtyjen pitkään ajettavien ohjelmien muistinvuotamiset osaksi johtuvat muistin fragmentoitumisesta, kun jatkuvasti pienikokoisia olioita luodaan ja tuhotaan sieltä täältä, mutta elävänä olevien olioiden paikkaa muistissa (heap:ssa) ei voida muuttaa.

Symbian-SDK:ssa on muistinkäsittelyyn liittyviä funktioita joilla esim. fragmentoitumisesta päästään eroon. Huonoa koodaamista sekään ei tietysti pelasta.

Ihan näppituntumalta sanoisin, että Javalla tai muilla tulkkeihin perustuvilla ohjelmointikielillä ei päästä samoihin lopputuloksiin suorituskyvyllisesti kuin hyvin suunnitelluilla ja eritoten koodatuilla natiivisovelluksilla any time soon.

sovelias
15.02.08, 08:13
N95 (S60 3rd FP1)Ilmeisesti tuoreimmalla julkisella softalla? muuten tuloksesi tuntuvat oudoilta. mikä oliko Nokian Maps vakio, vai päivitelty, esim beta 2?
pitää ensin asentaa joku natiivi funktiolaskin. Käytössä erinomainen Java-funktiolaskin nimeltä Calc.Jos java talktimer käynnissä ja sen jälkeen käynnistää tuon ehdottamasi laskimen niin taitaa RAM hävitä parinmegan luokkaa (yksinään käynnistettäessä 4-5MB väliin), määrästä voi olla montaa mieltä jos vertaa esim Chua Welicin cCalc ohjelmaan joka vie neljänneksen (n.0.5MB) RAMia, ja kymmenes osan riippuen vähän mihin verrataan.
OFFTOPICia vahvasti, mutta pitää perustella miksi GPS-navigaatio-ohjelman tekeminen Javalla ei ole yhtään huono idea.ei, varsinkin kustannuskriittisissä projekteissa, ja joillekkin alustoille ainoa vaihtoehto. Kuitenkin jostain hassusta syystä parhaat autonavigointi sovellukset ovat olleet natiiveja, vaikka java toteutuksiakin on ollut markkinoilla. ja vastoin sinun muistiajatuksia, niin tehottomus ja muistiongelmat ovat hankaloittaneet java sovellusten suosiota navigointi käytössä.

hiphei
15.02.08, 15:42
Selvästikään Java-virtuaalikoneesta ei ladata koko konetta muistiin, vaan muistinhallinta tosiaan osaa ajaa sitä koodia ilmeisesti FLASH-muistilta suoraan.
Tämä on ihan Symbian OS:n mahdollistama toiminnallisuus, jota hyödynnetään ilman Javaakin.

Siinä ikäänkuin pakotetaan uudelleenkäyttämään Java-kirjastoissa olevaa koodia korkeammalla tasolla, mitä S60-natiivisovelluksissa.
Käytännössä C/C++ ohjelmat ovat konekielellä koodisivuilla. Siis samankokoinen koodisivu konekieltä (C/C++ kieltä) sisältää vähemmän logiikkaa ja toimintaa mitä Java-bytekoodi.
Ensin bytekoodi käyttää Java-virtuaalikoneen ja Java-kirjastojen jaettua koodia, jonka jälkeen vielä Java-kirjastot ja -virtuaalikone käyttää Symbianin ohjelmakirjastoja.
Koodia tulee yhteiskäytettyä ja jaettua koodarin tietämättäänkin paljon enemmän mitä C/C++.
S60:ssä hyödunnetään paljon S60:n ja Symbian OS:n valmiita API-"kirjastoja", joita käytännössä "pakotetaan" käyttämään. Nämäkin "kirjastot" tuppavat olemaan DLL:iä, jotka dynaamisesti ladataan ja ovat siten valmiiksi muiden natiivien ohjelmien kuin myös sen Javankin käytössä.
Prosessori ei osaa ajaa "Java-koodisivuja" vaan se suorittaa ihan pelkästään vain opcode:ja ja opcode:ihin ei millään saa ängettyä enempää logiikkaa kuin mitä prossu ymmärtää.

Juttu johtuu em. asiasta, jossa C++/C/konekielen osoittimien käyttö estää optimoinnin tapauksissa jossa koodia tai dataa kannattaisi siirtää eri järjestykseen ja paikkaan ajoaikana, jotta se mahtuu vaikka L2 cacheen jatai jokin ehdollinen koodi suoritetaan usein ja vie paljon aikaa, mutta järjestämällä ehtolauseet uudestaan tuo sama koodi suoritetaankin harvoin.
C++:ssa voi käyttää myös referenssejä ja smart pointereita tavallisten pointtereiden sijaan. Pointterit itsessään eivät ole este millekään. On huomattava että myös referenssit ovat syvimmältä olemukseltaan pointtereita jossain muistiosoitteessa sijaitsevaan dataan. Prosessori tajuaa vain muistiosoitteita. Natiivi C++-kääntäjä optimoi koodia hyvinkin paljon ja muuttaa ehtolauseiden järjestystä niin, että ne optimaalisesti kulkevat ARM-prossun (muistaakseni) 17 pipelinen läpi. ARM-prossussa itsessään on myös sekä staattista että ajonaikaista optimointia "kuplien" tunnistukselle, jotta pipelining toimisi paremmin.

Jos JVM on kunnolla tehty, se osaa optimoida käynnistyshetkellä ko. alustalle, esim optimoida tietyn kokoiselle L2-cachelle ja käyttää CPU:n sisäisiä rekisterejä viisaasti.Java ei pääse käsiksi cacheen eikä rekistereihin - se on allaolevan käyttöjärjestelmän kääntämisen aikaan sen kääntäjän käsissä ja cachen osalta kiinni ihan siitä, mitä muuta se prossu tekee samoihin aikoihin käyttöjärjestelmän ja sen kernelin tahoilla.

zimon
15.02.08, 16:09
Ilmeisesti tuoreimmalla julkisella softalla? muuten tuloksesi tuntuvat oudoilta. mikä oliko Nokian Maps vakio, vai päivitelty, esim beta 2?

Joo, Nokia Maps beta 2, kun halusin itse katsoa olisiko Seuranta-ominaisuus palautettu.

Jos java talktimer käynnissä ja sen jälkeen käynnistää tuon ehdottamasi laskimen niin taitaa RAM hävitä parinmegan luokkaa (yksinään käynnistettäessä 4-5MB väliin), määrästä voi olla montaa mieltä jos vertaa esim Chua Welicin cCalc ohjelmaan joka vie neljänneksen (n.0.5MB) RAMia, ja kymmenes osan riippuen vähän mihin verrataan.

Niinpä. Tuo calc tukee hiukkasen enemmän ominaisuuksia, kuten matriisilaskua, scriptejä, välituloksien lähes rajatonta muistamista ja viimeisimmän parinkymmenen näyttämisen näytöllä, käyrän piirtämistä sekä tilastodataa, jolle se samantien laskee tärkeimmät tunnusluvut ja osaa antaa best-fit-käyrän sekä parametreinä että piirtää se näytölle.

Ominaisuusluettelo on aika mahtava, vaikka paria lisäominaisuutta vielä tuohon toivoisi. http://midp-calc.sourceforge.net/Calc.html


Calc on tehty silmällä pitäen HP 48x-laskinta/tietokonetta, jos se joillekin on tuttu. Tosin Calc:n käyttäminen voi olla hankalaa sellaiselle joka on tottunut vain infix-laskimiin, jollaisia suurin osa on.

En tiedä kannattaako noita kahta verrata, koska calc:ssa on ccalc:iin nähden hurjasti enemmän ominaisuuksia.

Katsoin kuitenkin mitä Calc jatai Talktimer vie muistia. Y-tasks' Trace taas oli käyttössä ja annoin aina luvun vakiintua ennen kuin otin lukeman. Myös Calcissa tein pari laskkutoimitusta että se oikein heräsi ja Talktimerin pistin käyntiin kun se oli ajossa.

Measured with Y-tasks' Trace in N95 (v20.0.015)

free/total = percent (reserved_memory_after_boot_by_this_test) (more_or_less_to_previous_stage)

After boot: 26947584/58720256 = 46% <- cmp.to cmp.prev.
Calc started and running: 25194496/58720256 = 43% (-1753088) (-1753088)
Calc and Talk-timer running: 23343104/58720256 = 39% (-3604480) (-1851392)
Calc stopped: 24952832/58720256 = 42% (-1994752) (+1609728)
Talk-timer stopped: 26300416/58720256 = 44% (-647168) (+1347584)
Calc restarted and running: 25083904/58720256 = 42% (-1863680) (-1216512)
Calc stopped: 26271744/58720256 = 44% (-675840) (+1187840)

Eka suluissa oleva luku kertoo siis paljonko muistia varattuna bootin jälkeen vapaana olevaan määrään verrattuna. Toinen suluissa oleva luku kertoo mikä oli muutos vapaaseen muistiin edelliseen riviin ja tilanteeseen verrattuna.

Eli Calc ekan kerran käynnistyessään vie 1.75 MB. Talk-timer siihen mukaan niin muistia kuluu lisää 1.85 MB, eli yhteensä 3.60 MB.

Kun Calc lopetetaan, vapautuu muistia 1.6 MB ja kun Talk-timer lopetetaan sen jälkeen muistia vapautuu lisää 1.35 MB. Yhteensä vapautetaan siis n. 2MB muistia, joten 1.6 MB on JVM:sta jäänyt roikkumaan jotain jota S60:n muistinhallinta vielä ei ole puhdistanut.

Kun Calc uudelleenkäynnistetään ja se vie 1.22 MB, ja kun lopetetaan se palauttaa 1.19 MB.


ei, varsinkin kustannuskriittisissä projekteissa, ja joillekkin alustoille ainoa vaihtoehto. Kuitenkin jostain hassusta syystä parhaat autonavigointi sovellukset ovat olleet natiiveja, vaikka java toteutuksiakin on ollut markkinoilla. ja vastoin sinun muistiajatuksia, niin tehottomus ja muistiongelmat ovat hankaloittaneet java sovellusten suosiota navigointi käytössä.

Tilanne tulee todennäköisesti muuttumaan, koska Javalla on etuja tietyntyyppisissä sovelluksissa, esim. juuri niissä jotka ovat jatkuvasti ajossa ja ovat kopleksisia olio-ohjelmia. On selvää että parin vuoden takaisissa puhelimissa ja PDAissa ei riittänyt resurssit Javan tehokkaaseen ajamiseen, mutta tilanne on muuttumassa kuten se on jo muuttunut PC-puolella pari vuotta sitten. Javalla on mahdollista tehdä ohjelmia jotka pitkään ajossa ollessaan säästää sekä muistia että CPU-aikaa, ja siten myös akkuvirtaa, verrattuna c++/c-ohjelmiin.

zimon
15.02.08, 16:29
OT jatkuu. Ohjelmointikielten optimointiteoriaa.

OT jatkuu.

Huono esimerkki. C/C++ takaa, että ehtolausekkeet tehdään tietyssä järjestyksessä (vasemmalta oikealle) ihan senkin vuoksi, että ehdossa a voidaan muuttaa jotain yhteistä arvoa ja ehdossa b sitä samaa arvoa käytetään (singleton pattern, globaalit, tietokanta, muut tiedostot jne.). Tämän vuoksi ehtojen suoritusjärjestyksen muuttamisesta seuraa arvaamatonta käyttäytymistä.

Siinäpä se. Koska c++/c:ssa käytetään osoittimia ja osoittimilla laskemista, ja se voi tapahtua vaikka jossain kääntäjän näkymättömissä olevassa kirjastossa tai ennalta käännetyssä objektissa, niin kääntäjä eikä mikään JVM:n tapainen talkkari ohjelman ajon taustalla pysty päättelemään ovatko jotkut koodilohkot aitoja riippumattomia kooodilohkoja, vai onko niissä viittauksia toisiinsa.

Javassapa kääntäjä ja JVM voi tuon tehdä, koska se pystyy tietämään ja eristämään ne koodilohkot jotka ovat riippumattomia. Kyseessä on ns. "basic block"
http://en.wikipedia.org/wiki/Basic_block

C++/c:ssa "basic block":t jää auttamatta pieniksi silpuiksi kun jokainen funktiokutsu lopettaa peruslohkon ja mahdolliset optimoinnit kusee jatkuvasti. Ja basic-block:ien sisälläkin jos käyttään osoittimia, ei voi tietää onko koodilohko riippumaton johonkin muuhun koodilohkoon verrattuna, jolloin järjestyksellä ei olisi väliä.

Osoittimien käyttö on myrkkyä optimoinnille.
JVM mahdollisimman myöhään muuttaa referenssit oikeiksi osoitteiksi. Sitä ennen se voi tehdä ajoaikaisia optimointeja. Jos on käytössä JIT-JVM, niin kehittyneemmät sellaiset saattaa kesken suurehkon loopin hylätä jo konekieleksi käännetyn lohkon ja järjestellä sekä optimoida se uudestaan bytekoodissa ja tehdä uudet JIT-lohkot jotka toimivatkin sitten nopeammin.



Natiivikääntäjät ei kehity?

Kehittyy toki, mutta niillä on teoriaan perustuvia esteitä joita ei pysty ylittämään, ellei kielestä oteta ominaisuuksia pois, kuten Javassa tehtiin.
Toki on Javallakin natiivikääntäjiä, jolloin javaohjelma siis toimii ilman JVM:aa, mutta jossa niissäkin voidaan käännösaikana tehdä paljon sellaisia optimointeja mitä c/C++ ohjelmille ei voida tehdä.


Symbian-SDK:ssa on muistinkäsittelyyn liittyviä funktioita joilla esim. fragmentoitumisesta päästään eroon. Huonoa koodaamista sekään ei tietysti pelasta.

Mutta voiko se ajossa olevan ohjelman elossa olevia olioita ja muistirakenteita mennä siirtämään fyysisessä muistissa? Ei voi, koska muuten natiivisovelluksen viittaukset (osoitteet) pitäisi kaikki päivittää koodissa, joka olisi erittäin monimutkaista erityisesti kun c/c++/konekielessä saatetaan laskea osoitteilla => tekee mahdottomaksi.

JVM taas jälleen voi tuon tehdä. On valtavan suuri nopeuslisä, jos voidaan sellaisia olioita joita käytetään ajallisesti lähekkäin siirtää myös fyysisessä muistissä lähekkäin toisiaan. Cache-missit kaikissa moderneissa CPUissa on myrkkyä nopeudelle ja myös virrankulutukselle.


Ihan näppituntumalta sanoisin, että Javalla tai muilla tulkkeihin perustuvilla ohjelmointikielillä ei päästä samoihin lopputuloksiin suorituskyvyllisesti kuin hyvin suunnitelluilla ja eritoten koodatuilla natiivisovelluksilla any time soon.

PC-puolella näkyy jo teorian ennustama kiistaton nopeusetu natiivi-sovelluksiin verrattuna tietyntyyppisissä kompleksissa sovelluksissa. Esim. sellaisissa jossa luodaan ja tuhotaan paljon olioita tai ohjelman suorituksessa on paljon epädeterministisiä tai satunnaisia parametrejä, joita ei voi ennustaa käännösaikana mutta joista voidaan tehdä tilastollinen analyysi ajoaikana, jonka JVM voi java-koodille tehdä, ja tekeekin. (en tiedä tekeekö jo S60 JVM:ssa, mutta tulevaisuudessa varmasti)


Java ei pääse käsiksi cacheen eikä rekistereihin - se on allaolevan käyttöjärjestelmän kääntämisen aikaan sen kääntäjän käsissä ja cachen osalta kiinni ihan siitä, mitä muuta se prossu tekee samoihin aikoihin käyttöjärjestelmän ja sen kernelin tahoilla.

JVM:llä on käytössään CPU:n mahdollistamat sisäiset rekisterit (esim kuinka monta ja minkä tyyppisiä ne on) ja tieto L2-cachen suuruudesta, jota se voi hyödyntää javakoodin suorituksessa, optimoinneissa ja myös JIT-käännöksissä, jos sitä käytetään.

Unohtu muuten mainita aikaisemmin olevassa esimerkissä, että koska ehtolausekkeen toteutuvuus kokonaisuudessaan (JVM:n luoman tilaston peruusteella) on harvinaisempaa kuin sen epä-toteutuvuus, niin JVM:n kannattaa myös vaihtaa lohkoD:n ja lohkoE:n paikkaa fyysisessä muistissa kesken loopin ajon, koska silloin CPU:n L2-cache taas hyötyy että todennäköisemmin ei tarvita koodikohdassa hyppäystä eteenpäin ja näin mahdollisesi cache-missiä, vaan ehtolausekkeen jälkeen suoritettava koodi seuraa heti fyysisesti perässä.

sovelias
15.02.08, 17:15
Joo, Nokia Maps beta 2, kun halusin itse katsoa olisiko Seuranta-ominaisuus palautettu.Ne se selittää miksi sait Mapsin viemään muistia, ja jos N95 tuoreimmalla softalla, niin se selittää miksi java ei vienyt RAM muistia normaalisti.
Jos vertailet tuloksia edellisellä firmiksellä tekemisiisi, niin varmaan olet huomannut että javakikkareita ei N95lla paljoa ajella, jos pienikin softa vie enemmänkin megatavuissa kuin sadoissa kiloissa ja käynnistys ajat pitkiä.
Niinpä. Tuo calc tukee hiukkasen enemmän ominaisuuksia, Aha, no aijemmin vertailit Nokia Maps 2 betaa, MGMapsiin.

No jos kokeilee käyttöliittymältään simppeliä lainalaskuria, heilahtaa 5MB jos sen jälkeen lataa toisen functiolaskimen kulahtaa perään toistamegaa RAMia..

S60 alustalla jossa käytössä sama kuin ilmeisesti sinun luurissa, on muistin käyttö luokkaa 1.5MB + 1.5MB, niin se monipuolisempi ccalc vei vajaa 0.5MB... vaikka jäkimmäisen testialustalla oli muistinkulutuksen suhteen javakone rankasti parempi kuin yleisesti S60 3rd /FP1 koneissa.

Minulla ei ole mitään Jaavaa vastaan päinvastoin, mutta en oikein ymmärrä perusteluita sen suosimiseen muistinkulutuksen takia. Toivottavasti teidän firmassa ei ole Symbian J2ME projekteja aloitettu noilla perusteilla. markkinoilla on liuta s60 3rd (myös FP1) koneita joilla yhden java kikkulan ajaminen liki rajoittaa latteen muun käytön.

Pythonillakin pääsee vähemällä muistinkulutuksella, jos pitää nopeasti rajallisen rusurssein vääntää.

anttitk
15.02.08, 17:20
Eihän asia mulle kuulu, mutta.... eiköhön pojat vois alkaa jo pikkasen löysään pantaa..? Viikonloppu ja kaikkee. Tää vähän keulii jo ympäri.

zimon
15.02.08, 17:36
Ne se selittää miksi sait Mapsin viemään muistia, ja jos N95 tuoreimmalla softalla, niin se selittää miksi java ei vienyt RAM muistia normaalisti.

Joo, N95 V20.0.015 käytössä.


Aha, no aijemmin vertailit Nokia Maps 2 betaa, MGMapsiin.

No kummatkin tukee nykyään hybridi-karttoja (Nokia Maps 1 ei tukenut), reititystä, POI'den hakemista, karttojen cachetusta yms. Nokia Mapsissa on lisänä puhesyntetisaattori ja puhe-navigaatio. Ei ne nyt niin kaukana mielestäni toisistaan ole kuin cCalc ja Calc.

zimon
15.02.08, 17:39
Eihän asia mulle kuulu, mutta.... eiköhön pojat vois alkaa jo pikkasen löysään pantaa..? Viikonloppu ja kaikkee. Tää vähän keulii jo ympäri.

Mielenkiintoinen aihe minusta :-)
Mulle aikanaan oli pieni järkytys huomata vanhat ennakkokäsitykseni vääriksi, ja sellanen "normaalijärki", kun kanssa oletin ettei tulkattavalla kielellä millään voi päästä nopeammaksi kuin natiiviksi käännetyllä koodilla.
Mutta kuinkas sitten kävikään kun luin kirjan moderneista ohjelmoitikielten kääntäjistä.
http://books.google.fi/books?id=JNs6fWkJZbAC&dq=modern+compiler+implementation+in+java&pg=PP1&ots=i-s_cCS4Ua&sig=DCv2P-Y5nTTLb8l2pZuLIFetOuI&hl=fi&prev=http://www.google.fi/search?hl=fi&client=firefox-a&rls=org.mozilla:fi:official&hs=SJN&q=modern+compiler+implementation+in+java&btnG=Hae&sa=X&oi=print&ct=title&cad=one-book-with-thumbnail
(ja pari muuta)

Ja muutin tota ketjua aloittavaa viestiä ja otsikkoa.
Mun puolesta voi siirtää "Asian vierestä osioon."

hiphei
16.02.08, 16:52
Mun puolesta voi siirtää "Asian vierestä osioon."
Sopii hyvin, koska tämän tyylisille ohjelmointiin liittyville asioille ei ole kai omaa ketjua. Asian vierestäkin on hyvä vaikka jatkaa.

Siinäpä se. Koska c++/c:ssa käytetään osoittimia ja osoittimilla laskemista, ja se voi tapahtua vaikka jossain kääntäjän näkymättömissä olevassa kirjastossa tai ennalta käännetyssä objektissa, niin kääntäjä eikä mikään JVM:n tapainen talkkari ohjelman ajon taustalla pysty päättelemään ovatko jotkut koodilohkot aitoja riippumattomia kooodilohkoja, vai onko niissä viittauksia toisiinsa.

Javassapa kääntäjä ja JVM voi tuon tehdä, koska se pystyy tietämään ja eristämään ne koodilohkot jotka ovat riippumattomia. Kyseessä on ns. "basic block"
http://en.wikipedia.org/wiki/Basic_block

C++/c:ssa "basic block":t jää auttamatta pieniksi silpuiksi kun jokainen funktiokutsu lopettaa peruslohkon ja mahdolliset optimoinnit kusee jatkuvasti. Ja basic-block:ien sisälläkin jos käyttään osoittimia, ei voi tietää onko koodilohko riippumaton johonkin muuhun koodilohkoon verrattuna, jolloin järjestyksellä ei olisi väliä.

Osoittimien käyttö on myrkkyä optimoinnille.
JVM mahdollisimman myöhään muuttaa referenssit oikeiksi osoitteiksi. Sitä ennen se voi tehdä ajoaikaisia optimointeja. Jos on käytössä JIT-JVM, niin kehittyneemmät sellaiset saattaa kesken suurehkon loopin hylätä jo konekieleksi käännetyn lohkon ja järjestellä sekä optimoida se uudestaan bytekoodissa ja tehdä uudet JIT-lohkot jotka toimivatkin sitten nopeammin.
Tuollainen jatkuva koodin analysointi on raskasta ja uudelleenkääntämiseenkin menee merkittävästi kellojaksoja. Tälläiset ratkaisut sopivat paremminkin serverimaailmaan, jossa tehoja löytyy enemmän ja joissa rinnakkaisprosessointia pystyy hyödyntämään vaikka koodi ei alunperin olisikaan täysin optimaalista useammalle prossulle.
C/C++-kääntäjä korkeammilla optimointiasetuksilla pystyy järjestelemään operaatioita tehokkuuden kannalta mieleiseensä järjestykseen, niin että mahdollisimmat monet tarvittavat datat ovat rekistereissä. Rekistereihin ei mahdu kuin noin tusina arvoa kerrallaan. Prossulla on myös erinäisiä keinoja ennakoida asioita, jotta pipelining toimisi hyvin. ARM-prossujen perusteellinen dokumentaatio kertoo näistä enemmän.
Täydellisyyteen ei minkäänlainen optimointi pysty ja voinkin vain pelolla kuvitella millaista kaikkien koodaussääntöjen vastaista kymmenien sisäkkäisten looppien ja ehtolaudeiden sekä epäloogissa paikoissa kutsuttavien metodien joukkoa tässä JVM joutuisi optimoimaan. Jotta tuo Java-optimointi toimisi hyvin, niin sen prossun pitäisi suoraan osata Java:n tavukoodia tais suoraviivaisesti siitä johdettuja opcodeja. Valitettavasti nykyisissä mobiililaitteissa JVM ei pääse käsiksi mm. turvallisuussyistä edes suoraan kerneliin eikä siten pääse käskyttämään mieleisellään tavalla prossua vaan kaikki tapahtuu varsinaisen käyttöjärjestelmän päällä.

Mutta voiko se ajossa olevan ohjelman elossa olevia olioita ja muistirakenteita mennä siirtämään fyysisessä muistissa? Ei voi, koska muuten natiivisovelluksen viittaukset (osoitteet) pitäisi kaikki päivittää koodissa, joka olisi erittäin monimutkaista erityisesti kun c/c++/konekielessä saatetaan laskea osoitteilla => tekee mahdottomaksi.
Jos se dataa tykkää muuttaa niin kovin usein sijaintiaan niin ainahan voi tehdä taulun, johon ne lukuista pointteri osoittavat ja sitä taulun sisältämää pointteria arvoa sitten päivitetään aina datan sijainnin mukaan. Tälläinen ominaisuus on helppo tehdä missä tahansa oliokielessä ja jos olioilla on yhteinen kantaluokka. Javassahan näin on tehty ja tämä ideologia myös siten estää pointtereiden käytön missään tilanteessa.
Nimenomaan C-kielillä on helppo kopioida ihan minkälainen data ja ihan mihin muistiosoitteeseen vaan. Referenssien osoitteet eivät Javassakaan mitenkään automaagisesti muutu mihinkään uuteen paikkaan datan siirtämisen seurauksena. Javassa roskienkeruun vuoksi referensseistä joudutaan pitämään jossain erillisessä paikassa kirjaa eli missä osoitteessa (pointteri) sen referenssin olio oikeasi luuraa sillä hetkellä. Roskienkeruuta varten samoin jokainen olio näkymättömästi pitää kirjaa, montako referenssiä siihen viittaa. Kaikki tuollainen ylimääräinen kirjanpito on overheadia, jos siihen ei ole tarvetta ja lisää nimenomaan page faultien todennäköisyyttä näitä relaatioita ylläpidettäessä. Silti ihan kaikenlainen datan tai olioden kopionti on raskasta etenkin, jos puhelimessa ei ole edes MMU:ta.

zimon
20.02.08, 21:59
Tuollainen jatkuva koodin analysointi on raskasta ja uudelleenkääntämiseenkin menee merkittävästi kellojaksoja. Tälläiset ratkaisut sopivat paremminkin serverimaailmaan,

Ei se ole sinne pelkästään rajattu. Tuo ajoaikainen optimointi tuodaan myös mobiililaitteisiin, koska sillä voidaan saavuttaa parempia tehoja ja parempia akunkestoja.


C/C++-kääntäjä korkeammilla optimointiasetuksilla pystyy järjestelemään operaatioita tehokkuuden kannalta mieleiseensä järjestykseen, niin että mahdollisimmat monet tarvittavat datat ovat rekistereissä. Rekistereihin ei mahdu kuin noin tusina arvoa kerrallaan. Prossulla on myös erinäisiä keinoja ennakoida asioita, jotta pipelining toimisi hyvin. ARM-prossujen perusteellinen dokumentaatio kertoo näistä enemmän.

Näin on kaikkien prosessorien kanssa, että käännösvaiheessa jos osaa kertoa target-CPU:n, kääntäjän optimoija voi tehdä paljon temppuja joilla koodi tulee tehokkaammaksi.

Huomattavaa on, että itse JVM on käännetty toivottavasti noilla samoilla tiedoilla, joten se tietää miten monta sisäistä rekisteriä CPU:lla on, kuinka monta pipelineä, mitä erityisresursseja, L2-cachen koko yms.
JVM osaa hyödyntää tuota tietoa kummassakin tapauksessa, pelkästään tulkatessa tai JIT-kääntäessä bytekoodia.

Silti on paljon tilanteita monimutkaisimmissa ohjelmissa, ihan vaikka www-selaimessa tai navigaattorissakin miksei, jolloin käännösaikana ei ole kaikkea sitä informaatiota käytettävissä mitä voisi optimointeihin käyttää.



Täydellisyyteen ei minkäänlainen optimointi pysty ja voinkin vain pelolla kuvitella millaista kaikkien koodaussääntöjen vastaista kymmenien sisäkkäisten looppien ja ehtolaudeiden sekä epäloogissa paikoissa kutsuttavien metodien joukkoa tässä JVM joutuisi optimoimaan. Jotta tuo Java-optimointi toimisi hyvin, niin sen prossun pitäisi suoraan osata Java:n tavukoodia tais suoraviivaisesti siitä johdettuja opcodeja.

Ei tarvitse. JIT-JVM ei ole välttämätöntä, jotta ajoaikaisesta optimoinnista hyötyy. JIT:sta on jopa pieni haitta, koska tällöin pitää ajoaikaiseen optimoinnin kustannuksiin laskea se, että koodilohko joudutaankin kääntämään uudestaan mikäli sitä mennään optimoimaan sen bytecode-versiossa uudestaan. Kaikissa ajoaikaisissa optimoinneissa pitää arvioida optimointiin itsessään menevät resurssit suhteessa saatuun hyötyyn.

Monimutkaisuus sinänsä ei ole ongelma, koska käännösvaiheessa voidaan tietää varmat riippuvuudet ja mahdolliset riippuvuudet, mutta ennen kaikkea toisistaan riippumattomat koodilohkot. Kääntäjä voi myös järjestellä ja lisäillä koodia siten, että ajoaikana JVM:lla sitten on helpompaa tehdä profilointia ja se tietää mistä kannattaa yrittää optimoida ja mistä ei.


Valitettavasti nykyisissä mobiililaitteissa JVM ei pääse käsiksi mm. turvallisuussyistä edes suoraan kerneliin eikä siten pääse käskyttämään mieleisellään tavalla prossua vaan kaikki tapahtuu varsinaisen käyttöjärjestelmän päällä.

Ei tuo estä ajoaikaista optimointia JVM:ssa.

Jos se dataa tykkää muuttaa niin kovin usein sijaintiaan niin ainahan voi tehdä taulun, johon ne lukuista pointteri osoittavat ja sitä taulun sisältämää pointteria arvoa sitten päivitetään aina datan sijainnin mukaan. Tälläinen ominaisuus on helppo tehdä missä tahansa oliokielessä ja jos olioilla on yhteinen kantaluokka. Javassahan näin on tehty ja tämä ideologia myös siten estää pointtereiden käytön missään tilanteessa.

Teoreettisella tasolla kumpikin, sekä C/C++ ja Java ovat Turing Complete kieliä, joten kaiken saman jonka voi tehdä C++:lla voi tehdä Javalla, ja päinvastoin.

Kysymys on vaan informaatiosta ja sen käyttämisestä. JVM:ssa on mahdollista päästä käsiksi helpommin ajoaikaiseen dataan ja käyttää sitä optimoinneissa.

c/C++/Assemblyssä sama on mahdollista, mutta vaatii koodaajan itse tekemään se mahdolliseksi monimutkaisin tietorakentein ja koodin morphauksin. Mm. juuri luopua osoittimien käytöstä kokonaan omissa olioissaan ja tehdä kaikista metodikutsuista dynaamisia.
Voi jopa olla, että itseasiassa konekieleksi asti käännetty ohjelma on niin raskas morphata, että JVM:n tapa tehdä ajoaikaista optimointia on aina nopeampi JIT:n kanssa.


Nimenomaan C-kielillä on helppo kopioida ihan minkälainen data ja ihan mihin muistiosoitteeseen vaan. Referenssien osoitteet eivät Javassakaan mitenkään automaagisesti muutu mihinkään uuteen paikkaan datan siirtämisen seurauksena. Javassa roskienkeruun vuoksi referensseistä joudutaan pitämään jossain erillisessä paikassa kirjaa eli missä osoitteessa (pointteri) sen referenssin olio oikeasi luuraa sillä hetkellä. Roskienkeruuta varten samoin jokainen olio näkymättömästi pitää kirjaa, montako referenssiä siihen viittaa. Kaikki tuollainen ylimääräinen kirjanpito on overheadia, jos siihen ei ole tarvetta ja lisää nimenomaan page faultien todennäköisyyttä näitä relaatioita ylläpidettäessä. Silti ihan kaikenlainen datan tai olioden kopionti on raskasta etenkin, jos puhelimessa ei ole edes MMU:ta.

Ja tuon vuoksi juuri JVM voi mennä järjestelemään fyysisten olioiden oikeita paikkoja eri järjestykseen, koska se voi haltata ajettavan ohjelman siksi aikaa kun järjestelee olioiden paikat, päivittää referenssi-taulukon osoitteet ja jatkaa hommia nyt paremmin optimoiduilla olioilla L2-cachea silmälläpitäen.

JVM tietää onko MMU:ta vai ei ja voi sen perusteella tehdä päätöksiä siitä miten se itse hoitaa muistinhallnitaa ja muistin optimointia.

Jos JVM on tehty kunnolla, page-faulttejakaan ei tule niin paljon, koska se pystyy ennakoimaan mitä olioita tarvitaan vaikka loopissa ja ottaa niiden olioiden fyysiset osoitteet joko rekistereihin tai pinoon lähemmäksi itse tarvittavia olioita.

c/C++:n muistinhallinnan ongelma monesti on malloc():n tapa etsiä heapista sopivan kokoinen vapaa pala ja varata se sitten uudelle dynaamiselle olioille. Näin ohjelmassa jossa käytetään paljon dynaamisia olioita, oliot fragmentoituu pitkin heappia ja minor pagefaultteja tulee paljon. Erityisesti tämän huomaa vaikka siitä kun taulukkoa, jossa on olion osoitteita, tai linkitettyä listaa suurennetaan silloin tällöin. JVM tietää että kannattaa mielummin varata muistit uusille olioille taulukkoon/listaan lähelle entisiä, kun malloc:lle taas kelpaa mikä tahansa sopivan kokoinen pala mistä tahansa.

C++:ssa pitää koodarin itse tehdä samantyyppinen ajoaikainen olioiden fyysisen paikkojen uudelleenjärjestely, tai käyttää kirjastoa, joita tietääkseni ei vielä ole saatavilla.

Ei ole mikään sattuma, että Javassa jätettiin osoittimet käyttämättä muualla kuin JNI-metodeiden kautta. C ja C++ juontaa aikansa vuodesta 1972, jolloin ei vielä edes voitu kuvitella kaikkia mahdollisuuksia mitä uudet CPU-tekniikat ja algoritmit mahdollistavat. Javaan upotettiin 1991 ja eteenpäin +20 vuoden karttunut informaatio ja opitut jutut. Se aidosti on sukupolvea korkeampi ohjelmointikieli kuin C/C++.

Tulevaisuudessa myös käännösaikainen ja ajoaikainen moniprosessorituki tulee Javassa mahdolliseksi paljon helpommin mitä c/c++:ssa. Vanhat Java-ohjelmat voidaan ajaa monella CPU:lla, vaikka niitä ei koskaan suunniteltu siihen tehtävään. Jälleen referenssit ovat ylivoimaisia osoittimiin nähden, koska kääntäjä ja JVM pystyy pitämään kirjaa mitkä metodit mitäkin olioita käyttää ja mitkä ovat koodilohkojen tiedetyt ja mahdolliset riippuvuudet. Ja itseasiassa jo nykyiset JVM:t automaattisesti hoitavat roskienkeruun ja mahdollisen JIT-kääntämisen omissa säikeissään. Myös ajoaikainen profilointi ja optimointi luonnollisesti tehdään omassa säikeessään, jolloin useat CPU:t tulevat heti käyttöön jos niitä on.


Ihan mielenkiinnosta, miten selität nuo koetulokset joissa Java on nopeampi mitä C/C++:lla käännetty sama koodi?
http://members.lycos.co.uk/wjgoh/Java%20vs%20C%20benchmarks.doc

a) Java ohjelmat toimii väärin?
b) C++ ohjelmat toimii väärin?
c) koejärjestelyn tekijä on epäluotettava?
d) jokin muu mikä?

Kummassakaan (C++ vs Java) ei itse sovelluksen koodari ole tehnyt eroavia optimointeja, vaan kaikki nopeuserot selittyvät vain kääntäjillä ja ajoaikaisella optimoinnilla.

Testituloksista jopa näkyy, että kun ohjelma on pitempään ajossa, silloin potkasee ajoaikainen optimointi käyntiin JVM:ssa (-server moodi) ja siitä tulee silminnähden nopeampi C++:sta käännettyä ohjelmaa ja client-JVM:aa jossa ei ole ajoaikaista optimointia. JVM vaatii aikaa profiloidakseen loopit ja oliot, kunnes se tekee päätöksen että kannattaa optimoida.

Tosin joissakin testeissä se "tavallinen" JVM ilman ajoaikaistakin optimointia on nopeampi C++:aa, joka tarkoittaa vaan sitä että Java-kääntäjä on pystynyt optimoimaan lähdekoodia paremmin kuin mitä C++-kääntäjä.

Hyvä paperi tästä on tässä, jossa käydään läpi joitakin syitä miksi Javan ennustetaan olevan nopeampaa kuin C++. Myöhemmin testeissä tätä on alkanut jo näkyä käytännössä.
http://trs-new.jpl.nasa.gov/dspace/bitstream/2014/18351/1/99-1827.pdf&e=9797

6 Conclusion
On-the-fly compilation is a paradigm shift.
Paradigm shifts generally lead to exciting and
unanticipated new possibilities. In particular, Java
may become faster than C++ because the compiler
has access to information not available to a C++
compiler. Market forces will tend to make this
possibility become an actuality because improved
performance means improved energy efficiency and
battery life. Battery life will be an important
product discriminator in the rapidly growing market
for embedded systems.


Toinen hyvä kirjoitus, jossa käydään lyhyemmin tärkeimmät pääpointit:
http://www.idiom.com/~zilla/Computer/javaCbenchmark.html

1) Pointers make optimization hard
2) Garbage collection- is it worse...or better?
* The cost of missing the cache
3) Run-time compilation