2010-07-22 5 views
1

내 프로그램에서 사용하는 두 개의 큰 텍스트 파일 (수백만 줄)이 있습니다. 이러한 파일은 해시에 구문 분석되고로드되어 데이터에 빠르게 액세스 할 수 있습니다. 내가 직면 한 문제는 현재 파싱 및 로딩이 프로그램에서 가장 느린 부분이라는 것입니다. 다음은이 작업이 수행되는 코드입니다.대용량 파일의로드 속도 증가

database = extractDatabase(@type).chomp("fasta") + "yml" 
revDatabase = extractDatabase(@type + "-r").chomp("fasta.reverse") + "yml" 
@proteins = Hash.new 
@decoyProteins = Hash.new 

File.open(database, "r").each_line do |line| 
    parts = line.split(": ") 
    @proteins[parts[0]] = parts[1] 
end 

File.open(revDatabase, "r").each_line do |line| 
    parts = line.split(": ") 
    @decoyProteins[parts[0]] = parts[1] 
end 

그리고 파일은 아래 예와 같습니다. YAML 파일로 시작했지만 파싱 속도를 높이기 위해 형식이 수정되었습니다.

MTMDK: P31946 Q14624 Q14624-2 B5BU24 B7ZKJ8 B7Z545 Q4VY19 B2RMS9 B7Z544 Q4VY20 
MTMDKSELVQK: P31946 B5BU24 Q4VY19 Q4VY20 
.... 

내가 그들을 파일을 설정 및 구문 분석의 다른 방법으로 주위를 엉망했습니다, 그리고 지금까지 가장 빠른 방법이지만, 여전히 지독하게 느리다.

속도를 향상시킬 수있는 방법이 있습니까, 아니면 제가 취할 수있는 다른 접근법이 있습니까? 작동하지 않는 것들의

목록 :

  • YAML.
  • 표준 루비 스레드.
  • 프로세스를 포크하고 파이프를 통해 해시를 검색합니다.
+0

C 확장 프로그램 작성 방법은 무엇입니까? – CodeJoust

+0

Ruby 1.8 또는 1.9를 사용하고 있습니까? 1.9는 1.8보다 10-20 % 더 빠르다. (이런 종류의 윈도우에서는 윈도우가 훨씬 더 커진다.) – Digikata

+0

1.9.1을 사용하고 있습니다. –

답변

2

제 사용법에서는 일반적으로 구문 분석을하기 전에 파일을 메모리에 전부 또는 일부만 읽는 것이 더 빠릅니다. 데이터베이스의 크기가 작다면 충분이, 당신은 설정에 블록 구문 분석, 또는 스레드 다음으로 읽은 데이터가 간단

buffer = File.readlines(database) 
buffer.each do |line| 
    ... 
end 

가 더 복잡해진다, 메모리에 비해 너무 큰 경우

로 수 별도의 읽기 및 구문 분석 스레드가 있습니다.

+0

약 30 초 동안 면도했지만 2 분 이상 걸립니다. –

+0

이 작업을 수행 한 후이 메서드에 대한 다른 변경을하면 시간이 감소한다는 것을 알았습니다. 이러한 개선 및 기타 개선을 통해 이제는 수용 가능한 시간으로 내려갔습니다. –

0

루비에 대해 너무 많이 알지는 않지만 이전에이 문제를 해결해야했습니다. 가장 좋은 방법은 파일을 덩어리로 분리하거나 파일을 분리하여 스레드를 생성하여 한 번에 각 덩어리를 읽는 것입니다. 분할 된 파일이 메모리에 결합되면 결과가 빨라야합니다.

http://rubylearning.com/satishtalim/ruby_threads.html

희망하는 데 도움이 : 여기에 루비의 스레드에 대한 몇 가지 정보입니다.

+0

정말 도움이 될까요? 필자가 언급 한 것처럼, 각 파일에 대해 스레드를 사용했을 때 속도가 느려졌 기 때문에. –

2

수십 년간의 경험을 통해 고안된 솔루션을 사용하지 않는 이유는 무엇입니까? 데이터베이스 (예 : SQLlite3)는 무엇입니까?

+0

+1, 단순한 키/값에 대해서는 "한번로드 된"단계 이후에 좋지 않을 수도 있지만. 또 다른 옵션은 BDB 스타일 (Berkley-DB) 스타일 백엔드입니다. 단순한 키/값 저장소이고 추가적인 SQL 관계 및 조인이 필요하지 않은 경우에 사용합니다. –

1

(내가 처음 (Ruby) BDB 및 기타 "NoSQL에"백엔드 엔진을보고 권 해드립니다 비록 그들이 당신의 필요에 맞게 경우, 다른합니다.)

결정적 인덱스에 고정 된 크기의 기록 인 경우 프록시 객체를 통해 각 항목의 지연로드를 수행 할 수 있습니다. 이것은 mmap에 적합한 후보가 될 것입니다. 그러나 이것은 이 아니며은 전체 액세스 시간을 가속화하지 않지만 프로그램의 수명주기 전체에 걸쳐로드를 상각합니다 (적어도 처음 사용하기까지 그리고 일부 데이터가 사용되지 않으면로드하지 않는 이점을 얻습니다).). 고정 된 크기의 레코드 나 결정 론적 인덱스 값이 없다면이 문제는 더욱 복잡해지고 전통적인 "인덱스"저장소 (예 : SQL 백엔드의 B- 트리 또는 BDB가 사용하는 모든 것 :-)처럼 보이기 시작합니다.

여기 스레딩과 일반적인 문제

은 다음과 같습니다

  1. IO는 가능성이 당신은 여전히 ​​모든 데이터를 사용하기 전에 필요한
  2. 루비 "녹색"스레드 주위에 당신의 병목이 될 것입니다

Widefinder Project에 관심이있을 것입니다. 일반적으로 "빠른 IO 처리를 시도합니다".

+0

데이터베이스를 만드는 데 걸리는 시간은 참을 수가 없었습니다. –