XML生成非常慢并且在Rails 4中使用了大量内存

时间:2016-11-20 07:39:56

标签: ruby-on-rails ruby-on-rails-4 heroku

我正在生成一个XML文件,以便与另一个系统共享数据。根据我的故障排除,我发现这个过程既缓慢又消耗大量内存(在Heroku上获得大量R14。)

我的Jobs Controller上的索引方法如下所示:

def index
  respond_to do |format|
    format.xml {@jobs = @user.jobs.includes(job_types: [:job_lines, :job_photos])}
    format.json 
    { 
      # More code here, this part is not the problem.
    }
  end
end

我的视图(index.xml.builder)看起来像这样(我删除了一堆字段以保持示例更小):

xml.instruct!
xml.jobs do
  @jobs.each do |j|
    xml.job do
      xml.id             j.id
      xml.job_number     j.job_number
      xml.registration   j.registration
      xml.name           j.name
      xml.job_types do
        j.job_types.each do |t|
          xml.job_type do
            xml.id          t.id
            xml.job_id      t.job_id
            xml.type_number t.type_number
            xml.description t.description
            xml.job_lines do
              t.job_lines.each do |l|
                xml.job_line do
                  xml.id          l.id
                  xml.line_number l.line_number
                  xml.job_type_id l.job_type_id
                  xml.line_type   l.line_type
                  xml.type_number l.type_number
                  xml.description l.description
                  xml.part_number l.part_number
                end # job_line node
              end # job_lines.each
            end # job_lines node
            xml.job_photos do
              t.job_photos.each do |p|
                xml.job_photo do
                  xml.id          p.id
                  xml.pcid        p.pcid
                  xml.job_type_id p.job_type_id
                  xml.image_url   p.image.url
                end # job_line node
              end # job_lines.each
            end # job_lines node
          end # job_type
        end # job_types.each
      end # job_types node
    end # job node
  end # @jobs.each
end # jobs node

生成的XML文件不小(大约100kB)。在Heroku上运行,他们的Scout工具告诉我这个过程通常需要4-6秒才能运行。此外,尽管只运行了1个工作线程,但有4个线程(在Puma中),这部分代码消耗了我所有的内存。在scout中,我可以看到它的“Max Allocations”高达10M,而我的下一个最差方法只有500k的分配。

谁能告诉我我做错了什么?是否有更高效的(在速度和内存使用方面)生成XML的方式?

任何帮助都将不胜感激。

编辑1

我已尝试像这样手动构建XML:

joblist.each do |j|
  result << "  <job>\n"
  result << "    <id>" << j.id.to_s << "</id>\n"
  result << "    <job_number>"    << j.job_number.to_s << "</job_number>\n"
  # Lots more lines removed
end 

这给了我一些改进。我最大的拨款现在是1.8M。我接近Heroku的限制(在24小时内达到512MB限制的最大值500MB)。

我仍然只运行1个带有4个线程的工作者。如果我能够更多地记住内存,那么我可以运行更多的Puma Workers和Threads。

编辑2

我最终必须批量执行此操作(使用偏移和限制)并一次发送5个作业。当我这样做时,内存使用量大幅下降。显然,对控制器的调用越来越多,但每个调用都越来越小。

0 个答案:

没有答案