Увеличение скорости загрузки больших файлов - PullRequest
1 голос
/ 23 июля 2010

Моя программа использует два больших текстовых файла (миллионы строк).Эти файлы анализируются и загружаются в хэши, чтобы к данным можно было быстро получить доступ.Проблема, с которой я сталкиваюсь, заключается в том, что в настоящее время анализ и загрузка являются самой медленной частью программы.Ниже приведен код, где это делается.

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 ]

2 голосов
/ 23 июля 2010

В моем случае чтение всего или части файла в память перед анализом обычно происходит быстрее.Если размеры базы данных достаточно малы, это может быть просто:

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

Если они слишком велики, чтобы уместиться в память, это усложняется, вам нужно настроить чтение блоков данных с последующим анализом,или с отдельными разделами для чтения и анализа.

2 голосов
/ 23 июля 2010

Почему бы не использовать решение, разработанное на основе многолетнего опыта: базу данных, скажем, SQLlite3?

1 голос
/ 23 июля 2010

(Для отличия, хотя я бы сначала рекомендовал взглянуть на (Ruby) BDB и другие механизмы "NoSQL", если они вам подходят.)

Если используются записи фиксированного размера с детерминированным индексом , то вы можете выполнить отложенную загрузку каждого элемента через прокси-объект. Это было бы подходящим кандидатом для mmap. Однако это не ускорит общее время доступа, а просто амортизирует загрузку в течение жизненного цикла программы (по крайней мере, до первого использования, а если некоторые данные никогда не используются, то вы получаете преимущество никогда не загружать его). Без записей фиксированного размера или детерминированных значений индексов эта проблема более сложна и начинает больше походить на традиционное хранилище «индексов» (например, B-дерево в серверной части SQL или что-либо другое, что использует BDB: -).

Общие проблемы с многопоточностью:

  1. IO вероятно станет вашим узким местом вокруг "зеленых" нитей Ruby
  2. Вам все еще нужны все данные перед использованием

Возможно, вас заинтересует Widefinder Project , просто "попытка ускорить обработку ввода-вывода".

0 голосов
/ 23 июля 2010

Я не слишком много знаю о Ruby, но мне приходилось сталкиваться с этой проблемой раньше.Я обнаружил, что лучшим способом было разделить файл на куски или отдельные файлы, а затем создать потоки, чтобы прочитать каждый кусок за один раз.Как только разделенные файлы находятся в памяти, результаты должны быть быстрыми.Вот некоторая информация о нитях в Ruby:

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

Надеюсь, что это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...