2016-10-19 10 views
0

Я создаю программу чтения файлов Obj, которая читается по строкам с использованием буферизованного считывателя, я должен проверять каждую строку, если она является вершиной, я добавляю ее в вершины ArrayList, и если она лицо создаю объект Face, который get(i) вершины ArrayList, а еще 2 - «нормальные и УФ», а затем добавьте в список лиц. это кодAndroid speed BufferedReader читает строку и ArrayList добавляет и получает

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); 
    } 
} 

проблема в производительности, файл содержит около 120000 линии, этот процесс занимает около 90 секунд, что является слишком долго, потому что я хочу загружать много моделей, как, что, если файл является более сложным, и имеет 850 000 строк, процесс занимает около 280 секунд, что не принимается, BufferReader может сканировать линии очень быстро, но обработка ArrayList вызывает медленное, я тестировал LinkedList, но результат был ужасным «в 5 раз медленнее», так есть метод или другое решение, которое я мог использовать для этого? позже я повторяю грани ArrayList, чтобы создать буфер и передать его OpenGL.

Редактировать Я использовал Vector с теми же 120000 строк файла результат составляет 109 секунд (20 секунд увеличивая, чем ArrayList)

+0

Вы можете прочитать миллионы строк в секунду с 'BufferedReader.readLine()'. Производительность 'ArrayList' определена в Javadoc. Ваша проблема - почти наверняка семь условий 'if'. Неясно, что вы спрашиваете. – EJP

+0

Да, я знаю, что проблема не в BufferedReader, я проверяю прочитать файл и распечатать каждую строку это действительно очень быстро, я спрашиваю, как я могу получить коллекцию Face s с этими условиями быстрее, чем ArrayList или каким-либо намек на выполнить свой код, может быть, я что-то использовать в неправильном – Mohamed

+0

Таким образом, вы знаете, что проблема заключается не в буферном Reade, но вы об этом в своем названии, ваш вопрос, и теги. Зачем? Вы считали, что вы сокращаете свой титул, свой вопрос и ваши теги на то, что на самом деле актуально? – EJP

ответ

1

BufferedReader и ArrayList не являются проблемы.

Ваши проблемы с производительностью в основном сводятся к двум вопросам: распределение и разбор.

Синтаксических - Часть I

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

Вы tokenizing строки, используя регулярное выражение . Это самый медленный способ разделить линию на токены. Вы можете ускорить это, итерации через струну самостоятельно и наращивание жетонов, когда вы идете. Это «низко висящий плод», небольшое изменение, которое даст вам большое ускорение.

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

Снова, используя регулярные выражения. Это замедляет вас.

Синтаксический - Часть II

Почему вы повторно проанализировать то, что вы уже разобраны?

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)); 
    } 

Вы делаете дублирующие звонки на номер Integer.parseInt(tokens[x]) - 1. Вы должны просто поместить результат в int и использовать его.

Распределение

Посмотрите, сколько раз вы звоните оператору new. Каждое распределение объектов будет стоить вам с точки зрения производительности. Посмотрите на каждого оператора new в цикле и спросите: есть ли способ сделать это все сразу? Например: каждая вершина равна float[3]. Вместо того, чтобы снова и снова звонить new float[3], можете ли вы начать с пробного значения для numVertices и позвонить new float[numVertices][3] только один раз? Это может быть невыполнимо в любой ситуации, но вы должны искать возможности для сокращения вызовов new.

относящиеся к тому, что является использование ArrayList. Легко использовать ArrayList для накопления объектов, но это не очень эффективно. Помните, что каждый раз, когда массив выходит из строя, должен выделяться новый массив и копировать все существующие данные.

Этот формат файла OBJ не очень дружелюбно в том, что она сваливает вершины, координаты, векторы и т.д., не давая вам счетчик фронт использовать, которые были бы очень полезны здесь.

+0

Да, это прекрасный ответ, вы спасли мое время, спасибо, также я получаю отличные идеи из этого ответа, которые будут иметь большое значение для меня. – Mohamed

+1

Я следовал всем инструкциям в вас большой ответ, и я получаю удивительный результат, тот же самый файл, который имеет 180.000 линию и погрузки в 90 секунд теперь загружается всего за 7 секунд, спасибо. – Mohamed