rails/actionview/test
Hartley McGuire 597b56cde0
Optimize TagBuilder tag generation
Currently there's about a 35% difference between tags generated using
the `TagBuilder` and tags generated by passing a positional argument to
`#tag`.

This commit optimizes `TagBuilder` to reduce that difference down to 13%.

The first change is to perform less hash allocations by not splatting
the options twice in the `TagBuilder` (one at the `tag.a` invocation,
and one at `tag_string`). The extra splat for `tag_string` was moved
into `method_missing` since that is the only other caller of this
private method.

The other change is to only escape the content in `tag_string` if it a
non-empty.

Additionally, a test was tweaked to ensure that passing `options` to a
`self_closing_element` is tested as it was previously not.

Benchmark:

```
require "action_view"
require "benchmark/ips"

class Foo
  include ActionView::Helpers
end

helpers = Foo.new

Benchmark.ips do |x|
  x.report("tag") { helpers.tag("a", href: "foo") }
  x.report("tag_builder") { helpers.tag.a(href: "foo") }
  x.compare!
end
```

Before:

```
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [arm64-darwin22]
Warming up --------------------------------------
                 tag    67.180k i/100ms
         tag_builder    50.267k i/100ms
Calculating -------------------------------------
                 tag    673.064k (± 0.4%) i/s -      3.426M in   5.090520s
         tag_builder    504.971k (± 0.4%) i/s -      2.564M in   5.076842s

Comparison:
                 tag:   673063.7 i/s
         tag_builder:   504971.4 i/s - 1.33x  slower
```

After:

```
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [arm64-darwin22]
Warming up --------------------------------------
                 tag    67.374k i/100ms
         tag_builder    59.702k i/100ms
Calculating -------------------------------------
                 tag    670.837k (± 0.4%) i/s -      3.369M in   5.021714s
         tag_builder    592.727k (± 1.3%) i/s -      2.985M in   5.037088s

Comparison:
                 tag:   670836.6 i/s
         tag_builder:   592726.7 i/s - 1.13x  slower
```

Co-authored-by: Sean Doyle <seanpdoyle@users.noreply.github.com>
2024-01-16 17:51:21 -05:00
..
actionpack Prevent assigning internal ivars to AV::Base 2023-11-03 20:52:47 -04:00
activerecord Expose assert_queries_match and assert_no_queries_match assertions 2023-12-21 01:30:16 +02:00
fixtures Introduce ActionView::TestCase.register_parser 2023-09-27 02:03:23 +00:00
lib Fix form_for id generation for new CPK models 2023-08-28 15:56:25 -05:00
template Optimize TagBuilder tag generation 2024-01-16 17:51:21 -05:00
abstract_unit.rb Get rid of the jruby_skip test helper 2023-10-02 13:01:44 +02:00
active_record_unit.rb Introducs TestFixtures#fixture_paths. 2023-03-14 19:02:56 -04:00
buffers_test.rb Add OutputBuffer#raw and #capture to reduce the need to swap the buffer 2022-08-03 12:56:34 +02:00