2016-10-19 5 views
0

Ich erstelle eine Obj-Datei-Leser, die Zeile für Zeile mit einem gepufferten Leser lesen, muss ich überprüfen, jede Zeile, wenn es ein Scheitelpunkt ist, fügen Sie es zu Vertices ArrayList und wenn es ist ein Gesicht Ich erstelle ein Face Objekt, das get(i) die Scheitelpunkte ArrayList und weitere 2 Listen "Normal und UVs" dann in die Gesichter Liste hinzufügen. Dies ist der CodeAndroid Geschwindigkeit BufferedReader lesen Zeile und ArrayList hinzufügen und erhalten

public final void ctreateObject() { 
    float now = System.nanoTime(); 
    BufferedReader bufferReader = new BufferedReader(inputStreamReader); 
    String line; 
    try { 
     while ((line = bufferReader.readLine()) != null) {    
      if (line.startsWith("f")) { 
       processFLine(line); 
      } else if (line.startsWith("vn")) { 
       processVNLine(line); 
      } else if (line.startsWith("vt")) { 
       processVTLine(line); 
      } else if (line.startsWith("v")) { 
       processVLine(line); 
      } else if (line.startsWith("usemtl")) { 
       mtlName = line.split("[ ]+", 2)[1]; 
      } else if (line.startsWith("mtllib")) { 
       mtllib = line.split("[ ]+")[1]; 
      } else if (line.startsWith("g") || line.startsWith("o")) { 
       if (faces.size() > 0) { 
        List<Face> theFaces = new ArrayList<Face>(); 
        theFaces.addAll(faces); 
        Model model = new Model(id, theFaces, mtlName); 
        SharedData.models.add(model); 
        faces.clear(); 
       } 
      } 
      Log.i("line", line); 
      ln++; 
     } 
     if (faces.size() > 0) { 
      List<Face> theFaces = new ArrayList<Face>(); 
      theFaces.addAll(faces); 
      Model model = new Model(id, theFaces, mtlName); 
      SharedData.models.add(model); 
      faces.clear(); 
      vertices.clear(); 
      normals.clear(); 
      uvs.clear(); 
     } 
     inputStreamReader.close(); 
     bufferReader.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    Log.i("Line", String.valueOf(ln)); 
    Log.i("time", String.valueOf((System.nanoTime() - now)/1000000000)); 
} 

private void processVLine(String line) { 
    String[] tokens = line.split("[ ]+"); 
    vertices.add(new float[] { Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]), Float.parseFloat(tokens[3]) }); 
} 

private void processVNLine(String line) { 
    String[] tokens = line.split("[ ]+"); 
    normals.add(new float[] { Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]), Float.parseFloat(tokens[3]) }); 
} 

private void processVTLine(String line) { 
    String[] tokens = line.split("[ ]+"); 
    uvs.add(new float[] { Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]) }); 
} 

private void processFLine(String line) { 
    String[] tokens = line.split("[ ]+"); 
    if (tokens.length == 4) { 
     makeFace3(tokens); 
    } 
} 

