我有一个应用程序,它可以处理图像并使用延迟作业在后台创建PDF。使用Process.spawn
(通过运行GraphicsMagick进程的subexec-gem)处理图像。然后,我们使用Prawn gem创建一个PDF文件,其中包括这些图像和文本组件。我不相信虾宝石使用叉子或Spawn。我们使用的是Ruby 1.9.3。结果是,在制作了一些PDF文件后,我们的延迟作业处理的内存从大约120MB膨胀到超过800MB。
我知道派生的GraphicsMagick进程与父进程共享内存,但在子进程完成后,内存会还给系统吗?如果我在分叉过程中创建PDF文件,那么在分叉过程完成后,创建PDF文件时使用的内存会返回到系统吗?
我继续进行PDF创建任务并进行了测试。分叉进程确实在退出后将内存释放回系统,并且我们的延迟作业进程不再失控。我已经附上了代码,以防有人遇到类似的问题。有趣的是,运行Ruby1.9.3+Rails3.x,我们不需要在派生进程或父进程中重新连接数据库。在Stackoverflow的其他问题中对此有很多争论。
def run_in_fork
read, write = IO.pipe
pid = fork do
error = nil
read.close
begin
yield
rescue => e
error = e
end
Marshal.dump(error, write)
exit!(0) # skips exit handlers.
end
write.close
result = read.read
Process.wait(pid)
raise "Child process failed" if result.empty?
if exception = Marshal.load(result)
raise exception
end
return true
end
def my_method
object = MyObject.find.first
run_in_fork do
object.long_running_process
end
object.reload
end