ruby-on-rails – 从一堆模型对象生成XML时速度较慢

class GenericFormatter < Formatter
 attr_accessor :tag_name,:objects

 def generate_xml
   builder = Nokogiri::XML::Builder.new do |xml|
   xml.send(tag_name.pluralize) {
   objects.each do |obj|
        xml.send(tag_name.singularize){

            self.generate_obj_row obj,xml
        }                
    end
    }
   end
   builder.to_xml
 end


def initialize tag_name,objects
  self.tag_name = tag_name
  self.objects = objects
end


def generate_obj_row obj,xml
   obj.attributes.except("updated_at").map do |key,value|
     xml.send(key, value)
   end
   xml.updated_at obj.updated_at.try(:strftime,"%m/%d/%Y %H:%M:%S") if obj.attributes.key?('updated_at')
end
 end 

在上面的代码中,我实现了格式化程序,我使用nokogiri XML Builder通过操作代码中传递的对象来生成XML.当数据不是太大时,如果数据更大,则生成更快的XML超过10,000个记录然后它会减慢生成的XML并且至少需要50-60秒.

问题:有没有办法更快地生成XML,我在视图上也尝试过XML Builders但是没有用.我怎么能更快地生成XML?该解决方案应该是rails 3上的应用程序以及优化上述代码的建议吗?

最佳答案
您的主要问题是一次性处理所有内容,而不是将数据分成批次.这一切都需要大量内存,首先构建所有这些ActiveRecord模型,然后构建整个xml文档的内存表示.元编程也很昂贵(我的意思是那些发送方法).

看看这段代码:

class XmlGenerator
  attr_accessor :tag_name, :ar_relation

  def initialize(tag_name, ar_relation)
    @ar_relation = ar_relation
    @tag_name = tag_name
  end

  def generate_xml
    singular_tag_name = tag_name.singularize
    plural_tag_name = tag_name.pluralize

    xml = ""
    xml << "<#{plural_tag_name}>"

    ar_relation.find_in_batches(batch_size: 1000) do |batch|
      batch.each do |obj|
        xml << "<#{singular_tag_name}>"

        obj.attributes.except("updated_at").each do |key, value|
          xml << "<#{key}>#{value}</#{key}>"
        end

        if obj.attributes.key?("updated_at")
          xml << "<updated_at>#{obj.updated_at.strftime('%m/%d/%Y %H:%M:%S')}</updated_at>"
        end

        xml << "</#{singular_tag_name}>"
      end
    end

    xml << "</#{tag_name.pluralize}>"
    xml
  end
end

# example usage
XmlGenerator.new("user", User.where("age < 21")).generate_xml

主要改进是:

>批量从数据库中获取数据,需要传递ActiveRecord集合而不是ActiveRecord模型数组
>通过构造字符串生成xml,这可能会产生无效的xml,但它比使用构建器快得多

我测试了超过6万条记录.生成这样的xml文档大约需要40秒.

可以做更多的事情来进一步改善这一点,但这一切都取决于您的应用.

以下是一些想法:

>不要使用ActiveRecord来获取数据,而是使用更轻的库或普通的数据库驱动程序
>仅获取所需的数据
>调整批量大小
>将生成的xml直接写入文件(如果这是您的用例)以节省内存

转载注明原文:ruby-on-rails – 从一堆模型对象生成XML时速度较慢 - 代码日志