Skip to content

Load pp only when XPath debug tracing is enabled - #365

Open
tas50 wants to merge 1 commit into
ruby:masterfrom
tas50:perf/defer-pp-require
Open

Load pp only when XPath debug tracing is enabled#365
tas50 wants to merge 1 commit into
ruby:masterfrom
tas50:perf/defer-pp-require

Conversation

@tas50

@tas50 tas50 commented Aug 28, 2026

Copy link
Copy Markdown

Problem

lib/rexml/xpath_parser.rb requires pp at the top of the file. PP is used in exactly one place:

def trace(*args)
  indent = "  " * @nest
  PP.pp(args, "").each_line do |line|
    puts("#{indent}#{line}")
  end
end

trace is reached only through enter and leave, and every call site is guarded by if @debug (lines 225, 228, 246, 292, 373, 651, 690, 695, 769, 773, 781, 800). @debug comes from DEBUG, which is:

DEBUG = (ENV["REXML_XPATH_PARSER_DEBUG"] == "true")

So every REXML user loads pp and prettyprint for a debugging aid that is off by default.

Fix

Move the require into #trace, the only method that touches PP.

Measurements

Ruby 4.0.6 (arm64-darwin), best of seven runs:

require "rexml/document" files loaded
before 23.85 ms 38
after 21.72 ms 36
−2.13 ms (9%) −2

Small in absolute terms, but REXML sits underneath a good deal of the ecosystem, and the change carries no behavior risk.

Debug tracing is unaffected — running with REXML_XPATH_PARSER_DEBUG=true produces the same trace output:

[:enter,
 :expr,
 [:document, :descendant_or_self, :node, :child, :qname, "", "b"],
 [<UNDEFINED> ... </>]]
  [:while,

Tests

test/run.rb: 811 tests, 0 failures, unchanged (814 with the additions).

The three added tests cover that requiring rexml/document does not load pp, that XPath matching works without it, and that evaluating an XPath does not pull it in. Two of them fail against the previous code.

xpath_parser.rb requires pp at the top of the file, but PP is used in
exactly one place: XPathParser#trace, reached only through enter and
leave, and every one of those call sites is guarded by `if @debug`.
@debug comes from DEBUG, which is false unless the environment variable
REXML_XPATH_PARSER_DEBUG is set to "true".

So every REXML user loads pp and prettyprint for a debugging aid that
is off by default.

Measured on Ruby 4.0.6 (arm64-darwin), best of seven runs:

              require "rexml/document"   files loaded
  before      23.85 ms                   38
  after       21.72 ms                   36
               -2.13 ms                   -2   (9% faster)

Small in absolute terms, but REXML sits underneath a lot of the
ecosystem and the change carries no behavior risk.

Debug tracing still works: running with REXML_XPATH_PARSER_DEBUG=true
produces the same trace output as before.

Test suite: 811 tests, 0 failures, unchanged. The three added tests
cover that requiring rexml/document does not load pp, that XPath
matching works without it, and that evaluating an XPath does not pull
it in. Two of them fail against the previous code.

Signed-off-by: Tim Smith <tsmith84@proton.me>
@kou

kou commented Aug 29, 2026

Copy link
Copy Markdown
Member

Could you share what is your real world problem?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants