Skip to content

Commit fd7735d

Browse files
authored
Optimization of REXML::Parsers::SAX2Parser#get_namespace (#300)
## Benchmark ``` before after before(YJIT) after(YJIT) sax 1.415k 2.297k 1.755k 2.958k i/s - 100.000 times in 0.070687s 0.043539s 0.056966s 0.033810s Comparison: sax after(YJIT): 2957.7 i/s after: 2296.8 i/s - 1.29x slower before(YJIT): 1755.4 i/s - 1.68x slower before: 1414.7 i/s - 2.09x slower ``` - YJIT=ON : 1.68x faster - YJIT=OFF : 1.62x faster
1 parent 5474ab2 commit fd7735d

File tree

2 files changed

+38
-7
lines changed

2 files changed

+38
-7
lines changed

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 & 7 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
@@ -259,11 +259,8 @@ def add( pair )
259259
end
260260

261261
def get_namespace( prefix )
262-
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
262+
current_namespace = @namespace_stack[-1]
263+
current_namespace[prefix] || current_namespace[nil]
267264
end
268265
end
269266
end

0 commit comments

Comments
 (0)