Skip to content

Commit

Permalink
Optimize string concatenation using << operator (#617)
Browse files Browse the repository at this point in the history
This change enhances the efficiency of HTML string construction, by
replacing `+=` operator with `<<`.

The shovel operator (`<<`) modifies strings in-place, reducing memory
allocation and improving overall performance compared to the `+=`
operator.

### Test Case

Ruby 3.3.5 x64 on M1 Pro

```rb
Arbre::Context.new { div { |d| d.ul { li } } }.to_s
```

#### Before

```
--- Memory Profiler ---

Total allocated: 4624 bytes (80 objects)
Total retained:  0 bytes (0 objects)

allocated memory by gem
-----------------------------------
      4624  arbre/lib

allocated memory by file
-----------------------------------
      2560  arbre/html/tag.rb
      1120  arbre/element/builder_methods.rb
       400  arbre/element_collection.rb
       280  arbre/element.rb
       264  arbre/context.rb

--- Benchmark: IPS ---

                test     50.546k (± 1.4%) i/s -    254.550k in   5.037005s

--- Benchmark: Memory ---

                test     6.208k memsize (     0.000  retained)
                        99.000  objects (     0.000  retained)
                        29.000  strings (     0.000  retained)
```

#### After

```
--- Memory Profiler ---

Total allocated: 3840 bytes (64 objects)
Total retained:  0 bytes (0 objects)

allocated memory by gem
-----------------------------------
      3840  arbre/lib

allocated memory by file
-----------------------------------
      1776  arbre/html/tag.rb
      1120  arbre/element/builder_methods.rb
       400  arbre/element_collection.rb
       280  arbre/element.rb
       264  arbre/context.rb

--- Benchmark: IPS ---

                test     52.205k (± 1.6%) i/s -    265.659k in   5.090028s

--- Benchmark: Memory ---

                test     5.424k memsize (     0.000  retained)
                        83.000  objects (     0.000  retained)
                        19.000  strings (     0.000  retained)
```
  • Loading branch information
tagliala authored Sep 8, 2024
1 parent 64aaf01 commit 2d5a438
Showing 1 changed file with 7 additions and 9 deletions.
16 changes: 7 additions & 9 deletions lib/arbre/html/tag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,25 +116,23 @@ def closing_tag
def indent(open_tag, child_content, close_tag)
spaces = ' ' * indent_level * INDENT_SIZE

html = ""
html = +""

if no_child? || child_is_text?
if self_closing_tag?
html += spaces + open_tag.sub( />$/, '/>' )
html << spaces << open_tag.sub( />$/, '/>' )
else
# one line
html += spaces + open_tag + child_content + close_tag
html << spaces << open_tag << child_content << close_tag
end
else
# multiple lines
html += spaces + open_tag + "\n"
html += child_content # the child takes care of its own spaces
html += spaces + close_tag
html << spaces << open_tag << "\n"
html << child_content # the child takes care of its own spaces
html << spaces << close_tag
end

html += "\n"

html
html << "\n"
end

def self_closing_tag?
Expand Down

0 comments on commit 2d5a438

Please sign in to comment.