I've been working on improving the performance and functionality of to_xml.
While putting together this patch, I discovered that the recent upgrade of Builder::XMLMarkup to 2.0 slows down to_xml by 80%, since it now encodes attributes and seems to do a better job, that's more expensive, of encoding all values. http://dev.rubyonrails.org/changeset/4260 Could somebody take a look at this patch and give some feedback. http://dev.rubyonrails.org/ticket/4989 The major benefits of this patch are (more improvements are listed in the ticket). 1) Allow ActiveRecord::Base subclasses to override to_xml. Currently, all AR instances are turned into a Hash and then have to_xml run on the hash, which prevents subclassing of AR instances through an :include. 2) Speeds up to_xml generation by 22-30% depending upon the model. This is done by using the fact that we know the SQL column type and this allows us to skip the XML encoding if the type doesn't need encoding, such as booleans, floats, integers. I've attached a small script you can use to time the to_xml before and after the patch. 3) Allows the :include option to be arbitrary deep, previously, only one level of :include worked. 4) Binary columns are Base64 encoded and have an encoding="base64" attribute added to it. It turns out that it is 80 times faster to do builder << Base64.encode(value) then builder.tag!(tag, value). Outstanding issues are 1) The XML output is not at nice looking with the optimization of using builder.tag!(tag) do builder << value.to_s end instead of builder.tag!(tag, value), but that seems like a small price to pay. <?xml version="1.0" encoding="UTF-8"?> <node> <node-id type="integer"> 1234 </node-id> </node> Regards, Blair -- Blair Zajac, Ph.D. <[EMAIL PROTECTED]> Subversion training, consulting and support http://www.orcaware.com/svn/ #!/usr/local/bin/ruby # This assumes that the script is run from the top of the Ruby on # Rails project. print "Loading Ruby on Rails..." $stdout.flush require 'config/environment' print "\n" require 'benchmark' include Benchmark N = 1000 subclasses = ActiveRecord::Base.send(:subclasses) subclasses = subclasses.reject { |s| 'CGI::Session::ActiveRecordStore::Session' == s.to_s } subclasses = subclasses.sort_by { |s| s.to_s } max_length = subclasses.collect { |s| s.to_s.length }.max bm(max_length + 4) do |x| subclasses.each do |subclass| obj = subclass.find(:first, :order => subclass.primary_key) s = sprintf('%s %2d %s', subclass, subclass.column_names.length, ' '*(max_length - subclass.to_s.length)) x.report(s) { N.times { obj.to_xml } } end end _______________________________________________ Rails-core mailing list Rails-core@lists.rubyonrails.org http://lists.rubyonrails.org/mailman/listinfo/rails-core