1


1

大きなファイルの読み込み速度を上げる

私のプログラムが使用する2つの大きなテキストファイル(数百万行)があります。 これらのファイルは解析され、ハッシュにロードされるため、データにすばやくアクセスできます。 私が直面している問題は、現在、解析と読み込みがプログラムの最も遅い部分であることです。 以下は、これが行われるコードです。

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
I've messed around with different ways of setting up the file and
parsing them, and so far this is the fastest way, but it's still awfully
slow.

Is there a way to improve the speed of this, or is there a whole other
approach I can take?

*List of things that don't work*:

* YAML.
* Standard Ruby threads.
* Forking off processes and then retrieving the hash through a pipe.

4 Answer


2


何十年もの経験を経て考案されたソリューション、データベース、SQLite3を使用してみませんか?


2


私の使用法では、解析する前にファイルの全部または一部をメモリに読み込むと、通常は速くなります。 データベースのサイズが十分に小さい場合、これは次のように簡単です。

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

それらが大きすぎてメモリに収まらない場合は、より複雑になります。データのブロック読み取りに続いて解析を設定するか、読み取りスレッドと解析スレッドを別々にスレッド化する必要があります。


1


(異なるために、最初にhttp://www.rubyinside.com/bdb-improved-ruby-bindings-for-berkeley-db-1438.html[(Ruby)BDB]および他の「NoSQL 「バックエンドエンジン(必要に応じて)。)

確定的なインデックスを持つ固定サイズのレコードが使用されている場合、プロキシオブジェクトを介して各アイテムの遅延ロードを実行できます。 これは、mmapの適切な候補です。 ただし、これは合計アクセス時間を_not_スピードアップしませんが、プログラムのライフサイクル全体でロードを償却します(少なくとも最初に使用するまで、一部のデータが使用されない場合は、ロードしないという利点があります)。 固定サイズのレコードまたは確定的なインデックス値がないと、この問題はより複雑になり、従来の「インデックス」ストアのように見え始めます(例: SQLバックエンドのBツリーまたはBDBが使用するもの:-)。

ここでのスレッド化に関する一般的な問題は次のとおりです。

  1. IOは_likely_ Rubyの「グリーン」スレッドのボトルネックになります

  2. あなたはまだ使用する前にすべてのデータが必要です

Widefinder Projectに興味があるかもしれません。一般的には「より高速なIO処理の取得」です。


0


私はRubyについてあまり知りませんが、以前は問題に対処しなければなりませんでした。 最良の方法は、ファイルをチャンクまたは個別のファイルに分割し、スレッドを生成して各チャンクを一度に読み込むことであることがわかりました。 パーティション化されたファイルがメモリに結合されると、結果は高速になります。 Rubyのスレッドに関する情報を次に示します。

お役に立てば幸いです。