Ruby大量的哈希和内存使用情况

时间:2018-10-30 10:40:15

标签: ruby memory hash

如何提高内存使用率?

我负责从英语到10种语言的翻译。

例如:TRANSLATION_HASH["dog"]["fr"] => chien.

TRANSLATION_HASH包含1亿个英语表达式。

它很好用,但是需要10Gb的内存。 注意:TRANSLATION_HASH是只读的(我从不写过)

在开始时全部加载一次(10000万个英语表达式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

3 个答案:

答案 0 :(得分:1)

您应该熟悉Hash在存储器中的存储方式。关于该here的博客很好。

如果您的词典仅包含单词而不是短语,则每种语言应该只有大约90mb的数据(假设参考字节为4个字节,平均单词长度为5个字符),这意味着总共大约1gb的数据,哈希和字符串的方式工作将需要更多的内存,每个字符串是一个对象,其中包含诸如内存位置,字符编码,长度等信息。因此,纯文本数据的十倍的内存消耗实际上是Ruby的一个相当不错的成就。​​

正如其他人所建议的那样,最好的选择是将这些数据存储在数据库或键值存储(例如Redis)中,但是由于性能问题您拒绝了该选项(在常规笔记本电脑上,Redis可以在每秒50万个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'

此外,我不禁要指出,以这种方式制作的翻译器不会产生在任何情况下都有用的结果。您不能仅仅通过用另一种语言的单词翻译来替换每个单词来充分地翻译。另外,您还必须为每个语法情况存储对,“睡觉,睡觉,睡觉,睡觉,睡觉,睡觉,睡着……”甚至要找到匹配的单词。

此外,《牛津英语词典》仅包含171476个单词。

答案 1 :(得分:0)

在我的计算机上,对于一千万个元素的只读(冻结对象)哈希(字符串到字符串):

Ruby哈希:每秒150万个请求,内存为5.1%。

GoogleHashSparseRubyToRuby:每秒344 000个请求,内存为4%。

Redis的@KimmoLehto建议(使用套接字文件):每秒<5 000个请求,低内存(外部事务中的数据)。

如果性能不成问题,Redis将是最好的解决方案(减少内存)。

编辑:Ruby Hash的哈希键(key.hash)是一个很好的优化,可以减少内存使用。

答案 2 :(得分:0)

进行以下更改后,它占用的内存更少,并且速度更快:

TRANSLATION_HASH是哈希的哈希(哈希中存储了1亿个哈希) 索引(例如:“ dog”)是一个字符串

例如:TRANSLATION_HASH [“ dog”] [“ fr”] =>“ chien”。

已更改: TRANSLATION_INDEX [“ dog”] => 1169 //散列为每个10000000个英语表达式存储一个uniq键。 TRANSLATION_FR [1169] =>“ chien” TRANSLATION_ES [1169] =>“ perro” ...

因此,我将1万个哈希值变成了11,并使用int索引进行工作。