提高大文件的加载速度

时间:2010-07-22 20:39:51

标签: ruby performance

我的程序使用了两个大文本文件(数百万行)。这些文件被解析并加载到哈希中,以便可以快速访问数据。我面临的问题是,目前,解析和加载是程序中最慢的部分。以下是完成此操作的代码。

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。
  • 标准Ruby线程。
  • 分离流程,然后通过管道检索哈希值。

4 个答案:

答案 0 :(得分:2)

为什么不使用几十年经验设计的解决方案:一个数据库,比如SQLite3?

答案 1 :(得分:2)

在我的使用中,在解析之前将全部或部分文件读入内存通常会更快。如果数据库大小足够小,这可能就像

一样简单
buffer = File.readlines(database)
buffer.each do |line|
    ...
end

如果它们太大而无法适应内存,则会变得更加复杂,您必须设置数据的块读取,然后解析,或者使用单独的读取和解析线程进行线程化。

答案 2 :(得分:1)

(有所不同,虽然我首先建议查看(Ruby) BDB和其他“NoSQL”后端引擎,如果它们符合您的需要。)

如果使用具有确定性索引的固定大小的记录,则可以通过代理对象对每个项目执行延迟加载。这将是mmap的合适候选者。但是,这将加快总访问时间,但只会在程序的整个生命周期中分摊加载(至少在第一次使用之前,如果从未使用某些数据,那么你会得到永远不会加载它的好处)。如果没有固定大小的记录或确定性索引值,这个问题会更复杂,并且看起来更像传统的“索引”存储(例如,SQL后端的B树或BDB使用的任何一个: - )。

线程的一般问题是:

  1. IO 很可能成为围绕Ruby“绿色”线程的瓶颈
  2. 使用前仍需要所有数据
  3. 您可能对Widefinder Project感兴趣,通常只是“尝试加快IO处理速度”。

答案 3 :(得分:0)

我对Ruby知之甚少,但我之前不得不处理这个问题。我发现最好的方法是将文件拆分为块或单独的文件,然后生成线程以一次读取每个块。一旦分区文件在内存中组合,结果应该很快。以下是Ruby中Threads的一些信息:

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

希望有所帮助。