Skip to content

Commit e41b6b0

Browse files
committed
Optimization of REXML::Parsers::SAX2Parser#get_namespace
## Benchmark ``` before after before(YJIT) after(YJIT) sax 1.377k 2.247k 1.668k 2.829k i/s - 100.000 times in 0.072609s 0.044501s 0.059965s 0.035352s Comparison: sax after(YJIT): 2828.7 i/s after: 2247.1 i/s - 1.26x slower before(YJIT): 1667.6 i/s - 1.70x slower before: 1377.2 i/s - 2.05x slower ``` - YJIT=ON : 1.70x faster - YJIT=OFF : 1.63x faster
1 parent 5474ab2 commit e41b6b0

2 files changed

Lines changed: 38 additions & 6 deletions

File tree

benchmark/sax.yaml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
loop_count: 100
2+
contexts:
3+
- gems:
4+
rexml: 3.2.6
5+
require: false
6+
prelude: require 'rexml'
7+
- name: master
8+
prelude: |
9+
$LOAD_PATH.unshift(File.expand_path("lib"))
10+
require 'rexml'
11+
- name: 3.2.6(YJIT)
12+
gems:
13+
rexml: 3.2.6
14+
require: false
15+
prelude: |
16+
require 'rexml'
17+
RubyVM::YJIT.enable
18+
- name: master(YJIT)
19+
prelude: |
20+
$LOAD_PATH.unshift(File.expand_path("lib"))
21+
require 'rexml'
22+
RubyVM::YJIT.enable
23+
24+
prelude: |
25+
require 'rexml/parsers/sax2parser'
26+
27+
DEPTH = 100
28+
xml = '<a>' * DEPTH + '</a>' * DEPTH
29+
30+
benchmark:
31+
'sax' : |
32+
parser = REXML::Parsers::SAX2Parser.new(xml)
33+
parser.listen(:start_element){|uri, localname, qname, attrs|}
34+
parser.parse

lib/rexml/parsers/sax2parser.rb

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def initialize source
1212
@parser = BaseParser.new(source)
1313
@listeners = []
1414
@procs = []
15-
@namespace_stack = []
15+
@namespace_stack = [{}]
1616
@has_listeners = false
1717
@tag_stack = []
1818
@entities = {}
@@ -122,7 +122,7 @@ def parse
122122
event[2].each {|n, v| event[2][n] = @parser.normalize(v)}
123123
nsdecl = event[2].find_all { |n, value| n =~ /^xmlns(:|$)/ }
124124
nsdecl.collect! { |n, value| [ n[6..-1], value ] }
125-
@namespace_stack.push({})
125+
@namespace_stack.push(@namespace_stack[-1].dup)
126126
nsdecl.each do |n,v|
127127
@namespace_stack[-1][n] = v
128128
# notify observers of namespaces
@@ -260,10 +260,8 @@ def add( pair )
260260

261261
def get_namespace( prefix )
262262
return nil if @namespace_stack.empty?
263-
264-
uris = (@namespace_stack.find_all { |ns| not ns[prefix].nil? }) ||
265-
(@namespace_stack.find { |ns| not ns[nil].nil? })
266-
uris[-1][prefix] unless uris.nil? or 0 == uris.size
263+
current_namespace = @namespace_stack[-1]
264+
current_namespace[prefix] || current_namespace[nil]
267265
end
268266
end
269267
end

0 commit comments

Comments
 (0)