2016-10-19 1 views
0

버퍼링 된 판독기를 사용하여 한 줄씩 읽는 Obj 파일 판독기를 만듭니다. 꼭지점 인 경우 각 줄을 확인해야합니다. 꼭지점 ArrayList에 추가하십시오. 얼굴 나는 Face 객체를 만들고 get(i) 개의 정점 ArrayList을 만들고 다른 2 개는 "normal and UVs"를 나열하여 얼굴 목록에 추가합니다. 이, 파일이 프로세스가 파일이 더 복잡한 경우 나, 같은 부하가 많은 모델 싶어하기 때문에 너무 긴 약 90 초 정도 걸립니다 약 12 ​​라인을 포함하는 문제는 성능에 코드안드로이드 속도 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); 
    } 
} 

입니다 그리고 850,000 라인을 가지고있는 프로세스는 받아 들여지지 않는 약 280 초가 걸리는데, BufferReader은 라인을 매우 빠르게 스캔 할 수 있지만 ArrayList 프로세싱은 느려지므로 나는 LinkedList을 테스트했지만 그 결과는 "5 배 느리다"는 것이 었습니다. 이 방법이나 다른 솔루션을 사용해도됩니까? 나중에 나는 얼굴을 반복하여 ArrayList으로 만들고 버퍼를 만들고 OpenGL에 전달합니다. I는 동일한 120,000 라인 Vector 사용

편집 은 (20초이보다 증가 ArrayList)

+0

'BufferedReader.readLine()'으로 초당 수백만 라인을 읽을 수 있습니다. 'ArrayList'의 성능은 Javadoc에서 정의됩니다. 당신의 문제는 거의 확실하게 7 가지 '조건'입니다. 네가 묻고있는 것이 불분명하다. – EJP

+0

예 BufferedReader에 문제가 없다는 것을 알았습니다. 파일을 읽은 다음 각 행을 인쇄하는 것이 정말 빠릅니다. arraylist 나 힌트보다 빠른 조건으로 Face 컬렉션을 얻는 방법을 묻습니다. 내 코드를 수행하고, 내가 잘못된 방식으로 뭔가를 사용하고있을 수도 있습니다. – Mohamed

+0

문제는 버퍼링 된 리드가 아니지만 제목, 질문 및 태그에서 언급 한 것입니다. 왜? 제목, 질문 및 태그를 실제로 관련성이있는 것으로 줄이는 것이 고려 되었습니까? – EJP

답변

1

BufferedReaderArrayList 문제가없는 결과를 109 초 파일.

성능 문제는 기본적으로 할당 및 구문 분석이라는 두 가지 문제로 나뉩니다.

구문 분석 - 부

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

당신은 정규 표현식를 사용하여 문자열을 토큰 화된다. 이것은 선을 토큰으로 분할 할 수있는 가장 느린 방법입니다. 당신은 문자열을 반복하고 당신이 갈 때 토큰을 만들어서 속도를 높일 수 있습니다. 이것은 "낮은 교수형 과일", 당신에게 큰 속도 향상을 줄 것이다 작은 변화입니다.

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