Rails设计疑点:我应该/可以将整个字典/表加载到内存中吗?

fjs*_*js6 5 memory-management ruby-on-rails

我是一个在一个简单的Rails应用程序中工作的新手,它将文档(长字符串)从一种语言翻译成另一种语言.字典是一个术语表(一个用于查找和替换的字符串regexp,以及一个输出替换字符串的块).该表长达100万条记录.

每个请求都是一个想要翻译的文档.在第一个野蛮的力量方法中,我需要针对每个请求/文档运行整个字典.

由于字典每次都会运行(从第一个记录到最后一个),而不是用每个文档加载字典记录表,我认为最好将整个字典作为内存中的数组.

我知道它不是最有效的,但字典必须在这一点上运行.

1.-如果通过重组文档和字典无法获得效率(意味着无法创建较小的字典子集).什么是最好的设计方法?

2.-您是否了解我可以从中学到的类似项目?

3.-我应该在哪里学习如何在rails启动时将这么大的表加载到内存(缓存?)?

任何提出的问题的任何答案将不胜感激.非常感谢你!

Jul*_*lik 2

我认为您的网络托管服务商不会对这样的解决方案感到满意。这个脚本

dict = {}
(0..1000_000).each do | num |
    dict[/#{num}/] = "#{num}_subst"
end
Run Code Online (Sandbox Code Playgroud)

在我的 MBP 上消耗了 1 GB 的 RAM 来存储哈希表。另一种方法是将您的替换存储在内存缓存中,以便您(至少)可以跨计算机存储它们。

require 'rubygems'
require 'memcached'
@table = Memcached.new("localhost:11211")

retained_keys = (0..1000_000).each do | num |
  stored_blob = Marshal.dump([/#{num}/, "#{num}_subst"])
  @table.set("p#{num}", stored_blob)
end
Run Code Online (Sandbox Code Playgroud)

您将不得不担心如何保持密钥“热”,因为如果不需要它们,memcached 将使它们过期。

然而,对于您的情况,最好的方法非常简单 - 将替换写入一个文件(每个替换一行)并创建一个流过滤器,逐行读取文件,并从此文件中进行替换。您还可以通过映射工作来并行化它,例如,每个替换字母和替换标记。

但这应该让你开始:

  require "base64"

  File.open("./dict.marshal", "wb") do | file |
    (0..1000_000).each do | num |
      stored_blob = Base64.encode64(Marshal.dump([/#{num}/, "#{num}_subst"]))
      file.puts(stored_blob)
    end
  end

  puts "Table populated (should be a 35 meg file), now let's run substitutions"

  File.open("./dict.marshal", "r") do | f |
    until f.eof?
      pattern, replacement = Marshal.load(Base64.decode64(f.gets))
    end
  end

  puts "All replacements out"
Run Code Online (Sandbox Code Playgroud)

要填充文件并加载每个替换,我需要执行以下操作:

 real    0m21.262s
 user    0m19.100s
 sys     0m0.502s
Run Code Online (Sandbox Code Playgroud)

只需从文件中加载正则表达式和字符串(全部一百万个,一块一块)

 real    0m7.855s
 user    0m7.645s
 sys     0m0.105s
Run Code Online (Sandbox Code Playgroud)

因此,这是 7 秒的 IO 开销,但您不会丢失任何内存(并且还有巨大的改进空间) - RSIZE 约为 3 兆。如果您批量进行 IO,或者制作一个文件进行 10-50 次替换并将它们作为一个整体加载,您应该能够轻松地使其运行得更快。将文件放在 SSD 或 RAID 上,您就获胜了,但您可以保留 RAM。