#ruby-on-rails #ruby #xml #nokogiri
#ruby-on-rails #ruby #xml #nokogiri
Вопрос:
Некоторое время мы использовали Rails ‘(2.3.3) Builder для генерации XML-разметки для наших API, когда мы думали, что Nokogiri Builder будет генерировать XML быстрее (как многие указывали).
Проблема в том, что мои тесты показали, что Nokogiri::Builder медленнее, чем обычный Builder:
Nokogiri::Builder: 3.1314s
Builder: 2.1592s
для рендеринга одного и того же запроса 10 раз. Я несколько раз повторял подобные тесты в разных средах, поэтому я уверен, что Nokogiri работает медленнее.
Наше приложение имеет множество представлений .xml.builder, которые используют многие части .xml.builder:
xml.instruct!
xml.feed do
xml.stuff do
xml.more_stuff(...)
end
xml.location do
xml << render(:partial => shared/location, :object => mylocation)
end
end
В приведенном выше примере используется shared/_location.xml.builder . Наше приложение в значительной степени использует такие части XML для организации кода.
Я перешел на Nokogiri после «Ускорения ваших ответов Rails XML» (см. Приложение для тестирования там).
Мой обработчик шаблонов выглядит так:
class NokogiriBuilder < ActionView::TemplateHandler
include ActionView::TemplateHandlers::Compilable
def compile template
"_set_controller_content_type(Mime::XML);"
"xml = ::Nokogiri::XML::Builder.new(:encoding => 'UTF-8') { |xml| "
template.source
'}.to_xml; self.output_buffer = xml;'
end
end
Когда я попытался запустить свой код через rubyprof, результаты показывают, что create_element занимает много времени!
%self total self wait child calls name
23.47 1.15 1.15 0.00 0.00 731 Mysql#query
9.59 0.78 0.47 0.00 0.31 1437 Nokogiri::XML::Document#create_element
7.96 3.61 0.39 0.00 3.61 867 <Module::Benchmark>#realtime
5.51 0.27 0.27 0.00 0.00 1167 Nokogiri::XML::Node#encode_special_chars
5.51 0.28 0.27 0.00 0.01 1370 Module#define_method
5.10 0.26 0.25 0.00 0.01 346 Array#select
3.88 0.19 0.19 0.00 0.00 5236 Module#constants
3.27 0.90 0.16 0.00 0.83 1820 Array#collect
2.45 0.13 0.12 0.00 0.01 1712 Rack::Lint::Assertion#assert
2.24 1.09 0.11 0.00 1.09 554 ActiveSupport::CoreExtensions::String::Inflections#constantize
2.04 0.10 0.10 0.00 0.00 23 Nokogiri::XML::ParseOptions#initialize
2.04 0.10 0.10 0.00 0.00 726 <Class::ActiveSupport::Callbacks::CallbackChain>#extract_options
Мне действительно интересно, что такого особенного в моем случае, что Nokogiri будет работать медленнее, хотя для многих людей это оказалось во много раз быстрее!
Никаких нежных занятий любовью? 🙁
Комментарии:
1. 1 для подробной информации и профилирования, но -1 для… в чем вопрос? Почему одна библиотека немного медленнее другой для вашего конкретного варианта использования, когда какая-то запись в блоге заставила вас думать, что она всегда будет быстрее в любом случае?
2. Это в некотором роде верно, поскольку этот , этот и другие упоминали о больших улучшениях. Поскольку я сейчас оптимизирую свое приложение, это казалось легким выигрышем. Вопрос в том, что конкретно может быть в моем приложении, чтобы замедлить работу более быстрой библиотеки? То, что я делаю, может быть чем-то очень неправильным.
3. Важно проверять даты блогов, когда вы рассчитываете на их информацию. Первый был написан за два года до публикации этого вопроса, и за это время Rails претерпели бы множество обновлений, так что легко понять, почему результаты могли быть другими. Интернет никогда не забывает, но информация действительно устаревает.
4. Согласен с приведенными выше комментариями. Существует, возможно, дюжина факторов, которые могут повлиять на производительность, не связанных с синтаксическим анализом XML. Например, если вы используете версию Rails от 2009 года, используете ли вы также и старую версию ruby? Какая ОС? Вы читаете большие файлы с медленного диска? Nokogiri, вероятно, быстрее разбирается, когда XML находится в памяти, но получение его там и готовность (даже внутри Nokogiri) могут сильно различаться. Кроме того, размер и сложность анализируемого объекта имеют значение — например, мы читаем более 100 мегабайтных XML-файлов, и Nokogiri в этом случае работает быстрее.