2014-02-22 2 views
0

는 I는 다음과 같은 형식대용량 데이터 파일을 반복적으로 처리하는 방법은 무엇입니까?

CO_1 0 0 0 0 1

CO_2 0 0 0 0 1

이 데이터 파일에는 450 만 명 엔트리와 공간 분리 된 데이터 파일을 가지고 이 파일 100 번을 반복하는 알고리즘 인 Self-Organizing Map (SOM)에 대한 입력으로 사용됩니다.

다음 readFile 함수를 사용하여 파일을 임시 문자열로 완전히 복사하고 문자열을 SOM 알고리즘에 전달합니다. 내가 느끼는 지금까지 위의 방법은 메모리에 무거운 부담을두고 어떻게

public String readFile() 
{ 
    String temp = ""; 

    try 
    { 
     FileReader file = new FileReader(FILE_LOCATION); 
     BR = new BufferedReader(file); 
     String strLine = null; 

     while((strLine = BR.readLine()) != null) 
     { 
      temp += strLine + "\n"; 
     } 
    } 
    catch(Exception e) 
    { 

    } 

    return temp; 
} 

메모리 오버런이 발생할 수 반복 속도가 느려집니다. 현재 30GB 메모리 할당을 사용하는 클러스터에서이 코드를 실행 중이며 실행은 약 36 시간 동안 단일 반복을 완료하지도 못합니다.

초기 블록이 완료되면 SOM이 데이터를 폴링해야하기 때문에 파일을 부분적으로 읽을 수 없으므로 훨씬 더 복잡해집니다.

어떻게 개선 할 수 있었는지 아이디어를 얻었으므로 성공적으로 450 만 항목을 100 번 반복 할 수있었습니다.

편집

전체 파일은 한 번 위의 방법을 사용하여 문자열에 읽습니다. 그런 다음 문자열 변수가 100 회 반복되는 동안 사용됩니다. 그러나 매번 문자열 tokenizers는 파일 * 반복 횟수의 각 행을 처리하는 데 사용되었습니다.

+0

파일을보다 효율적인 데이터 구조로 나타낼 수 있습니까? 예를 들어,''Map ''에 대해''map.put (1, new BitSet())'형식의 항목을 갖는 경우는 무엇입니까? 여기서''1'' 키를 사용하여 문자열을 나타냅니다 나머지 문자열을 표현하기 위해''CO_1''과''0 0 0 0 1''을 포함하는 비트 셋을 사용합니까? – gdiazc

+0

@Synex 어떤 부분이 가장 오래 걸리는지 확인하기 위해 코드를 프로파일 링 해 보셨습니까? – Alan

+0

@Alan 아니요. 어떤 제안? Eclipse IDE – Synex

답변

2

이러한 목적으로 문자열 연결을 사용하지 마십시오.
String 대신 StringBuffer 클래스를 사용하십시오.
다음 예제 고려 :

public StringBuffer readFile() 
{ 
    StringBuffer tempSB = new StringBuffer(); 

    try 
    { 
     FileReader file = new FileReader(FILE_LOCATION); 
     BR = new BufferedReader(file); 
     String strLine = null; 

     while((strLine = BR.readLine()) != null) 
     { 
      tempSB.append(strLine); 
      tempSB.append("\n"); 
     } 
    } 
    catch(Exception e) 
    { 

    } 

    return temp; 
} 

이 힙 메모리를 저장합니다.

+0

이 상황에서, 대략적으로 얼마나 많은 데이터가 StringBuffer의 초기 용량을 지정하는 것이 현명 할 수 있으므로 크기 조정을 반복 할 필요가 없습니다. 예 : '= new StringBuffer (typical_line_length * rough_number_of_lines);' – Alan

+0

동기화가 필요 없으므로 여기에서'StringBuilder'를 사용할 수 있습니다. – qqilihq

+0

어떤 텍스트라도 찾으려면''Lucene Indexing''을 찾아야합니다. – unknown

0

String + =로 파일을 읽는 것은 매우 비쌉니다. 항목을 데이터 구조로 파싱하고 약 1-10 초가 걸릴 것이라고 제안합니다. 이 작업을 반복하려면 1 초도 채 걸리지 않아야합니다. 엔트리 당 110 바이트를 사용하는 4.5 백만개의 엔트리는 약 0.5GB, 아마도 더 복잡한 구조의 경우 1GB를 사용해야합니다. 걱정할 정도는 아닙니다.

0

당신이 TXT에게 시리얼 파일을 구문 분석하고 무작위로하는 SQL DB 또는 no-SQL 하나 또는 심지어 Lucene Search Engine처럼 영구 저장소를 사용 를 읽을 수 있어야합니다. > 파일 한 줄 한 줄을 읽어 만 유지 -

  • 사용할 수있는 스트림 처리 RAM에 전체 파일을로드 할 필요는 없습니다 : 이렇게하면 같은 혜택을 줄 것이다 RAM에있는 실제 라인
  • 소스 파일을 파싱하고 지속하는 데는 약간의 시간이 걸리지 만 랜덤 액세스는 훨씬 빠릅니다.
  • 당신도 독립적으로
+0

더 많은 데이터가 있다면 이것은 좋은 아이디어 일지 모르지만 Synex는 상대적으로 작은 세트 만 다루기 때문에 DB를 사용하는 것이 과잉이라고 생각합니다. 각 레코드는 짧은 문자열, 문자 및 5 개의 숫자입니다. 이것은 엔트리 당 100 바이트보다 작아서 0.5GB보다 작습니다. 괜찮은 기계라고 가정하면 이것이 문제가되어서는 안됩니다. – Alan

+0

글쎄, 36 시간의 처리 시간과 30GB의 RAM *은 이미 과잉 공격이다 :) 어쨌든 단기간의 관점에서도 DB를 한 번만 설정하면된다. – injecteer

+0

나는 동의한다. @Alan. 파일 크기가 약 100MB 인 것 같기 때문에 메모리 내 솔루션이이 경우에 더 적합합니다. – gdiazc

2

내가 다른 대답을 보완하고 싶습니다 분석하고 여러 스레드에서 데이터를 읽을 수 있습니다. 비록 당신이 데이터를 문자열보다 효율적인 데이터 구조에 저장해야한다고 생각하지만, 코드가 느려지는 다른 이유가 있다고 생각합니다.

파일 크기가 약 100MB 인 것 같기 때문에 Eclipse가 충분한 힙 공간을 할당하지 않았기 때문에 코드가 느려질 수 있습니다. 다음 플래그를 추가하십시오.

-Xmx4G 

이렇게하면 작업 할 4GB의 힙 공간 코드가 제공됩니다. 이렇게하려면 Eclipse에서 다음으로 이동하십시오.

// Run -> Run Configurations -> <Select your main class on the left> 
// -> <Select the 'Arguments' tab> 
// -> <Add the string "-Xmx4G" to the 'VM arguments' text area> 

이렇게하면 속도가 빨라질 수 있습니다!

관련 문제