Skip to content

Commit 36d2374

Browse files
committed
docs(ruby): Update benchmarks
Signed-off-by: Dmitry Dygalo <[email protected]>
1 parent 9b58750 commit 36d2374

File tree

4 files changed

+72
-11
lines changed

4 files changed

+72
-11
lines changed

bindings/ruby/Gemfile.lock

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ GEM
3030
rake-compiler-dock (1.9.1)
3131
rb_sys (0.9.116)
3232
rake-compiler-dock (= 1.9.1)
33+
roadie (5.2.1)
34+
css_parser (~> 1.4)
35+
nokogiri (~> 1.15)
3336
rspec (3.12.0)
3437
rspec-core (~> 3.12.0)
3538
rspec-expectations (~> 3.12.0)
@@ -54,6 +57,7 @@ DEPENDENCIES
5457
premailer (~> 1.21)
5558
rake-compiler (~> 1.3.0)
5659
rb_sys
60+
roadie (~> 5.2.1)
5761
rspec
5862

5963
BUNDLED WITH

bindings/ruby/README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -205,17 +205,17 @@ Caching is disabled by default.
205205

206206
## Performance
207207

208-
Leveraging efficient tools from Mozilla's Servo project, this library delivers superior performance.
209-
It consistently outperforms `premailer`, offering speed increases often exceeding **50 times**.
208+
This library uses components from Mozilla's Servo project for CSS parsing and matching.
209+
Performance benchmarks show 50-100x faster execution than `roadie` and `premailer`.
210210

211-
The table below provides a detailed comparison between `css_inline` and `premailer` when inlining CSS into an HTML document (like in the Usage section above):
211+
The table below shows benchmark results comparing `css_inline`, `roadie`, and `premailer` on typical HTML documents:
212212

213-
| | Size | `css_inline 0.15.0` | `premailer 1.21.0 with Nokogiri 1.15.2` | Difference |
214-
|-------------------|---------|---------------------|------------------------------------------------|------------|
215-
| Basic usage | 230 B | 6.11 µs | 350.10 µs | **57.24x** |
216-
| Realistic email 1 | 8.58 KB | 101.82 µs | 7.99 ms | **78.49x** |
217-
| Realistic email 2 | 4.3 KB | 77.22 µs | Error: Cannot parse 0 calc((100% - 500px) / 2) | - |
218-
| GitHub Page | 1.81 MB | 172.41 ms | 2.77 s | **15.97x** |
213+
| | Size | `css_inline 0.15.0` | `roadie 5.2.1` | `premailer 1.21.0` |
214+
|-------------------|---------|---------------------|----------------|---------------------------|
215+
| Basic usage | 230 B | 6.11 µs | 175.21 µs (**28.75**) | 350.10 µs (**57.24x**) |
216+
| Realistic email 1 | 8.58 KB | 101.82 µs | 721.18 µs (**6.96x**) | 7.99 ms (**78.49x**) |
217+
| Realistic email 2 | 4.3 KB | 77.22 µs | 2.02 ms (**28.48x**) | ERROR |
218+
| GitHub Page | 1.81 MB | 172.41 ms | 8.84 s (**52.21x**) | 2.77 s (**15.97x**) |
219219

220220
Please refer to the `test/bench.rb` file to review the benchmark code.
221221
The results displayed above were measured using stable `rustc 1.87` on Ruby `3.3.5`.

bindings/ruby/css_inline.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,6 @@ Gem::Specification.new do |spec|
4040
spec.add_development_dependency "rake-compiler", "~> 1.3.0"
4141
spec.add_development_dependency "benchmark-ips", "~> 2.10"
4242
spec.add_development_dependency "premailer", "~> 1.21"
43+
spec.add_development_dependency "roadie", "~> 5.2.1"
4344
spec.add_development_dependency "nokogiri", "~> 1.15"
4445
end

bindings/ruby/test/bench.rb

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
require 'json'
22
require "benchmark/ips"
33
require "premailer"
4+
require "roadie"
45
require_relative "../lib/css_inline"
56

67
file = File.read('../../benchmarks/benchmarks.json')
@@ -13,10 +14,65 @@ def premailer_inline(html)
1314
premailer.to_inline_css
1415
end
1516

17+
def roadie_inline(html)
18+
document = Roadie::Document.new(html)
19+
document.transform
20+
end
21+
22+
def test_library(name, html, &block)
23+
begin
24+
result = block.call(html)
25+
[true, nil]
26+
rescue => e
27+
puts "Warning: #{name} failed with: #{e.class} - #{e.message}"
28+
[false, e]
29+
end
30+
end
31+
32+
def format_time(seconds)
33+
case seconds
34+
when 0...0.000001
35+
"%.3f ns" % (seconds * 1_000_000_000)
36+
when 0.000001...0.001
37+
"%.3f μs" % (seconds * 1_000_000)
38+
when 0.001...1
39+
"%.3f ms" % (seconds * 1_000)
40+
else
41+
"%.3f s" % seconds
42+
end
43+
end
44+
1645
benchmarks.each do |benchmark|
46+
puts "\n=== Benchmark: #{benchmark['name']} ==="
47+
48+
# Test which libraries work for this benchmark
49+
libraries = {
50+
"css_inline" => -> (html) { CSSInline::inline(html) },
51+
"premailer" => -> (html) { premailer_inline(html) },
52+
"roadie" => -> (html) { roadie_inline(html) }
53+
}
54+
55+
working_libraries = {}
56+
libraries.each do |name, func|
57+
success, error = test_library(name, benchmark['html'], &func)
58+
if success
59+
working_libraries[name] = func
60+
else
61+
puts " Skipping #{name} for this benchmark due to error"
62+
end
63+
end
64+
65+
if working_libraries.empty?
66+
puts " No libraries could process this benchmark!"
67+
next
68+
end
69+
1770
Benchmark.ips do |x|
18-
x.report("css_inline_#{benchmark['name']}") { CSSInline::inline(benchmark['html']) }
19-
x.report("premailer_#{benchmark['name']}") { premailer_inline(benchmark['html']) }
71+
working_libraries.each do |name, func|
72+
x.report("#{name}_#{benchmark['name']}") do
73+
func.call(benchmark['html'])
74+
end
75+
end
2076
x.compare!
2177
end
2278
end

0 commit comments

Comments
 (0)