You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Avoid unnecessary replacements when the node doesn't change
This represents a +2x performance optimization when the replacement
logic is based on some condition, and it returns the same unchanged
node when it wants to skip it:
```ruby
html = <<~HTML
<div>
#{'<p>ignore me</p>' * 1000}
#{'<p>replace me</p>' * 1000}
</div>
HTML
content = content_from_html(html)
replacement_example = -> do
content.fragment.replace("p") do |node|
if node.text =~ /replace me/
"<p>replace me</p>"
else
node
end
end
end
current_implementation = -> do
class ActionText::Fragment
def replace(selector)
update do |source|
source.css(selector).each do |node|
replacement_node = yield(node)
node.replace(replacement_node.to_s)
end
end
end
end
replacement_example.call
end
new_implementation = -> do
class ActionText::Fragment
def replace(selector)
update do |source|
source.css(selector).each do |node|
replacement_node = yield(node)
node.replace(replacement_node.to_s) if node != replacement_node
end
end
end
end
replacement_example.call
end
Benchmark.ips do |x|
x.report "Current implementation", ¤t_implementation
x.report "New implementation", &new_implementation
x.compare!
end
```
Results:
```
Warming up --------------------------------------
Current implementation
2.000 i/100ms
New implementation 5.000 i/100ms
Calculating -------------------------------------
Current implementation
32.484 (±30.8%) i/s - 134.000 in 5.036419s
New implementation 74.878 (±38.7%) i/s - 250.000 in 5.052168s
Comparison:
New implementation: 74.9 i/s
Current implementation: 32.5 i/s - 2.31x (± 0.00) slower
```
0 commit comments