Ruby огромный хэш и использование памяти - PullRequest
0 голосов
/ 30 октября 2018

Как улучшить использование памяти?

Я делаю переводчик, с английского на 10 языков.

Пример: TRANSLATION_HASH["dog"]["fr"] => chien.

TRANSLATION_HASH содержит 10 000 000 английских выражений.

Отлично работает, но занимает 10 Гб памяти .... Примечание: TRANSLATION_HASH только для чтения (я никогда не пишу в него)

Все загружено (10 000 000 английских выражений X 10 переводов) один раз при запуске:

TRANSLATION_HASH["word 1"]["fr"] = "french word from word 1" TRANSLATION_HASH["word 1"]["es"] = "Spanish word from word 1" TRANSLATION_HASH["word 1"]["de"] = "German word from word 1

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

Для хэша из 10 миллионов элементов (строки в строки) только для чтения (замороженные объекты) на моем компьютере:

Рубиновый хэш: 1 500 000 запросов в секунду, 5,1% памяти.

GoogleHashSparseRubyToRuby: 344 000 запросов в секунду, 4% памяти.

В соответствии с предложением @KimmoLehto, Redis (с использованием файла сокета): <5000 запросов в секунду, низкий объем памяти (данные во внешней части). </p>

Redis был бы лучшим решением (уменьшить память), если бы производительность не была проблемой.

РЕДАКТИРОВАТЬ: хеширование ключей (key.hash) Ruby Hash, было отличной оптимизацией и сократить использование памяти.

0 голосов
/ 30 октября 2018

Вам следует ознакомиться с тем, как Hash хранится в памяти. Есть хороший пост в блоге об этом здесь .

Если ваш словарь содержит только слова, а не фразы, у вас должно быть около 90 МБ данных на язык (при условии, что 4 байта для справки и средняя длина слова 5 символов), то есть всего около 1 ГБ данных, способ хэширования и строки работа потребует гораздо больше памяти, чем каждая, каждая строка является объектом, который содержит информацию, такую ​​как место в памяти, кодировка символов, длина и так далее. Таким образом, использование Ruby в десять раз больше по сравнению с обычными текстовыми данными - неплохое достижение.

Как и предполагали другие, лучшим вариантом будет сохранение этих данных в базе данных или хранилище значений ключей, таких как Redis, но вы отклонили этот вариант из-за проблем с производительностью (на обычном ноутбуке Redis может работать более 500 000 GET в секунду).

Другим вариантом сокращения потребления памяти будет сокращение использования хешей и использование индексов массива. Ваш переводчик может выглядеть так:

TRANSLATIONS = { 
  "hello" => ['bonjour', 'hola'],
  "thanks" => ['merci', 'gracias']
}

LANGUAGES = { french: 0, spanish: 1 }

def translate(english_word, language)
  TRANSLATIONS.dig(english_word, LANGUAGES[language])
end

translate('hello', :spanish)
 => 'hola'

Кроме того, я не могу не отметить, что созданный таким образом переводчик не дает результата, который полезен в любом контексте. Вы не можете перевести достаточно, просто заменив каждое слово переводом слова с другого языка. Также вам придется хранить пары для каждого грамматического падежа: «спать, спать, спать, спать, спать, спать, спать, ...», чтобы даже найти подходящее слово.

Кроме того, Оксфордский словарь английского языка содержит только 171 476 слов.

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