private void makeFace3(String[] tokens) { 
    if (tokens[1].matches("[0-9]+")) {// f: v 
     Face face = new Face(vertices.get(Integer.parseInt(tokens[1]) - 1), vertices.get(Integer.parseInt(tokens[2]) - 1), vertices.get(Integer.parseInt(tokens[1]) - 1)); 
     if (normals.size() > 0) { 
      face.setAn(normals.get(Integer.parseInt(tokens[1]) - 1)); 
      face.setBn(normals.get(Integer.parseInt(tokens[2]) - 1)); 
      face.setCn(normals.get(Integer.parseInt(tokens[3]) - 1)); 
     } 
     if (uvs.size() > 0) { 
      face.setAuv(uvs.get(Integer.parseInt(tokens[1]) - 1)); 
      face.setBuv(uvs.get(Integer.parseInt(tokens[2]) - 1)); 
      face.setCuv(uvs.get(Integer.parseInt(tokens[3]) - 1)); 
     } 
     faces.add(face); 
    } 
    if (tokens[1].matches("[0-9]+/[0-9]+")) { 
     Face face = new Face(vertices.get(Integer.parseInt(tokens[1].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[2].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     if (normals.size() > 0) { 
      face.setAn(normals.get(Integer.parseInt(tokens[1].split("/")[0]) - 1)); 
      face.setBn(normals.get(Integer.parseInt(tokens[2].split("/")[0]) - 1)); 
      face.setCn(normals.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     } 
     if (uvs.size() > 0) { 
      face.setAuv(uvs.get(Integer.parseInt(tokens[1].split("/")[1]) - 1)); 
      face.setBuv(uvs.get(Integer.parseInt(tokens[2].split("/")[1]) - 1)); 
      face.setCuv(uvs.get(Integer.parseInt(tokens[3].split("/")[1]) - 1)); 
     } 
     faces.add(face); 
    } 
    if (tokens[1].matches("[0-9]+//[0-9]+")) {// f: v//vn 
     Face face = new Face(vertices.get(Integer.parseInt(tokens[1].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[2].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     if (uvs.size() > 0) { 
      face.setAuv(uvs.get(Integer.parseInt(tokens[1].split("/")[0]) - 1)); 
      face.setBuv(uvs.get(Integer.parseInt(tokens[2].split("/")[0]) - 1)); 
      face.setCuv(uvs.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     } 
     if (normals.size() > 0) { 
      face.setAn(normals.get(Integer.parseInt(tokens[1].split("/")[2]) - 1)); 
      face.setBn(normals.get(Integer.parseInt(tokens[2].split("/")[2]) - 1)); 
      face.setCn(normals.get(Integer.parseInt(tokens[3].split("/")[2]) - 1)); 
     } 
     faces.add(face); 
    } 
    if (tokens[1].matches("[0-9]+/[0-9]+/[0-9]+")) { 
     Face face = new Face(vertices.get(Integer.parseInt(tokens[1].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[2].split("/")[0]) - 1), vertices.get(Integer.parseInt(tokens[3].split("/")[0]) - 1)); 
     if (uvs.size() > 0) { 
      face.setAuv(uvs.get(Integer.parseInt(tokens[1].split("/")[1]) - 1)); 
      face.setBuv(uvs.get(Integer.parseInt(tokens[2].split("/")[1]) - 1)); 
      face.setCuv(uvs.get(Integer.parseInt(tokens[3].split("/")[1]) - 1)); 
     } 
     if (normals.size() > 0) { 
      face.setAn(normals.get(Integer.parseInt(tokens[1].split("/")[2]) - 1)); 
      face.setBn(normals.get(Integer.parseInt(tokens[2].split("/")[2]) - 1)); 
      face.setCn(normals.get(Integer.parseInt(tokens[3].split("/")[2]) - 1)); 
     } 
     faces.add(face); 
    } 
} 

das Problem in der Leistung ist, ist es die Datei enthält etwa 120.000 Zeilen dieser Prozess etwa 90 Sekunden in Anspruch nimmt, die zu lang ist, weil ich Liest viele Modelle wie das will, wenn die Datei komplizierter und hat 850.000 Linie der Prozess dauert etwa 280 Sekunden, die nicht akzeptiert wird, kann die BufferReader die Linien sehr sehr schnell scannen aber die ArrayList Verarbeitung verursacht die langsam, ich testete die LinkedList aber das Ergebnis war schrecklich "5 mal langsamer", so ist da Eine Methode oder eine andere Lösung kann ich verwenden, um dies zu tun? später iteriere ich die Flächen ArrayList, um den Puffer zu erstellen und übergebe ihn an OpenGL.

bearbeiten I Vector mit den gleichen Linien 120,000 verwendete Datei das Ergebnis ist 109 Sekunden (20 Sekunden als ArrayList Erhöhung)

+0

Sie können Millionen von Zeilen pro Sekunde mit 'BufferedReader.readLine()' lesen. Die Leistung von 'ArrayList' ist im Javadoc definiert. Ihr Problem ist mit ziemlicher Sicherheit die sieben "if" Bedingungen. Unklar, was du verlangst. – EJP

+0

Ja, ich weiß, dass das Problem nicht im BufferedReader ist, ich lese die Datei und drucke jede Zeile, es ist wirklich sehr schnell, ich frage, wie bekomme ich eine Sammlung von Face s mit diesen Bedingungen schneller als die Arraylist oder einen Hinweis darauf Führen Sie meinen Code aus, möglicherweise verwende ich etwas in der falschen Weise – Mohamed

+0

So wissen Sie, dass das Problem nicht die gepufferte Anzeige ist, aber Sie erwähnen es in Ihrem Titel, in Ihrer Frage und in Ihren Umbauten. Warum? Haben Sie darüber nachgedacht, Ihren Titel, Ihre Frage und Ihre Tags auf das zu reduzieren, was tatsächlich relevant ist? – EJP

Antwort

1

BufferedReaderArrayList und sind nicht die Probleme.

Ihre Leistungsprobleme beruhen im Wesentlichen auf zwei Problemen: Zuweisung und Parsing.

Parsing - Teil I

String[] tokens = line.split("[ ]+"); 

Sie sind Zeichenüber die Zeichenfolge ein regulären Ausdruck. Dies ist der langsamste Weg, die Linie in Token zu teilen. Sie können dies beschleunigen, indem Sie selbst durch die Zeichenfolge iterieren und die Token aufbauen. Dies ist die "tief hängenden Früchte", die kleine Veränderung, die Ihnen die große Beschleunigung geben wird.

if (tokens[1].matches("[0-9]+")) {// f: v 

Wieder mit regulären Ausdrücken. Das verlangsamt dich.

Parsing - Teil II

Warum analysieren neu Sie etwas, das Sie bereits analysiert?

Face face = new Face(vertices.get(Integer.parseInt(tokens[1]) - 1), vertices.get(Integer.parseInt(tokens[2]) - 1), vertices.get(Integer.parseInt(tokens[1]) - 1)); 
    if (normals.size() > 0) { 
     face.setAn(normals.get(Integer.parseInt(tokens[1]) - 1)); 
     face.setBn(normals.get(Integer.parseInt(tokens[2]) - 1)); 
     face.setCn(normals.get(Integer.parseInt(tokens[3]) - 1)); 
    } 

Sie führen doppelte Anrufe an Integer.parseInt(tokens[x]) - 1. Sie sollten das Ergebnis einfach in eine int setzen und diese verwenden.

Allocation

Schauen Sie, wie oft Sie die new Betreiber anrufen. Jede Objektzuordnung wird Sie in Bezug auf die Leistung kosten. Schauen Sie sich alle new Betreiber in einer Schleife an und fragen Sie: Gibt es irgendeine Möglichkeit, das alles auf einmal zu machen? Zum Beispiel: Jeder Eckpunkt ist ein float[3]. Anstatt new float[3] immer und immer wieder aufzurufen, können Sie mit einem Testwert für numVertices beginnen und new float[numVertices][3] nur einmal anrufen? Das kann nicht in jeder Situation machbar sein, aber Sie sollten nach Möglichkeiten suchen, auf new Anrufe zu reduzieren.

In Verbindung damit ist die Verwendung von ArrayList. Es ist einfach, ArrayList zu verwenden, um Objekte zu sammeln, aber es ist nicht sehr effizient. Denken Sie daran, dass jedes Mal, wenn das Array ausläuft, ein neues Array zugewiesen und alle vorhandenen Daten in dieses Array kopiert werden müssen.

Das OBJ-Dateiformat ist nicht sehr freundlich, da es Scheitelpunkte, Koordinaten, Vektoren usw. abgibt, ohne Ihnen eine Zählung zu geben, die vorne verwendet werden könnte, was hier sehr hilfreich gewesen wäre.

+0

Ja, das ist die perfekte Antwort, du hast meine Zeit gerettet danke, auch ich bekomme ein paar tolle Ideen aus dieser Antwort, die großen Unterschied mit mir machen wird. – Mohamed

+1

Ich befolgte alle Anweisungen in dir große Antwort und ich bekomme erstaunliche Ergebnis, die gleiche Datei, die 180.000 Zeile hat und in 90 Sekunden geladen wurde, ist jetzt nur in 7 Sekunden geladen, Danke. – Mohamed

Verwandte Themen