У меня есть хэш Ruby, который достигает примерно 10 мегабайт, если записывается в файл с помощью Marshal.dump. После сжатия gzip это примерно 500 килобайт.
Итерация и изменение этого хэша очень быстро выполняется в рубине (доли миллисекунды). Даже копирование очень быстрое.
Проблема в том, что мне нужно разделить данные в этом хеше между процессами Ruby on Rails. Чтобы сделать это с помощью кеша Rails (file_store или memcached), мне сначала нужно Marshal.dump файл, однако при сериализации файла возникает задержка в 1000 миллисекунд, а при сериализации - 400 миллисекунд.
В идеале я хотел бы иметь возможность сохранять и загружать этот хэш из каждого процесса менее чем за 100 миллисекунд.
Одна идея состоит в том, чтобы создать новый процесс Ruby для хранения этого хэша, который предоставляет API другим процессам для изменения или обработки данных внутри него, но я хочу избегать этого, если я не уверен, что других нет способы быстро поделиться этим объектом.
Есть ли способ, которым я могу более напрямую разделять этот хэш между процессами без необходимости его сериализации или десериализации?
Вот код, который я использую для генерации хеша, аналогичного тому, с которым я работаю:
@a = []
0.upto(500) do |r|
@a[r] = []
0.upto(10_000) do |c|
if rand(10) == 0
@a[r][c] = 1 # 10% chance of being 1
else
@a[r][c] = 0
end
end
end
@c = Marshal.dump(@a) # 1000 milliseconds
Marshal.load(@c) # 400 milliseconds
Обновление:
Поскольку мой первоначальный вопрос не получил много ответов, я предполагаю, что не существует такого простого решения, как я бы надеялся.
В настоящее время я рассматриваю два варианта:
- Создайте приложение Sinatra для хранения этого хеша с API для его изменения / доступа.
- Создайте приложение C, чтобы сделать то же самое, что и # 1, но намного быстрее.
Объем моей проблемы увеличился, так что хеш может быть больше, чем в моем исходном примере. Так что № 2 может быть необходимым. Но я понятия не имею, с чего начать с точки зрения написания приложения на C, предоставляющего соответствующий API.
Хороший обзор того, как лучше всего реализовать # 1 или # 2, можно получить за лучший ответ.
Обновление 2
В итоге я реализовал это как отдельное приложение, написанное на Ruby 1.9, с интерфейсом DRb для связи с экземплярами приложения. Я использую гем Daemons для порождения экземпляров DRb при запуске веб-сервера. При запуске приложение DRb загружает необходимые данные из базы данных, а затем связывается с клиентом, чтобы вернуть результаты и оставаться в курсе. Сейчас он работает довольно хорошо. Спасибо за помощь!