Android OpenGL-ES 3d file feldolgozás lassú

Android OpenGL-ES 3d file feldolgozás lassú
2011-11-25T19:51:05+01:00
2011-11-30T16:21:57+01:00
2022-11-23T21:31:01+01:00
demodemo
Gyanítom, hogy Lackoka fog ismét hozzászólni.:)

Szóval: régebben írtam már ilyet, de már lövésem sincs, mit hogyan.

A lényeg: írtam egy 3d file parsert, ami viszonylag szörnyen lassan dolgozik.

3 megás filet, nagyon.-nagyon lassan parse-ol.
Valahogy fel lehetne ezt gyorsítani sebességileg?

amúgy így haladok végig a fileon:

InputStream fileIn = resources.openRawResource(resourceID);
BufferedReader buffer = new BufferedReader(new InputStreamReader(fileIn));

while ((line = buffer.readLine()) != null) {
StringTokenizer parts = new StringTokenizer(line, " ");


...

tehát a szokásos sorról-sorra típus.

jah és a log:

INFO/model loader(2463): End parsing 55656ms

tehát 55 mperc...ez kissé durva

Üdv, és köszi
Mutasd a teljes hozzászólást!
NDK-val próbálkoztál már? Nem biztos, hogy egy 10 évvel ezelőtti PC-nek megfelelő eszközön Java-val kell ilyeneket csinálni.
Mutasd a teljes hozzászólást!

  • Megpróbálkozhatsz a RandomAccessFile osztállyal. Ez natív implementáció.
    És mivel van neki olyan metódusa hogy seek nem is feltétlenül kell beolvasnod az egészet, csak azt ami éppen szükséges.
    Mivel nem értek OpenGL-hez egyáltalán, így azt sem tudom hogy miként néz ki egy ilyen fájl, de feltételezem vertextek, vagy valami ilyesmik (azaz számok). Lehet nem String-ként kéne feldolgozni, mert ez így tuti lassabb.
    Mutasd a teljes hozzászólást!
  • Igen, vertexeket, normálokat, textura koordinátákat, ezért is ilyen nagy ez a file.

    Egy sorban gyakorlatilag egy vertex van

    v x y z
    vt x y
    vn x y z
    f vi/vti/vni

    v-vektor, vt-texture, vn-normal, f-face

    csakhogy énis írjak valami hasznosat.:)

    ok megpróbálom a randomot, köszi
    Mutasd a teljes hozzászólást!
  • Lehet, hogy hülye kérdés, DE


    String fileIn = resources.getResourceName(resourceID); Log.e("fileIn", fileIn); File f=new File(fileIn); //BufferedReader buffer = new BufferedReader(new InputStreamReader(fileIn)); RandomAccessFile buffer = null; try { buffer = new RandomAccessFile(f, "r"); } catch (FileNotFoundException e) { Log.e("err", ""+e); }

    Nem olvassa a filet, errorral elszáll:

    11-26 15:50:05.445: ERROR/err(6691): java.io.FileNotFoundException: /ls.gold.wallpaper:raw/cm_obj (No such file or directory)
    Mutasd a teljes hozzászólást!
  • Egy asset URL így néz ki:
    file://android_asset/faljnev.txt
    URL-ből tudsz csinálni URI-t, amit át tudsz adni a File objektum egy konstruktorának.
    Persze nem próbáltam, és az sem biztos hogy működik, lévén ezek a fájlok be vannak csomagolva az apk-ba.

    Ha nem jutsz vele semmire, akkor marad az InputStream.
    Két dologgal próbálkozhatsz:
    - nem string-ként kezeled ennek a fájlnak a tartalmát, lévén hogy úgyis számokat tárolsz benne
    - assetek kőzé teszed a fájlod (AssetManager)

    Nem próbáltam ki egyiket sem, hogy milyen gyorsan dolgozik, de majd te kipróbálod. :)
    Mutasd a teljes hozzászólást!
  • 1,

    11-27 12:19:44.531: ERROR/model loader(14714): End parsing 38591ms


    38 mperc lett az 55-60ból, egyre jobb.:)

    ez AssetManagerrel ls RANDOM_ACCESS-el. Mondjuk ez egy 3 megás file, szóval elég lassan tolja még mindig.

    2,
    a RandomAccessFile -t nem sikerült működésre bírnom sajnos. Nem tudom, hogyan adjak meg file nevet, hogyha az apk-n belül van a file.


    3,


    Két dologgal próbálkozhatsz:
    - nem string-ként kezeled ennek a fájlnak a tartalmát, lévén hogy úgyis számokat tárolsz benne


    ezt hogy kell érteni, tudsz egy példát adni rá? Igazából, ha a RandomAccessFile C-s, akkor lehet hogy az gyorsabb sokkal, de nem jövök rá, hogyan lehet nevet adni a filenak ott belső filenál.

    Egyébként az assetes mostani kód:



    AssetManager assetManager = context.getAssets(); InputStream fileIn = null; try { fileIn = assetManager.open(resourceID, AssetManager.ACCESS_RANDOM); } catch (IOException e) { Log.e("err0", ""+e); } BufferedReader buffer = new BufferedReader(new InputStreamReader(fileIn));


    Mutasd a teljes hozzászólást!
  • ezt hogy kell érteni, tudsz egy példát adni rá?

    Ne BufferedReader-t csinálj belőle, hanem BufferedInputStream-et.


    final InputStream in = getAssets().open("cxf.jar"); try { final ByteArrayOutputStream out = new ByteArrayOutputStream(); try { final byte[] buffer = new byte[1024]; int len; while ((len = in.read(buffer)) > 0) out.write(buffer, 0, len); } finally { out.close(); } } finally { in.close(); }

    Szerk: kipróbáltam a RandomAccesFile-t és nekem sem működik. Ezek szerint apk-be csomagolt állományokat nem lehet vele olvasni.
    Mutasd a teljes hozzászólást!
  • Értem, de nekem valami hasonló dolog kéne a readLine()-hoz, ami egy sort visszaad Stringben, hogyan lehetne implementálni ezt erre?

    Mert így mindig 1024 byte-ot levesz, ha jól értem.
    Egyébként ha ez is lassú lesz, akkor muszáj lesz NDK-znom:(
    Mutasd a teljes hozzászólást!
  • Mondjuk ha a fájlod bináris adatokat tartalmazna és nem karakterest, akkor az sem lenne ekkora. Én megfontolnám helyedben a váltást.
    A mutatott példámban az egész fájl tartalma a "out"-be kerül, amiből így csinálsz Stringet (UTF-8 karakterkódolás esetén):

    byte[] data = out.toByteArray(); String s = = new String(data, "UTF-8");
    Mutasd a teljes hozzászólást!
  • Dehát a file-om egy String file object. Hogyan készítsek belőle byte array-t?

    egy .obj fileról van szó amúgy.

    plusz jó lenne, ha akármilyen .obj-ot kezelne..ami ugye string.
    Mutasd a teljes hozzászólást!
  • Most már lassan felfogom mi a feladat. Ezek szerint az .obj fájl egy szabványos formátum (mondtam én hogy nem értek az OpenGL-hez :)).
    InputStream-el beolvasod az egészet, abból lesz egy byte tömböd. Az előző hsz.-emben pedig ott van hogyan lesz abból String. Csak így az egész fájl lesz benne abban a String-ben, nem csak egy sor.
    Kipróbáltam a telefonomon mind a bináris mind a karakteres fájlbeolvasást is, és a bináris sokkal gyorsabb (3x).
    Nekem SGS2-m van és egy 6 megás fájllal a BufferedReader 1,6, míg a BufferedInputStreeam 0.4 mp alatt végzett.
    Mutasd a teljes hozzászólást!
  • public String streamToString(InputStream ios) throws IOException { byte []buffer = new byte[4096]; ByteArrayOutputStream ous = new ByteArrayOutputStream(); try { int read = 0; while ( (read = ios.read(buffer)) != -1 ) { ous.write(buffer, 0, read); } } finally { ous.close(); try { if ( ios != null ) ios.close(); } catch ( IOException e) { } } return new String(ous.toByteArray(), "UTF-8"); }

    Próbálok így beolvasni egy 3 megás filet, de nekem valamiért nem olvassa be teljesen, miért?:( (readline.-al meg jó)
    Mutasd a teljes hozzászólást!
  • Egyelőre 23 mperc a csúcs erre a 3 megára. Nem is igazán a file megnyitással volt baj, hanem a feldolgozás lassú.:)

    Lehet, hogy tényleg NDK lesz ebből.:(
    Mutasd a teljes hozzászólást!
  • Írtál már esetleg NDK-s kódot? Mennyivel dobna a gyorsaságon, ha azt hívogatnám meg?

    ugyanígy String kezelések/arraylistek feltöltése lenne benne, és ezt adná vissza

    Mutasd a teljes hozzászólást!
  • Bizonyára gyorsabb. :) Hogy mennyivel, azt nem tudom megmondani.
    De itt találsz néhány implementációt. Próbáld ki őket, hátha jobban teljesítenek mint a te megoldásod (talán van köztük natív implementáció is).
    Mutasd a teljes hozzászólást!
  • Köszi, de kb a min3D obj parser engine-jét írtam át énis jobbra...:D (már mindent kezel az enyém kb)
    Szóval nem túl nyerő egyik sem. a libgdl gondolom meg nativ, majd megnézem.
    Mutasd a teljes hozzászólást!
  • (más olvasóknak: a kódot megkaptam privátban, az alapján írom a válaszom)

    1. StringTokenizer helyett használd a String.split metódusát. Sokkal gyorsabbnak bizonyult. Link
    2. Globális változókból csinálj lokálist, mielőtt használod. Írd át a ciklusod ennek megfelően: Use Enhanced For Loop Syntax.
    3. Ahol előre tudod hogy hány eleme lesz a listádnak, ott inkább használj tömböt (pl. tempVertices, tempnormals, stb.). Egy helyen használod őket, és mindig ugyanannyi elemük van.

    SGS2-n 14mp-et sikerült redukálni 1mp-re ezekkel a módosításokkal.
    Mutasd a teljes hozzászólást!
  • Mindent igyekezek úgy csinálni, de nálam felment az idő 70 mpercre...Te hogy csinálod?:)
    Mutasd a teljes hozzászólást!
  • Én biztos bináris fájlt használnék.
    Mutasd a teljes hozzászólást!
  • ezt nem lehet, mivel szeretném, ha akármilyen obj filet kezelne a későbbiekben.
    Mutasd a teljes hozzászólást!
  • Fura, de az optimalizálásnak köszönhetően még lassabb az egész...Pedig mindent úgy csinálok ahogy ott van.

    elvileg a splittel is ygorsabb, de nálam a tokenizer gyorsabbnak tűnik...:)
    Mutasd a teljes hozzászólást!
  • update: az az 1 mperc ténylegesen 9 mperc, sgs2-n, nálam tehát a 17-18 mperc sgs1-en elfogadható. Valószínűleg JNI-znem kell.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd