Files
Jean Boussier 6acfd9c2b9 string.c: Speedup String#tr fastpath with SIMD
The fast path is now 4.4x faster, now making it ~2.6x times
faster than `CGI.escape_html`, and 26x faster than an equivalent
`gsub`.

```
compare-ruby: ruby 4.1.0dev (2026-09-06T11:22:48Z master 13fc4ffd32) +YJIT +PRISM [arm64-darwin25]
built-ruby: ruby 4.1.0dev (2026-09-06T14:39:43Z string-tr-simd e2526ca9ba) +YJIT +PRISM [arm64-darwin25]
``

|             |compare-ruby|built-ruby|
|:------------|-----------:|---------:|
|tr_escape    |     41.595k|  182.732k|
|             |           -|     4.39x|
|gsub_escape  |      7.135k|    6.977k|
|             |       1.02x|         -|
|cgi_escape   |     70.117k|   70.179k|
|             |           -|     1.00x|

However, contrary to a lookup table, here the performance is linear with
the number of characters to match, hence once we're looking for 16 distinct
bytes, the gain compared to the lookup table is down to ~2x.
2026-09-06 20:47:32 +02:00

24 lines
450 B
YAML

prelude: |
# frozen_string_literal: true
require 'cgi/escape'
STR = ((("a" * 31) + "<") * 1000).freeze
ESCAPED_CHARS = {
"\\" => "&#39",
"\"" => "&quot;",
">" => '&gt;',
"<" => '&lt;',
"&" => '&amp;',
}.freeze
ESCAPE_PATTERN = Regexp.union(ESCAPED_CHARS.keys)
benchmark:
tr_escape: |
STR.tr(ESCAPED_CHARS)
gsub_escape: |
STR.gsub(ESCAPE_PATTERN, ESCAPED_CHARS)
cgi_escape: |
CGI.escape_html(STR)