cataract 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci-manual-rubies.yml +27 -0
- data/.overcommit.yml +1 -1
- data/.rubocop.yml +62 -0
- data/.rubocop_todo.yml +186 -0
- data/BENCHMARKS.md +60 -139
- data/CHANGELOG.md +10 -0
- data/README.md +30 -2
- data/Rakefile +49 -22
- data/cataract.gemspec +4 -1
- data/ext/cataract/cataract.c +47 -47
- data/ext/cataract/css_parser.c +17 -33
- data/ext/cataract/merge.c +6 -0
- data/lib/cataract/at_rule.rb +8 -9
- data/lib/cataract/declaration.rb +18 -0
- data/lib/cataract/import_resolver.rb +3 -4
- data/lib/cataract/pure/byte_constants.rb +69 -0
- data/lib/cataract/pure/helpers.rb +35 -0
- data/lib/cataract/pure/imports.rb +255 -0
- data/lib/cataract/pure/merge.rb +1146 -0
- data/lib/cataract/pure/parser.rb +1236 -0
- data/lib/cataract/pure/serializer.rb +590 -0
- data/lib/cataract/pure/specificity.rb +206 -0
- data/lib/cataract/pure.rb +130 -0
- data/lib/cataract/rule.rb +22 -13
- data/lib/cataract/stylesheet.rb +14 -9
- data/lib/cataract/version.rb +1 -1
- data/lib/cataract.rb +18 -5
- metadata +12 -25
- data/benchmarks/benchmark_harness.rb +0 -193
- data/benchmarks/benchmark_merging.rb +0 -121
- data/benchmarks/benchmark_optimization_comparison.rb +0 -168
- data/benchmarks/benchmark_parsing.rb +0 -153
- data/benchmarks/benchmark_ragel_removal.rb +0 -56
- data/benchmarks/benchmark_runner.rb +0 -70
- data/benchmarks/benchmark_serialization.rb +0 -180
- data/benchmarks/benchmark_shorthand.rb +0 -109
- data/benchmarks/benchmark_shorthand_expansion.rb +0 -176
- data/benchmarks/benchmark_specificity.rb +0 -124
- data/benchmarks/benchmark_string_allocation.rb +0 -151
- data/benchmarks/benchmark_stylesheet_to_s.rb +0 -62
- data/benchmarks/benchmark_to_s_cached.rb +0 -55
- data/benchmarks/benchmark_value_splitter.rb +0 -54
- data/benchmarks/benchmark_yjit.rb +0 -158
- data/benchmarks/benchmark_yjit_workers.rb +0 -61
- data/benchmarks/profile_to_s.rb +0 -23
- data/benchmarks/speedup_calculator.rb +0 -83
- data/benchmarks/system_metadata.rb +0 -81
- data/benchmarks/templates/benchmarks.md.erb +0 -221
- data/benchmarks/yjit_tests.rb +0 -141
- data/scripts/fuzzer/run.rb +0 -828
- data/scripts/fuzzer/worker.rb +0 -99
- data/scripts/generate_benchmarks_md.rb +0 -155
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'json'
|
|
4
|
-
require 'fileutils'
|
|
5
|
-
|
|
6
|
-
# Collects system metadata for benchmark runs
|
|
7
|
-
class SystemMetadata
|
|
8
|
-
RESULTS_DIR = File.expand_path('.results', __dir__)
|
|
9
|
-
|
|
10
|
-
def self.collect
|
|
11
|
-
metadata = {
|
|
12
|
-
'ruby_version' => RUBY_VERSION,
|
|
13
|
-
'ruby_description' => RUBY_DESCRIPTION,
|
|
14
|
-
'platform' => RUBY_PLATFORM,
|
|
15
|
-
'cpu' => detect_cpu,
|
|
16
|
-
'memory' => detect_memory,
|
|
17
|
-
'os' => detect_os,
|
|
18
|
-
'timestamp' => Time.now.iso8601
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
FileUtils.mkdir_p(RESULTS_DIR)
|
|
22
|
-
File.write(File.join(RESULTS_DIR, 'metadata.json'), JSON.pretty_generate(metadata))
|
|
23
|
-
|
|
24
|
-
metadata
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def self.detect_cpu
|
|
28
|
-
if RUBY_PLATFORM.include?('darwin')
|
|
29
|
-
`sysctl -n machdep.cpu.brand_string`.strip
|
|
30
|
-
elsif File.exist?('/proc/cpuinfo')
|
|
31
|
-
cpuinfo = File.read('/proc/cpuinfo')
|
|
32
|
-
if (match = cpuinfo.match(/model name\s*:\s*(.+)/))
|
|
33
|
-
match[1].strip
|
|
34
|
-
else
|
|
35
|
-
'Unknown'
|
|
36
|
-
end
|
|
37
|
-
else
|
|
38
|
-
'Unknown'
|
|
39
|
-
end
|
|
40
|
-
rescue StandardError
|
|
41
|
-
'Unknown'
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def self.detect_memory
|
|
45
|
-
if RUBY_PLATFORM.include?('darwin')
|
|
46
|
-
# Output in GB
|
|
47
|
-
bytes = `sysctl -n hw.memsize`.strip.to_i
|
|
48
|
-
"#{bytes / (1024 * 1024 * 1024)}GB"
|
|
49
|
-
elsif File.exist?('/proc/meminfo')
|
|
50
|
-
meminfo = File.read('/proc/meminfo')
|
|
51
|
-
if (match = meminfo.match(/MemTotal:\s+(\d+)\s+kB/))
|
|
52
|
-
kb = match[1].to_i
|
|
53
|
-
"#{kb / (1024 * 1024)}GB"
|
|
54
|
-
else
|
|
55
|
-
'Unknown'
|
|
56
|
-
end
|
|
57
|
-
else
|
|
58
|
-
'Unknown'
|
|
59
|
-
end
|
|
60
|
-
rescue StandardError
|
|
61
|
-
'Unknown'
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def self.detect_os
|
|
65
|
-
if RUBY_PLATFORM.include?('darwin')
|
|
66
|
-
version = `sw_vers -productVersion`.strip
|
|
67
|
-
"macOS #{version}"
|
|
68
|
-
elsif File.exist?('/etc/os-release')
|
|
69
|
-
os_release = File.read('/etc/os-release')
|
|
70
|
-
if (match = os_release.match(/PRETTY_NAME="(.+)"/))
|
|
71
|
-
match[1]
|
|
72
|
-
else
|
|
73
|
-
RUBY_PLATFORM
|
|
74
|
-
end
|
|
75
|
-
else
|
|
76
|
-
RUBY_PLATFORM
|
|
77
|
-
end
|
|
78
|
-
rescue StandardError
|
|
79
|
-
RUBY_PLATFORM
|
|
80
|
-
end
|
|
81
|
-
end
|
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
<!-- AUTO-GENERATED FILE - DO NOT EDIT -->
|
|
2
|
-
<!-- This file is automatically generated from benchmark results. -->
|
|
3
|
-
<!-- To regenerate: rake benchmark:generate_docs -->
|
|
4
|
-
|
|
5
|
-
# Performance Benchmarks
|
|
6
|
-
|
|
7
|
-
Comprehensive performance comparison between Cataract and css_parser gem.
|
|
8
|
-
|
|
9
|
-
## Test Environment
|
|
10
|
-
|
|
11
|
-
- **Ruby**: <%= metadata['ruby_description'] %>
|
|
12
|
-
- **CPU**: <%= metadata['cpu'] %>
|
|
13
|
-
- **Memory**: <%= metadata['memory'] %>
|
|
14
|
-
- **OS**: <%= metadata['os'] %>
|
|
15
|
-
- **Generated**: <%= metadata['timestamp'] %>
|
|
16
|
-
|
|
17
|
-
<%- if parsing_data -%>
|
|
18
|
-
<details>
|
|
19
|
-
<summary><h2>CSS Parsing</h2></summary>
|
|
20
|
-
|
|
21
|
-
Performance of parsing CSS into internal data structures.
|
|
22
|
-
|
|
23
|
-
<%= parsing_data['description'] %>
|
|
24
|
-
|
|
25
|
-
<%- parsing_data['metadata']['test_cases'].each do |test_case| -%>
|
|
26
|
-
### <%= test_case['name'] %>
|
|
27
|
-
|
|
28
|
-
<%- results = parsing_data['results'].select { |r| r['name'].include?(test_case['fixture']) } -%>
|
|
29
|
-
<%- css_parser_result = results.find { |r| r['name'].include?('css_parser') } -%>
|
|
30
|
-
<%- cataract_result = results.find { |r| r['name'].include?('cataract') } -%>
|
|
31
|
-
<%- if css_parser_result && cataract_result -%>
|
|
32
|
-
<%- speedup = cataract_result['central_tendency'] / css_parser_result['central_tendency'] -%>
|
|
33
|
-
|
|
34
|
-
| Parser | Speed | Time per operation |
|
|
35
|
-
|--------|-------|-------------------|
|
|
36
|
-
| css_parser | <%= format_ips(css_parser_result, short: true) %> | <%= format_time_per_op(css_parser_result) %> |
|
|
37
|
-
| **Cataract** | **<%= format_ips(cataract_result, short: true) %>** | **<%= format_time_per_op(cataract_result) %>** |
|
|
38
|
-
| **Speedup** | **<%= format_speedup(speedup) %>** | |
|
|
39
|
-
|
|
40
|
-
<%- end -%>
|
|
41
|
-
<%- end -%>
|
|
42
|
-
|
|
43
|
-
</details>
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
<%- end -%>
|
|
47
|
-
|
|
48
|
-
<%- if serialization_data -%>
|
|
49
|
-
<details>
|
|
50
|
-
<summary><h2>CSS Serialization (to_s)</h2></summary>
|
|
51
|
-
|
|
52
|
-
Performance of converting parsed CSS back to string format.
|
|
53
|
-
|
|
54
|
-
<%= serialization_data['description'] %>
|
|
55
|
-
|
|
56
|
-
<%- serialization_data['metadata']['test_cases'].each do |test_case| -%>
|
|
57
|
-
### <%= test_case['name'] %>
|
|
58
|
-
|
|
59
|
-
<%- results = serialization_data['results'].select { |r| r['name'].include?(test_case['key']) } -%>
|
|
60
|
-
<%- css_parser_result = results.find { |r| r['name'].include?('css_parser') } -%>
|
|
61
|
-
<%- cataract_result = results.find { |r| r['name'].include?('cataract') } -%>
|
|
62
|
-
<%- if css_parser_result && cataract_result -%>
|
|
63
|
-
<%- speedup = cataract_result['central_tendency'] / css_parser_result['central_tendency'] -%>
|
|
64
|
-
|
|
65
|
-
| Parser | Speed | Time per operation |
|
|
66
|
-
|--------|-------|-------------------|
|
|
67
|
-
| css_parser | <%= format_ips(css_parser_result, short: true) %> | <%= format_time_per_op(css_parser_result) %> |
|
|
68
|
-
| **Cataract** | **<%= format_ips(cataract_result, short: true) %>** | **<%= format_time_per_op(cataract_result) %>** |
|
|
69
|
-
| **Speedup** | **<%= format_speedup(speedup) %>** | |
|
|
70
|
-
|
|
71
|
-
<%- end -%>
|
|
72
|
-
<%- end -%>
|
|
73
|
-
|
|
74
|
-
</details>
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
<%- end -%>
|
|
78
|
-
|
|
79
|
-
<%- if specificity_data -%>
|
|
80
|
-
<details>
|
|
81
|
-
<summary><h2>Specificity Calculation</h2></summary>
|
|
82
|
-
|
|
83
|
-
Performance of calculating CSS selector specificity values.
|
|
84
|
-
|
|
85
|
-
<%= specificity_data['description'] %>
|
|
86
|
-
|
|
87
|
-
| Test Case | Speedup |
|
|
88
|
-
|-----------|---------|
|
|
89
|
-
<%- specificity_data['metadata']['test_cases'].each do |test_case| -%>
|
|
90
|
-
| <%= test_case['name'] %> | **<%= format_speedup(test_case['speedup']) %>** |
|
|
91
|
-
<%- end -%>
|
|
92
|
-
|
|
93
|
-
**Summary:** <%= format_speedup(specificity_data['metadata']['speedups']['min']) %> to <%= format_speedup(specificity_data['metadata']['speedups']['max']) %> (avg <%= format_speedup(specificity_data['metadata']['speedups']['avg']) %>)
|
|
94
|
-
|
|
95
|
-
</details>
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
<%- end -%>
|
|
99
|
-
|
|
100
|
-
<%- if merging_data -%>
|
|
101
|
-
<details>
|
|
102
|
-
<summary><h2>CSS Merging</h2></summary>
|
|
103
|
-
|
|
104
|
-
Performance of merging multiple CSS rule sets with the same selector.
|
|
105
|
-
|
|
106
|
-
<%= merging_data['description'] %>
|
|
107
|
-
|
|
108
|
-
| Test Case | Speedup |
|
|
109
|
-
|-----------|---------|
|
|
110
|
-
<%- merging_data['metadata']['test_cases'].each do |test_case| -%>
|
|
111
|
-
| <%= test_case['name'] %> | **<%= format_speedup(test_case['speedup']) %>** |
|
|
112
|
-
<%- end -%>
|
|
113
|
-
|
|
114
|
-
**Summary:** <%= format_speedup(merging_data['metadata']['speedups']['min']) %> to <%= format_speedup(merging_data['metadata']['speedups']['max']) %> (avg <%= format_speedup(merging_data['metadata']['speedups']['avg']) %>)
|
|
115
|
-
|
|
116
|
-
### What's Being Tested
|
|
117
|
-
- Specificity-based CSS cascade (ID > class > element)
|
|
118
|
-
- `!important` declaration handling
|
|
119
|
-
- Shorthand property expansion (e.g., `margin` → `margin-top`, `margin-right`, etc.)
|
|
120
|
-
- Shorthand property creation from longhand properties
|
|
121
|
-
|
|
122
|
-
</details>
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
<%- end -%>
|
|
126
|
-
|
|
127
|
-
<%- if yjit_data -%>
|
|
128
|
-
<details>
|
|
129
|
-
<summary><h2>YJIT Impact</h2></summary>
|
|
130
|
-
|
|
131
|
-
Impact of Ruby's YJIT JIT compiler on Ruby-side operations. The C extension performance is the same regardless of YJIT.
|
|
132
|
-
|
|
133
|
-
<%= yjit_data['description'] %>
|
|
134
|
-
|
|
135
|
-
### Operations Per Second
|
|
136
|
-
|
|
137
|
-
| Operation | Without YJIT | With YJIT | YJIT Improvement |
|
|
138
|
-
|-----------|--------------|-----------|------------------|
|
|
139
|
-
<%- yjit_data['metadata']['operations'].each do |operation| -%>
|
|
140
|
-
<%- results = yjit_data['results'].select { |r| r['name'].include?(operation) } -%>
|
|
141
|
-
<%- no_yjit = results.find { |r| r['name'].include?('no YJIT') } -%>
|
|
142
|
-
<%- with_yjit = results.find { |r| r['name'].include?('YJIT') && !r['name'].include?('no YJIT') } -%>
|
|
143
|
-
<%- if no_yjit && with_yjit -%>
|
|
144
|
-
<%- improvement = with_yjit['central_tendency'] / no_yjit['central_tendency'] -%>
|
|
145
|
-
<%- pct = ((improvement - 1) * 100).round -%>
|
|
146
|
-
| <%= operation %> | <%= format_ips(no_yjit, short: true) %> | <%= format_ips(with_yjit, short: true) %> | **<%= format_speedup(improvement) %>** (<%= pct %>% faster) |
|
|
147
|
-
<%- end -%>
|
|
148
|
-
<%- end -%>
|
|
149
|
-
|
|
150
|
-
### Key Takeaways
|
|
151
|
-
- YJIT provides significant performance boost for Ruby-side operations
|
|
152
|
-
- Greatest impact on declaration merging
|
|
153
|
-
- Parse + iterate benefits least since most work is in C
|
|
154
|
-
- Recommended: Enable YJIT in production (`--yjit` flag or `RUBY_YJIT_ENABLE=1`)
|
|
155
|
-
|
|
156
|
-
</details>
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
<%- end -%>
|
|
160
|
-
|
|
161
|
-
## Summary
|
|
162
|
-
|
|
163
|
-
### Performance Highlights
|
|
164
|
-
|
|
165
|
-
| Category | Min Speedup | Max Speedup | Avg Speedup |
|
|
166
|
-
|----------|-------------|-------------|-------------|
|
|
167
|
-
<%- if parsing_data && parsing_data['metadata']['speedups'] -%>
|
|
168
|
-
<%- sp = parsing_data['metadata']['speedups'] -%>
|
|
169
|
-
| **Parsing** | <%= format_speedup(sp['min']) %> | <%= format_speedup(sp['max']) %> | <%= format_speedup(sp['avg']) %> |
|
|
170
|
-
<%- end -%>
|
|
171
|
-
<%- if serialization_data && serialization_data['metadata']['speedups'] -%>
|
|
172
|
-
<%- sp = serialization_data['metadata']['speedups'] -%>
|
|
173
|
-
| **Serialization** | <%= format_speedup(sp['min']) %> | <%= format_speedup(sp['max']) %> | <%= format_speedup(sp['avg']) %> |
|
|
174
|
-
<%- end -%>
|
|
175
|
-
<%- if specificity_data && specificity_data['metadata']['speedups'] -%>
|
|
176
|
-
<%- sp = specificity_data['metadata']['speedups'] -%>
|
|
177
|
-
| **Specificity** | <%= format_speedup(sp['min']) %> | <%= format_speedup(sp['max']) %> | <%= format_speedup(sp['avg']) %> |
|
|
178
|
-
<%- end -%>
|
|
179
|
-
<%- if merging_data && merging_data['metadata']['speedups'] -%>
|
|
180
|
-
<%- sp = merging_data['metadata']['speedups'] -%>
|
|
181
|
-
| **Merging** | <%= format_speedup(sp['min']) %> | <%= format_speedup(sp['max']) %> | <%= format_speedup(sp['avg']) %> |
|
|
182
|
-
<%- end -%>
|
|
183
|
-
|
|
184
|
-
### Implementation Notes
|
|
185
|
-
|
|
186
|
-
1. **C Extension**: Critical paths (parsing, specificity, merging, serialization) implemented in C
|
|
187
|
-
2. **Efficient Data Structures**: Rules grouped by media query for O(1) lookups
|
|
188
|
-
3. **Memory Efficient**: Pre-allocated string buffers, minimal Ruby object allocations
|
|
189
|
-
4. **Optimized Algorithms**: Purpose-built CSS specificity calculator
|
|
190
|
-
|
|
191
|
-
### Use Cases
|
|
192
|
-
|
|
193
|
-
- **Large CSS files**: Handles complex stylesheets efficiently
|
|
194
|
-
- **Specificity calculations**: Optimized for selector analysis
|
|
195
|
-
- **High-volume processing**: Reduced allocations minimize GC pressure
|
|
196
|
-
- **Production applications**: Tested with Bootstrap CSS and real-world stylesheets
|
|
197
|
-
|
|
198
|
-
---
|
|
199
|
-
|
|
200
|
-
## Running Benchmarks
|
|
201
|
-
|
|
202
|
-
```bash
|
|
203
|
-
# All benchmarks
|
|
204
|
-
rake benchmark 2>&1 | tee benchmark_output.txt
|
|
205
|
-
|
|
206
|
-
# Individual benchmarks
|
|
207
|
-
rake benchmark:parsing
|
|
208
|
-
rake benchmark:serialization
|
|
209
|
-
rake benchmark:specificity
|
|
210
|
-
rake benchmark:merging
|
|
211
|
-
rake benchmark:yjit
|
|
212
|
-
|
|
213
|
-
# Generate documentation
|
|
214
|
-
rake benchmark:generate_docs
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
## Notes
|
|
218
|
-
|
|
219
|
-
- All benchmarks use benchmark-ips with 3s warmup and 5-10s measurement periods
|
|
220
|
-
- Measurements are median i/s (iterations per second) with standard deviation
|
|
221
|
-
- css_parser gem must be installed for comparison benchmarks
|
data/benchmarks/yjit_tests.rb
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Shared test logic for YJIT benchmarks
|
|
4
|
-
# Extended by both YjitWithoutBenchmark and YjitWithBenchmark
|
|
5
|
-
module YjitTests
|
|
6
|
-
SAMPLE_CSS = <<~CSS
|
|
7
|
-
body { margin: 0; padding: 0; font-family: Arial, sans-serif; }
|
|
8
|
-
.header { color: #333; padding: 20px; background: #f8f9fa; }
|
|
9
|
-
.container { max-width: 1200px; margin: 0 auto; }
|
|
10
|
-
div p { line-height: 1.6; }
|
|
11
|
-
.container > .item { margin-bottom: 20px; }
|
|
12
|
-
h1 + p { margin-top: 0; font-size: 1.2em; }
|
|
13
|
-
CSS
|
|
14
|
-
|
|
15
|
-
def self.metadata
|
|
16
|
-
{
|
|
17
|
-
'operations' => [
|
|
18
|
-
'property access',
|
|
19
|
-
'declaration merging',
|
|
20
|
-
'to_s generation',
|
|
21
|
-
'parse + iterate'
|
|
22
|
-
],
|
|
23
|
-
'note' => 'C extension performance is the same regardless of YJIT. This measures Ruby code.'
|
|
24
|
-
}
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def self.speedup_config
|
|
28
|
-
# Compare without YJIT (baseline) vs with YJIT (comparison)
|
|
29
|
-
{
|
|
30
|
-
baseline_matcher: SpeedupCalculator::Matchers.without_yjit,
|
|
31
|
-
comparison_matcher: SpeedupCalculator::Matchers.with_yjit,
|
|
32
|
-
test_case_key: nil # No test_cases array, just operations
|
|
33
|
-
}
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def sanity_checks
|
|
37
|
-
# Verify basic operations work
|
|
38
|
-
decls = Cataract::Declarations.new
|
|
39
|
-
decls['color'] = 'red'
|
|
40
|
-
raise 'Property access failed' unless decls['color']
|
|
41
|
-
|
|
42
|
-
parser = Cataract::Stylesheet.new
|
|
43
|
-
parser.add_block(SAMPLE_CSS)
|
|
44
|
-
raise 'Parse failed' if parser.rules_count.zero?
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def call
|
|
48
|
-
run_property_access_benchmark
|
|
49
|
-
run_declaration_merging_benchmark
|
|
50
|
-
run_to_s_benchmark
|
|
51
|
-
run_parse_iterate_benchmark
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
private
|
|
55
|
-
|
|
56
|
-
def yjit_label
|
|
57
|
-
@yjit_label ||= defined?(RubyVM::YJIT.enabled?) && RubyVM::YJIT.enabled? ? 'YJIT' : 'no YJIT'
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def run_property_access_benchmark
|
|
61
|
-
puts '=' * 80
|
|
62
|
-
puts "TEST: Property access (get/set) - #{yjit_label}"
|
|
63
|
-
puts '=' * 80
|
|
64
|
-
|
|
65
|
-
benchmark('property_access') do |x|
|
|
66
|
-
x.config(time: 3, warmup: 1)
|
|
67
|
-
|
|
68
|
-
x.report("#{yjit_label}: property access") do
|
|
69
|
-
decls = Cataract::Declarations.new
|
|
70
|
-
decls['color'] = 'red'
|
|
71
|
-
decls['background'] = 'blue'
|
|
72
|
-
decls['font-size'] = '16px'
|
|
73
|
-
decls['margin'] = '10px'
|
|
74
|
-
decls['padding'] = '5px'
|
|
75
|
-
_ = decls['color']
|
|
76
|
-
_ = decls['background']
|
|
77
|
-
_ = decls['font-size']
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def run_declaration_merging_benchmark
|
|
83
|
-
puts "\n#{'=' * 80}"
|
|
84
|
-
puts "TEST: Declaration merging - #{yjit_label}"
|
|
85
|
-
puts '=' * 80
|
|
86
|
-
|
|
87
|
-
benchmark('declaration_merging') do |x|
|
|
88
|
-
x.config(time: 3, warmup: 1)
|
|
89
|
-
|
|
90
|
-
x.report("#{yjit_label}: declaration merging") do
|
|
91
|
-
decls1 = Cataract::Declarations.new
|
|
92
|
-
decls1['color'] = 'red'
|
|
93
|
-
decls1['font-size'] = '16px'
|
|
94
|
-
|
|
95
|
-
decls2 = Cataract::Declarations.new
|
|
96
|
-
decls2['background'] = 'blue'
|
|
97
|
-
decls2['margin'] = '10px'
|
|
98
|
-
|
|
99
|
-
decls1.merge(decls2)
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def run_to_s_benchmark
|
|
105
|
-
puts "\n#{'=' * 80}"
|
|
106
|
-
puts "TEST: to_s generation - #{yjit_label}"
|
|
107
|
-
puts '=' * 80
|
|
108
|
-
|
|
109
|
-
benchmark('to_s') do |x|
|
|
110
|
-
x.config(time: 3, warmup: 1)
|
|
111
|
-
|
|
112
|
-
x.report("#{yjit_label}: to_s generation") do
|
|
113
|
-
decls = Cataract::Declarations.new
|
|
114
|
-
decls['color'] = 'red'
|
|
115
|
-
decls['background'] = 'blue'
|
|
116
|
-
decls['font-size'] = '16px'
|
|
117
|
-
decls['margin'] = '10px'
|
|
118
|
-
decls['padding'] = '5px'
|
|
119
|
-
decls.to_s
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def run_parse_iterate_benchmark
|
|
125
|
-
puts "\n#{'=' * 80}"
|
|
126
|
-
puts "TEST: Parse + iterate - #{yjit_label}"
|
|
127
|
-
puts '=' * 80
|
|
128
|
-
|
|
129
|
-
benchmark('parse_iterate') do |x|
|
|
130
|
-
x.config(time: 3, warmup: 1)
|
|
131
|
-
|
|
132
|
-
x.report("#{yjit_label}: parse + iterate") do
|
|
133
|
-
parser = Cataract::Stylesheet.new
|
|
134
|
-
parser.add_block(SAMPLE_CSS)
|
|
135
|
-
parser.select(&:selector?).each do |rule|
|
|
136
|
-
_ = rule.declarations
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
end
|