From 198f2a0b6149a2e7c069ad3aaad6ced9f5bb3ea1 Mon Sep 17 00:00:00 2001
From: Stan Hu <stanhu@gmail.com>
Date: Thu, 15 Nov 2018 22:49:48 -0800
Subject: [PATCH] Use Nokogiri as the ActiveSupport XML backend

This significantly improves performance and reduces memory consumption
when parsing XML files. On a test with 124 JUnit files from a CE build,
there was about a 4x reduction in processing time.

Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/54068
---
 changelogs/unreleased/sh-use-nokogiri-xml-backend.yml | 5 +++++
 config/application.rb                                 | 3 +++
 lib/gitlab/ci/parsers/test/junit.rb                   | 2 +-
 spec/fast_spec_helper.rb                              | 1 +
 4 files changed, 10 insertions(+), 1 deletion(-)
 create mode 100644 changelogs/unreleased/sh-use-nokogiri-xml-backend.yml

diff --git a/changelogs/unreleased/sh-use-nokogiri-xml-backend.yml b/changelogs/unreleased/sh-use-nokogiri-xml-backend.yml
new file mode 100644
index 0000000000000..6a82e32c41637
--- /dev/null
+++ b/changelogs/unreleased/sh-use-nokogiri-xml-backend.yml
@@ -0,0 +1,5 @@
+---
+title: Use Nokogiri as the ActiveSupport XML backend
+merge_request: 23136
+author:
+type: performance
diff --git a/config/application.rb b/config/application.rb
index 1b084e91cfbd6..921baa5d617a4 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -158,6 +158,9 @@ class Application < Rails::Application
 
     config.action_view.sanitized_allowed_protocols = %w(smb)
 
+    # Nokogiri is significantly faster and uses less memory than REXML
+    ActiveSupport::XmlMini.backend = 'Nokogiri'
+
     # This middleware needs to precede ActiveRecord::QueryCache and other middlewares that
     # connect to the database.
     config.middleware.insert_after Rails::Rack::Logger, ::Gitlab::Middleware::BasicHealthCheck
diff --git a/lib/gitlab/ci/parsers/test/junit.rb b/lib/gitlab/ci/parsers/test/junit.rb
index ed5a79d9b9b06..2791730fd26cb 100644
--- a/lib/gitlab/ci/parsers/test/junit.rb
+++ b/lib/gitlab/ci/parsers/test/junit.rb
@@ -14,7 +14,7 @@ def parse!(xml_data, test_suite)
               test_case = create_test_case(test_case)
               test_suite.add_test_case(test_case)
             end
-          rescue REXML::ParseException
+          rescue Nokogiri::XML::SyntaxError
             raise JunitParserError, "XML parsing failed"
           rescue
             raise JunitParserError, "JUnit parsing failed"
diff --git a/spec/fast_spec_helper.rb b/spec/fast_spec_helper.rb
index fe475e1f7a0ab..0b5ab16ad71c3 100644
--- a/spec/fast_spec_helper.rb
+++ b/spec/fast_spec_helper.rb
@@ -9,3 +9,4 @@
 
 ActiveSupport::Dependencies.autoload_paths << 'lib'
 ActiveSupport::Dependencies.autoload_paths << 'ee/lib'
+ActiveSupport::XmlMini.backend = 'Nokogiri'
-- 
GitLab