2014-08-31 3 views
4

CodeEval에서 일부 작업을 수행하고 있습니다. 기본적으로 작업은 매우 간단합니다 : "파일에서 읽은 모든 정수의 합계를 출력하십시오".성능에 문제가있을 때 파일에서 정수를 읽는 방법?

import java.io.File; 
import java.io.IOException; 
import java.io.BufferedReader; 
import java.io.FileReader; 

public class SumIntegersFromFile { 

    public static void main(String args[]) throws IOException{ 

     File file = new File(args[0]); 
     BufferedReader br = new BufferedReader(new FileReader(file)); 
     String line; 
     int i=0; 
     while((line=br.readLine())!=null){ 
      int k = Integer.parseInt(line); 
      i+=k; 
     } 
     br.close(); 
     System.out.println(i); 
    } 
} 

을하지만이 솔루션은 성능 관점에서 최적이 아닌 들었다 :

내 솔루션은 다음과 같은됩니다.

코드는 질문 Best way to read a text file의 권장 사항을 기반으로합니다. 유일한 차이점은 문자열 대신 정수를 읽는 것입니다.

Java에서 파일의 정수를 읽는 가장 효율적인 방법은 무엇입니까?

+3

"35에서 29.352 만 얻었습니다"는 의미는 무엇입니까? – BitNinja

+9

이 질문은 작업 코드를 개선하기 때문에 주제와 관련이없는 것으로 보입니다. [codereview.se]에 게시 해보십시오. – Keppil

+0

@BitNinja 나는 점수를 의미했는데, 최대 점수는 35이고, 나는 29.352를 받았다. –

답변

1

명시 적으로 달리 언급하지 않는 한 합계가 int에 맞지 않는다고 가정해서는 안됩니다. i 유형을 long 또는 심지어 BigInteger으로 변경하고 점수에 차이가 있는지 확인하십시오.

k (와 Long.parseLong(line)을 사용하여 동일하게 시도해 볼 수 있습니다. 그것은 질문의 정확한 표현에 달려 있지만, 아마도 개별 값은 int의 한계를 초과 할 수 있습니다.

한 가지 더 ... 질문은, 당신이 말한 것처럼 모든 정수를 합산해야한다고 말합니다. 따라서 정수가 아닌 행이있을 가능성을 열어두기 때문에 NumberFormatException (현재 코드에서 수행 할 것입니다)을 던지기보다는 건너 뛸 수 있습니다.

(그리고 아마도 당신은이 한 줄에 하나의 항목 ... 있다고 들었다)

그러나 당신이 밖으로 성능의 모든 마지막 비트를 집어 넣은하려는 경우, 당신은 라인이 아닌 바이너리로 파일을 읽을 필요 한 줄씩 : 각 줄을 String으로 바꾸는 것은 너무 비쌉니다. 이를 수행하는 방법에 대한 자세한 설명은 this question on summing integers from a text file에서 찾을 수 있습니다.

+0

답변 해 주셔서 감사합니다. 나는이 문제를 올바르게 풀었고, 문제는 그것이 그렇게 최적화되어 있지 않다는 것이다. 전체 설명은 여기에 있습니다 : https://www.codeeval.com/open_challenges/24/ –

+0

점수의 전체 분석을 게시 할 수 있습니까? 얼마나 자세하게 설명해 주나요? –

+0

예를 여기에서 찾을 수 있습니다 : max_memory = 20 * 1024 * 1024 # 20메가바이트 MAX_TIME = * 1000 10 # 10 초 제출이 10 초 이상 # 소요 또는 메모리 #의 20메가바이트 이상을 사용하는 경우 # 점수 memory_taken 경우 0 > max_memory 또는 TIME_TAKEN> MAX_TIME : 복귀 0 max_total_score = total_max [분류] memory_factor = 1 - memory_taken/max_memory time_factor = 1 - TIME_TAKEN/MAX_TIME 계수 = (memory_factor + time_factor)/2 return score * max_total_score * factor/100 –

1

코드 성능에 문제가 없음을 알 수 있습니다. 즉, 귀하의 프로그램에 문제가 있다는 주장에 이의를 제기합니다.

파일에서 또는 네트워크를 통해 데이터를 읽는 것은 메모리에서 데이터를 조작하는 것보다 몇 배 더 느립니다. 따라서 메모리에서 일부 데이터 조작과 I/O를 혼합 한 코드의 성능은 일반적으로 I/O에 소요되는 시간에 의해 좌우됩니다. 메모리에서의 데이터 조작에 대한 조정은 거의 가치가 없습니다. 데이터 조작과 병렬로 I/O 작업이 수행되는 경우 (O/S가 미리 읽기를 수행하는 경우) 데이터 조작은 거의 자유로울 수 있습니다. 즉, 데이터 조작을 더 빠르게하면 어떤 시간이 걸리기 때문에 시간이 단축되지 않습니다. 데이터 조작을위한 CPU 시간의 감소는 입력을 기다리는 동안 프로그램이 차단하는 시간 양의 증가에 의해 정확하게 상쇄 될 것입니다.

I/O가 필요하고 성능이 좋은 프로그램은 I/O 대기를 차단하는 데 소비하는 시간을 줄여야합니다. 하드웨어 및 운영 체제가 제공하는 최적화를 활용하여 차단의 양을 줄일 수있는 방식으로 작동해야합니다.

중요하게도 낮은 수준에서 디스크 및 네트워크는 각 작업에 대해 작은 바이트 수로 작동하지 않습니다. 그들은 더 큰 단위의 패킷이나 블록을 사용합니다. 운영 체제와 상호 작용하여 하나의 디스크 블록에 저장되는 것보다 적은 바이트를 읽는 것은 낭비입니다.프로그램은 I/O를 버퍼링하여이를 피할 수 있으므로 프로그램 자체가 많은 작은 I/O 작업 시퀀스를 소수이지만 더 큰 작업으로 변경합니다. BufferedReader을 사용 중이므로 이미 그렇게하고 있습니다.

운영 체제는 미리 읽기를 수행하기 쉽습니다. 파일의 시작 부분에서 블록의 바이트를 요청하면 파일을 순차적으로 읽으므로 추측 할만한 가치가 있습니다. 또한 파일을 필요로하는 프로그램을 예상하여 파일의 후속 블록 중 일부를 가져옵니다. 파일을 순차적으로 읽으면 성능이 향상됩니다. 당신은 이미 그것을하고 있습니다.

관련 문제