tint_me 1.0.0
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 +7 -0
- data/.rubocop_todo.yml +7 -0
- data/.serena/project.yml +68 -0
- data/.simplecov +24 -0
- data/.yardopts +6 -0
- data/AGENTS.md +60 -0
- data/CHANGELOG.md +29 -0
- data/CLAUDE.md +1 -0
- data/LICENSE.txt +21 -0
- data/README.md +175 -0
- data/RELEASING.md +202 -0
- data/Rakefile +18 -0
- data/benchmark/2025-09-08-style-caching-optimization/01_baseline_results.txt +39 -0
- data/benchmark/2025-09-08-style-caching-optimization/02_with_full_caching_results.txt +54 -0
- data/benchmark/2025-09-08-style-caching-optimization/03_prefix_only_caching_results.txt +107 -0
- data/benchmark/2025-09-08-style-caching-optimization/04_baseline_vs_optimized_analysis.txt +65 -0
- data/benchmark/2025-09-08-style-caching-optimization/05_caching_approaches_comparison.txt +59 -0
- data/benchmark/2025-09-08-style-caching-optimization/06_append_operator_results.txt +107 -0
- data/benchmark/2025-09-08-style-caching-optimization/07_string_concatenation_comparison.txt +66 -0
- data/benchmark/2025-09-08-style-caching-optimization/08_with_freeze_optimization_results.txt +107 -0
- data/benchmark/2025-09-08-style-caching-optimization/09_freeze_optimization_analysis.txt +49 -0
- data/benchmark/2025-09-08-style-caching-optimization/10_constant_access_results.txt +107 -0
- data/benchmark/2025-09-08-style-caching-optimization/11_constant_vs_cache_analysis.txt +74 -0
- data/benchmark/2025-09-08-style-caching-optimization/12_empty_prefix_analysis.txt +81 -0
- data/benchmark/2025-09-08-style-caching-optimization/13_nil_check_optimization_results.txt +107 -0
- data/benchmark/2025-09-08-style-caching-optimization/14_nil_vs_empty_check_analysis.txt +81 -0
- data/benchmark/2025-09-08-style-caching-optimization/README.md +45 -0
- data/benchmark/2025-09-08-style-caching-optimization/benchmark_script.rb +180 -0
- data/docs/agents/git-pr.md +298 -0
- data/docs/agents/languages.md +388 -0
- data/docs/agents/rubocop.md +55 -0
- data/lib/tint_me/error.rb +6 -0
- data/lib/tint_me/sgr_builder.rb +259 -0
- data/lib/tint_me/style/schema.rb +22 -0
- data/lib/tint_me/style/types.rb +50 -0
- data/lib/tint_me/style.rb +286 -0
- data/lib/tint_me/version.rb +8 -0
- data/lib/tint_me.rb +62 -0
- data/mise.toml +5 -0
- data/sig/tint_me.rbs +61 -0
- metadata +131 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
OPTIMIZED BENCHMARK RESULTS (After Caching Implementation)
|
2
|
+
==========================================================
|
3
|
+
Date: 2025-09-08
|
4
|
+
|
5
|
+
## Performance Summary
|
6
|
+
|
7
|
+
### Style Application (operations/second)
|
8
|
+
- Simple style: ~5.44M ops/s (184ns per call)
|
9
|
+
- Complex style: ~3.83M ops/s (261ns per call)
|
10
|
+
- Hex color style: ~4.66M ops/s (215ns per call)
|
11
|
+
|
12
|
+
### Repeated Application (1000x)
|
13
|
+
- Simple style: 6,383 ops/s (157μs total)
|
14
|
+
- Complex style: 4,294 ops/s (233μs total)
|
15
|
+
- Hex style: 5,343 ops/s (187μs total)
|
16
|
+
|
17
|
+
### Memory Usage
|
18
|
+
- Simple style creation: 6.1KB, 58 objects (+350 bytes, +6 objects)
|
19
|
+
- Complex style creation: 7.8KB, 79 objects (+1.2KB, +13 objects)
|
20
|
+
- Simple style application: 424 bytes, 3 objects
|
21
|
+
- Complex style application: 264 bytes, 2 objects
|
22
|
+
|
23
|
+
### Object Allocations (100 applications)
|
24
|
+
- Simple style: 104 objects (85% reduction)
|
25
|
+
- Complex style: 104 objects (91% reduction)
|
26
|
+
|
27
|
+
## Performance Improvements
|
28
|
+
|
29
|
+
### Speed Improvements
|
30
|
+
- Simple style: 7.1x faster (766k → 5.44M ops/s)
|
31
|
+
- Complex style: 8.8x faster (437k → 3.83M ops/s)
|
32
|
+
- Hex color style: 17.5x faster (266k → 4.66M ops/s)
|
33
|
+
|
34
|
+
### Object Allocation Reductions
|
35
|
+
- Simple style: 85% fewer objects (703 → 104)
|
36
|
+
- Complex style: 91% fewer objects (1203 → 104)
|
37
|
+
|
38
|
+
### Repeated Application Improvements
|
39
|
+
- Simple style: 8.2x faster (781 → 6,383 ops/s)
|
40
|
+
- Complex style: 9.9x faster (433 → 4,294 ops/s)
|
41
|
+
- Hex style: 20.2x faster (265 → 5,343 ops/s)
|
42
|
+
|
43
|
+
## Memory Trade-offs
|
44
|
+
- Style creation memory increase: 6-18% higher
|
45
|
+
- Per-application memory usage: Dramatically reduced
|
46
|
+
- Overall memory efficiency: Much better for repeated use
|
47
|
+
|
48
|
+
## Key Observations
|
49
|
+
|
50
|
+
1. **Massive performance gains**: 7-18x faster style application
|
51
|
+
2. **Dramatic allocation reduction**: 85-91% fewer objects
|
52
|
+
3. **Consistent performance**: Style complexity no longer impacts speed significantly
|
53
|
+
4. **Memory trade-off acceptable**: Small creation overhead, huge runtime savings
|
54
|
+
5. **Hex colors now fast**: RGB conversion cached at creation time
|
@@ -0,0 +1,107 @@
|
|
1
|
+
============================================================
|
2
|
+
TIntMe Style Performance Benchmark
|
3
|
+
============================================================
|
4
|
+
|
5
|
+
Memory Usage Analysis:
|
6
|
+
----------------------------------------
|
7
|
+
Calculating -------------------------------------
|
8
|
+
Create simple style 6.048k memsize ( 0.000 retained)
|
9
|
+
58.000 objects ( 0.000 retained)
|
10
|
+
2.000 strings ( 0.000 retained)
|
11
|
+
Create complex style 7.744k memsize ( 0.000 retained)
|
12
|
+
79.000 objects ( 0.000 retained)
|
13
|
+
9.000 strings ( 0.000 retained)
|
14
|
+
Apply simple style (short text)
|
15
|
+
616.000 memsize ( 0.000 retained)
|
16
|
+
4.000 objects ( 0.000 retained)
|
17
|
+
1.000 strings ( 0.000 retained)
|
18
|
+
Apply complex style (short text)
|
19
|
+
264.000 memsize ( 0.000 retained)
|
20
|
+
2.000 objects ( 0.000 retained)
|
21
|
+
1.000 strings ( 0.000 retained)
|
22
|
+
|
23
|
+
Comparison:
|
24
|
+
Apply complex style (short text): 264 allocated
|
25
|
+
Apply simple style (short text): 616 allocated - 2.33x more
|
26
|
+
Create simple style: 6048 allocated - 22.91x more
|
27
|
+
Create complex style: 7744 allocated - 29.33x more
|
28
|
+
|
29
|
+
Performance Benchmark (operations per second):
|
30
|
+
----------------------------------------
|
31
|
+
ruby 3.2.9 (2025-07-24 revision 8f611e0c46) [arm64-darwin24]
|
32
|
+
Warming up --------------------------------------
|
33
|
+
Create simple style 2.927k i/100ms
|
34
|
+
Create complex style 2.413k i/100ms
|
35
|
+
Apply simple style (short)
|
36
|
+
443.590k i/100ms
|
37
|
+
Apply simple style (medium)
|
38
|
+
395.847k i/100ms
|
39
|
+
Apply simple style (long)
|
40
|
+
378.681k i/100ms
|
41
|
+
Apply complex style (short)
|
42
|
+
321.759k i/100ms
|
43
|
+
Apply complex style (medium)
|
44
|
+
382.195k i/100ms
|
45
|
+
Apply complex style (long)
|
46
|
+
356.585k i/100ms
|
47
|
+
Apply hex style (short)
|
48
|
+
373.664k i/100ms
|
49
|
+
Calculating -------------------------------------
|
50
|
+
Create simple style 29.037k (± 3.1%) i/s (34.44 μs/i) - 146.350k in 5.045026s
|
51
|
+
Create complex style 24.894k (± 1.7%) i/s (40.17 μs/i) - 125.476k in 5.042000s
|
52
|
+
Apply simple style (short)
|
53
|
+
4.428M (± 0.8%) i/s (225.85 ns/i) - 22.180M in 5.009439s
|
54
|
+
Apply simple style (medium)
|
55
|
+
3.847M (± 1.4%) i/s (259.95 ns/i) - 19.397M in 5.043123s
|
56
|
+
Apply simple style (long)
|
57
|
+
3.764M (± 1.6%) i/s (265.69 ns/i) - 18.934M in 5.031865s
|
58
|
+
Apply complex style (short)
|
59
|
+
3.275M (± 1.0%) i/s (305.32 ns/i) - 16.410M in 5.010664s
|
60
|
+
Apply complex style (medium)
|
61
|
+
3.748M (± 4.8%) i/s (266.82 ns/i) - 18.728M in 5.012920s
|
62
|
+
Apply complex style (long)
|
63
|
+
3.469M (± 5.5%) i/s (288.30 ns/i) - 17.473M in 5.056096s
|
64
|
+
Apply hex style (short)
|
65
|
+
3.747M (± 3.1%) i/s (266.90 ns/i) - 19.057M in 5.092324s
|
66
|
+
|
67
|
+
Comparison:
|
68
|
+
Apply simple style (short): 4427800.1 i/s
|
69
|
+
Apply simple style (medium): 3846907.6 i/s - 1.15x slower
|
70
|
+
Apply simple style (long): 3763792.3 i/s - 1.18x slower
|
71
|
+
Apply complex style (medium): 3747858.3 i/s - 1.18x slower
|
72
|
+
Apply hex style (short): 3746719.7 i/s - 1.18x slower
|
73
|
+
Apply complex style (long): 3468603.6 i/s - 1.28x slower
|
74
|
+
Apply complex style (short): 3275289.7 i/s - 1.35x slower
|
75
|
+
Create simple style: 29037.4 i/s - 152.49x slower
|
76
|
+
Create complex style: 24894.1 i/s - 177.87x slower
|
77
|
+
|
78
|
+
|
79
|
+
Repeated Application Benchmark:
|
80
|
+
----------------------------------------
|
81
|
+
Applying the same style 1000 times to measure caching benefit...
|
82
|
+
ruby 3.2.9 (2025-07-24 revision 8f611e0c46) [arm64-darwin24]
|
83
|
+
Warming up --------------------------------------
|
84
|
+
1000x simple style 497.000 i/100ms
|
85
|
+
1000x complex style 357.000 i/100ms
|
86
|
+
1000x hex style 426.000 i/100ms
|
87
|
+
Calculating -------------------------------------
|
88
|
+
1000x simple style 4.961k (± 0.9%) i/s (201.59 μs/i) - 24.850k in 5.009943s
|
89
|
+
1000x complex style 3.553k (± 3.4%) i/s (281.45 μs/i) - 17.850k in 5.031381s
|
90
|
+
1000x hex style 4.171k (± 5.0%) i/s (239.76 μs/i) - 20.874k in 5.019703s
|
91
|
+
|
92
|
+
Comparison:
|
93
|
+
1000x simple style: 4960.5 i/s
|
94
|
+
1000x hex style: 4170.9 i/s - 1.19x slower
|
95
|
+
1000x complex style: 3553.0 i/s - 1.40x slower
|
96
|
+
|
97
|
+
|
98
|
+
Object Allocation Analysis:
|
99
|
+
----------------------------------------
|
100
|
+
Create simple style: 117 objects allocated
|
101
|
+
Create complex style: 136 objects allocated
|
102
|
+
Apply simple style 100x: 104 objects allocated
|
103
|
+
Apply complex style 100x: 104 objects allocated
|
104
|
+
|
105
|
+
============================================================
|
106
|
+
Benchmark complete!
|
107
|
+
============================================================
|
@@ -0,0 +1,65 @@
|
|
1
|
+
PERFORMANCE COMPARISON ANALYSIS
|
2
|
+
===============================
|
3
|
+
|
4
|
+
## Before vs After Optimization Summary
|
5
|
+
|
6
|
+
### Style Application Performance (ops/second)
|
7
|
+
| Style Type | Before | After | Improvement |
|
8
|
+
|------------|-----------|-----------|-------------|
|
9
|
+
| Simple | 766,000 | 5,444,000 | 7.1x faster |
|
10
|
+
| Complex | 437,000 | 3,834,000 | 8.8x faster |
|
11
|
+
| Hex Color | 266,000 | 4,656,000 | 17.5x faster|
|
12
|
+
|
13
|
+
### Repeated Application (1000x, ops/second)
|
14
|
+
| Style Type | Before | After | Improvement |
|
15
|
+
|------------|--------|-------|-------------|
|
16
|
+
| Simple | 781 | 6,383 | 8.2x faster |
|
17
|
+
| Complex | 433 | 4,294 | 9.9x faster |
|
18
|
+
| Hex | 265 | 5,343 | 20.2x faster|
|
19
|
+
|
20
|
+
### Object Allocations (100 applications)
|
21
|
+
| Style Type | Before | After | Reduction |
|
22
|
+
|------------|--------|-------|-----------|
|
23
|
+
| Simple | 703 | 104 | 85% less |
|
24
|
+
| Complex | 1,203 | 104 | 91% less |
|
25
|
+
|
26
|
+
### Memory Usage Per Style Creation
|
27
|
+
| Style Type | Before | After | Increase |
|
28
|
+
|------------|---------------|---------------|----------|
|
29
|
+
| Simple | 5.8KB, 52 obj| 6.1KB, 58 obj | +6% |
|
30
|
+
| Complex | 6.6KB, 66 obj| 7.8KB, 79 obj | +18% |
|
31
|
+
|
32
|
+
## Key Insights
|
33
|
+
|
34
|
+
### Performance Gains
|
35
|
+
1. **Hex colors see biggest improvement**: 17.5-20x faster
|
36
|
+
- RGB conversion now happens once at creation instead of every call
|
37
|
+
|
38
|
+
2. **Complex styles benefit most**: 8.8-9.9x faster
|
39
|
+
- Multiple SGR parameters cached as single string
|
40
|
+
|
41
|
+
3. **Simple styles still significant**: 7.1-8.2x faster
|
42
|
+
- Even basic styles benefit from eliminating repeated calculation
|
43
|
+
|
44
|
+
### Memory Trade-offs
|
45
|
+
1. **Creation cost acceptable**: 6-18% increase in creation memory
|
46
|
+
- Small price for immutable objects that may be called many times
|
47
|
+
|
48
|
+
2. **Runtime memory much better**: Massive reduction in per-call allocations
|
49
|
+
- 85-91% fewer objects created during style application
|
50
|
+
|
51
|
+
3. **Net positive for typical usage**: Any style called >2-3 times benefits
|
52
|
+
|
53
|
+
### Algorithm Complexity Improvements
|
54
|
+
1. **Before**: O(n) per call where n = number of style attributes
|
55
|
+
2. **After**: O(1) per call - just string concatenation
|
56
|
+
3. **One-time cost**: SGR sequence building moved to initialization
|
57
|
+
|
58
|
+
## Recommendation
|
59
|
+
The optimization is highly successful with minimal downsides:
|
60
|
+
- Dramatic performance improvements across all scenarios
|
61
|
+
- Acceptable memory trade-off for creation
|
62
|
+
- Maintains identical API and behavior
|
63
|
+
- Especially beneficial for repeated use (the common case)
|
64
|
+
|
65
|
+
This change transforms Style from a computation-heavy operation to a simple string concatenation, making it suitable for high-frequency styling operations.
|
@@ -0,0 +1,59 @@
|
|
1
|
+
CACHING APPROACH COMPARISON
|
2
|
+
===========================
|
3
|
+
Date: 2025-09-08
|
4
|
+
|
5
|
+
## Memory Usage Comparison (Style Creation)
|
6
|
+
|
7
|
+
### With reset_code caching:
|
8
|
+
- Simple style: 6.1KB, 58 objects
|
9
|
+
- Complex style: 7.8KB, 79 objects
|
10
|
+
|
11
|
+
### Without reset_code caching:
|
12
|
+
- Simple style: 6.0KB, 58 objects (-8 bytes)
|
13
|
+
- Complex style: 7.7KB, 79 objects (-8 bytes)
|
14
|
+
|
15
|
+
**Memory savings: ~8 bytes per Style instance (negligible)**
|
16
|
+
|
17
|
+
## Performance Comparison (ops/second)
|
18
|
+
|
19
|
+
### Style Application Performance:
|
20
|
+
| Style Type | With reset_code cache | Without reset_code cache | Difference |
|
21
|
+
|------------|----------------------|---------------------------|------------|
|
22
|
+
| Simple | 5.44M | 4.43M | 18% slower |
|
23
|
+
| Complex | 3.83M | 3.28M | 14% slower |
|
24
|
+
| Hex | 4.66M | 3.75M | 20% slower |
|
25
|
+
|
26
|
+
### Repeated Application (1000x):
|
27
|
+
| Style Type | With cache | Without cache | Difference |
|
28
|
+
|------------|------------|---------------|------------|
|
29
|
+
| Simple | 6,383 | 4,961 | 22% slower |
|
30
|
+
| Complex | 4,294 | 3,553 | 17% slower |
|
31
|
+
| Hex | 5,343 | 4,171 | 22% slower |
|
32
|
+
|
33
|
+
### Memory Usage Per Application:
|
34
|
+
| Style Type | With cache | Without cache | Difference |
|
35
|
+
|------------|------------|---------------|------------|
|
36
|
+
| Simple | 424 bytes | 616 bytes | +45% more |
|
37
|
+
| Complex | 264 bytes | 264 bytes | same |
|
38
|
+
|
39
|
+
## Analysis
|
40
|
+
|
41
|
+
### Performance Impact:
|
42
|
+
- **14-22% performance decrease** without reset_code caching
|
43
|
+
- Simple styles show highest impact (22% slower)
|
44
|
+
- Memory allocation per call increases for simple styles
|
45
|
+
|
46
|
+
### Memory Trade-off:
|
47
|
+
- **Minimal creation savings**: Only 8 bytes per Style instance
|
48
|
+
- **Higher runtime cost**: Simple styles use 45% more memory per call
|
49
|
+
- **Net negative**: More allocations during frequent usage
|
50
|
+
|
51
|
+
### Recommendations:
|
52
|
+
|
53
|
+
**Keep reset_code caching** because:
|
54
|
+
1. Negligible memory savings (8 bytes) when removed
|
55
|
+
2. Significant performance cost (14-22% slower)
|
56
|
+
3. Increased runtime memory allocations
|
57
|
+
4. Reset code is a constant string ("\e[0m") - perfect for caching
|
58
|
+
|
59
|
+
The reset_code caching provides substantial performance benefits with minimal memory overhead, making it an optimal trade-off for the typical use case of applying styles multiple times.
|
@@ -0,0 +1,107 @@
|
|
1
|
+
============================================================
|
2
|
+
TIntMe Style Performance Benchmark
|
3
|
+
============================================================
|
4
|
+
|
5
|
+
Memory Usage Analysis:
|
6
|
+
----------------------------------------
|
7
|
+
Calculating -------------------------------------
|
8
|
+
Create simple style 6.056k memsize ( 0.000 retained)
|
9
|
+
58.000 objects ( 0.000 retained)
|
10
|
+
2.000 strings ( 0.000 retained)
|
11
|
+
Create complex style 7.752k memsize ( 0.000 retained)
|
12
|
+
79.000 objects ( 0.000 retained)
|
13
|
+
9.000 strings ( 0.000 retained)
|
14
|
+
Apply simple style (short text)
|
15
|
+
424.000 memsize ( 0.000 retained)
|
16
|
+
3.000 objects ( 0.000 retained)
|
17
|
+
1.000 strings ( 0.000 retained)
|
18
|
+
Apply complex style (short text)
|
19
|
+
264.000 memsize ( 0.000 retained)
|
20
|
+
2.000 objects ( 0.000 retained)
|
21
|
+
1.000 strings ( 0.000 retained)
|
22
|
+
|
23
|
+
Comparison:
|
24
|
+
Apply complex style (short text): 264 allocated
|
25
|
+
Apply simple style (short text): 424 allocated - 1.61x more
|
26
|
+
Create simple style: 6056 allocated - 22.94x more
|
27
|
+
Create complex style: 7752 allocated - 29.36x more
|
28
|
+
|
29
|
+
Performance Benchmark (operations per second):
|
30
|
+
----------------------------------------
|
31
|
+
ruby 3.2.9 (2025-07-24 revision 8f611e0c46) [arm64-darwin24]
|
32
|
+
Warming up --------------------------------------
|
33
|
+
Create simple style 2.537k i/100ms
|
34
|
+
Create complex style 2.341k i/100ms
|
35
|
+
Apply simple style (short)
|
36
|
+
466.725k i/100ms
|
37
|
+
Apply simple style (medium)
|
38
|
+
341.328k i/100ms
|
39
|
+
Apply simple style (long)
|
40
|
+
287.127k i/100ms
|
41
|
+
Apply complex style (short)
|
42
|
+
323.061k i/100ms
|
43
|
+
Apply complex style (medium)
|
44
|
+
336.757k i/100ms
|
45
|
+
Apply complex style (long)
|
46
|
+
303.412k i/100ms
|
47
|
+
Apply hex style (short)
|
48
|
+
237.369k i/100ms
|
49
|
+
Calculating -------------------------------------
|
50
|
+
Create simple style 28.350k (± 3.5%) i/s (35.27 μs/i) - 142.072k in 5.018115s
|
51
|
+
Create complex style 22.956k (± 8.6%) i/s (43.56 μs/i) - 114.709k in 5.048226s
|
52
|
+
Apply simple style (short)
|
53
|
+
4.604M (± 1.7%) i/s (217.20 ns/i) - 23.336M in 5.069941s
|
54
|
+
Apply simple style (medium)
|
55
|
+
3.365M (± 3.7%) i/s (297.21 ns/i) - 17.066M in 5.080576s
|
56
|
+
Apply simple style (long)
|
57
|
+
3.071M (± 4.5%) i/s (325.67 ns/i) - 15.505M in 5.059977s
|
58
|
+
Apply complex style (short)
|
59
|
+
3.362M (± 4.0%) i/s (297.41 ns/i) - 16.799M in 5.006339s
|
60
|
+
Apply complex style (medium)
|
61
|
+
3.337M (± 1.8%) i/s (299.70 ns/i) - 16.838M in 5.047809s
|
62
|
+
Apply complex style (long)
|
63
|
+
3.027M (± 6.1%) i/s (330.32 ns/i) - 15.171M in 5.032030s
|
64
|
+
Apply hex style (short)
|
65
|
+
2.473M (± 1.8%) i/s (404.40 ns/i) - 12.581M in 5.089276s
|
66
|
+
|
67
|
+
Comparison:
|
68
|
+
Apply simple style (short): 4604142.2 i/s
|
69
|
+
Apply simple style (medium): 3364580.5 i/s - 1.37x slower
|
70
|
+
Apply complex style (short): 3362358.4 i/s - 1.37x slower
|
71
|
+
Apply complex style (medium): 3336720.3 i/s - 1.38x slower
|
72
|
+
Apply simple style (long): 3070605.6 i/s - 1.50x slower
|
73
|
+
Apply complex style (long): 3027356.7 i/s - 1.52x slower
|
74
|
+
Apply hex style (short): 2472779.1 i/s - 1.86x slower
|
75
|
+
Create simple style: 28349.6 i/s - 162.41x slower
|
76
|
+
Create complex style: 22956.2 i/s - 200.56x slower
|
77
|
+
|
78
|
+
|
79
|
+
Repeated Application Benchmark:
|
80
|
+
----------------------------------------
|
81
|
+
Applying the same style 1000 times to measure caching benefit...
|
82
|
+
ruby 3.2.9 (2025-07-24 revision 8f611e0c46) [arm64-darwin24]
|
83
|
+
Warming up --------------------------------------
|
84
|
+
1000x simple style 528.000 i/100ms
|
85
|
+
1000x complex style 362.000 i/100ms
|
86
|
+
1000x hex style 238.000 i/100ms
|
87
|
+
Calculating -------------------------------------
|
88
|
+
1000x simple style 5.013k (± 7.6%) i/s (199.47 μs/i) - 25.344k in 5.092091s
|
89
|
+
1000x complex style 3.694k (± 2.3%) i/s (270.71 μs/i) - 18.462k in 5.000406s
|
90
|
+
1000x hex style 2.608k (± 5.6%) i/s (383.40 μs/i) - 13.090k in 5.040010s
|
91
|
+
|
92
|
+
Comparison:
|
93
|
+
1000x simple style: 5013.4 i/s
|
94
|
+
1000x complex style: 3694.0 i/s - 1.36x slower
|
95
|
+
1000x hex style: 2608.3 i/s - 1.92x slower
|
96
|
+
|
97
|
+
|
98
|
+
Object Allocation Analysis:
|
99
|
+
----------------------------------------
|
100
|
+
Create simple style: 117 objects allocated
|
101
|
+
Create complex style: 136 objects allocated
|
102
|
+
Apply simple style 100x: 104 objects allocated
|
103
|
+
Apply complex style 100x: 104 objects allocated
|
104
|
+
|
105
|
+
============================================================
|
106
|
+
Benchmark complete!
|
107
|
+
============================================================
|
@@ -0,0 +1,66 @@
|
|
1
|
+
STRING CONCATENATION METHOD COMPARISON
|
2
|
+
======================================
|
3
|
+
Date: 2025-09-08
|
4
|
+
|
5
|
+
## Performance Comparison: String Interpolation vs << Operator
|
6
|
+
|
7
|
+
### Method Implementations
|
8
|
+
|
9
|
+
#### String Interpolation (Original)
|
10
|
+
```ruby
|
11
|
+
def call(text)
|
12
|
+
return text if @prefix.empty?
|
13
|
+
"#{@prefix}#{text}#{@reset_code}"
|
14
|
+
end
|
15
|
+
```
|
16
|
+
|
17
|
+
#### << Operator (Experimental)
|
18
|
+
```ruby
|
19
|
+
def call(text)
|
20
|
+
return text if @prefix.empty?
|
21
|
+
@prefix.dup << text << @reset_code
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
### Performance Results (ops/second)
|
26
|
+
|
27
|
+
| Style Type | String Interpolation | << Operator | Performance Loss |
|
28
|
+
|------------|---------------------|-------------|------------------|
|
29
|
+
| Simple | 5.44M/s | 4.55M/s | **16% slower** |
|
30
|
+
| Complex | 3.83M/s | 3.35M/s | **13% slower** |
|
31
|
+
| Hex Color | 4.66M/s | 2.45M/s | **47% slower** |
|
32
|
+
|
33
|
+
### Memory Usage (per application)
|
34
|
+
|
35
|
+
| Implementation | Simple Style | Complex Style |
|
36
|
+
|----------------|-------------|---------------|
|
37
|
+
| String Interpolation | 424 bytes, 3 objects | 264 bytes, 2 objects |
|
38
|
+
| << Operator | 424 bytes, 3 objects | 264 bytes, 2 objects |
|
39
|
+
|
40
|
+
*Memory usage appears identical*
|
41
|
+
|
42
|
+
### Analysis
|
43
|
+
|
44
|
+
#### Why << Operator is Slower:
|
45
|
+
|
46
|
+
1. **Extra Copy Cost**: `@prefix.dup` creates unnecessary string copy
|
47
|
+
2. **Multiple Operations**: Three separate `<<` calls vs single interpolation
|
48
|
+
3. **Ruby Optimization**: String interpolation is highly optimized in Ruby
|
49
|
+
4. **Hex Colors Impact**: Most significant performance hit (47% slower)
|
50
|
+
|
51
|
+
#### Performance Loss Breakdown:
|
52
|
+
|
53
|
+
- **Simple styles**: 16% slower due to dup + concatenation overhead
|
54
|
+
- **Complex styles**: 13% slower, similar pattern
|
55
|
+
- **Hex colors**: 47% slower, suggests interpolation especially optimized for longer strings
|
56
|
+
|
57
|
+
### Conclusion
|
58
|
+
|
59
|
+
**String interpolation (`"#{a}#{b}#{c}"`) is definitively superior** for this use case:
|
60
|
+
|
61
|
+
- Consistently faster across all style types
|
62
|
+
- No additional memory allocation overhead
|
63
|
+
- Leverages Ruby's built-in string interpolation optimizations
|
64
|
+
- Simpler, more readable code
|
65
|
+
|
66
|
+
The experiment confirms that the original implementation choice was optimal. Ruby's string interpolation is highly optimized and should be preferred over manual concatenation methods for performance-critical string building operations.
|
@@ -0,0 +1,107 @@
|
|
1
|
+
============================================================
|
2
|
+
TIntMe Style Performance Benchmark
|
3
|
+
============================================================
|
4
|
+
|
5
|
+
Memory Usage Analysis:
|
6
|
+
----------------------------------------
|
7
|
+
Calculating -------------------------------------
|
8
|
+
Create simple style 6.056k memsize ( 0.000 retained)
|
9
|
+
58.000 objects ( 0.000 retained)
|
10
|
+
2.000 strings ( 0.000 retained)
|
11
|
+
Create complex style 7.752k memsize ( 0.000 retained)
|
12
|
+
79.000 objects ( 0.000 retained)
|
13
|
+
9.000 strings ( 0.000 retained)
|
14
|
+
Apply simple style (short text)
|
15
|
+
424.000 memsize ( 0.000 retained)
|
16
|
+
3.000 objects ( 0.000 retained)
|
17
|
+
1.000 strings ( 0.000 retained)
|
18
|
+
Apply complex style (short text)
|
19
|
+
264.000 memsize ( 0.000 retained)
|
20
|
+
2.000 objects ( 0.000 retained)
|
21
|
+
1.000 strings ( 0.000 retained)
|
22
|
+
|
23
|
+
Comparison:
|
24
|
+
Apply complex style (short text): 264 allocated
|
25
|
+
Apply simple style (short text): 424 allocated - 1.61x more
|
26
|
+
Create simple style: 6056 allocated - 22.94x more
|
27
|
+
Create complex style: 7752 allocated - 29.36x more
|
28
|
+
|
29
|
+
Performance Benchmark (operations per second):
|
30
|
+
----------------------------------------
|
31
|
+
ruby 3.2.9 (2025-07-24 revision 8f611e0c46) [arm64-darwin24]
|
32
|
+
Warming up --------------------------------------
|
33
|
+
Create simple style 2.829k i/100ms
|
34
|
+
Create complex style 2.405k i/100ms
|
35
|
+
Apply simple style (short)
|
36
|
+
551.851k i/100ms
|
37
|
+
Apply simple style (medium)
|
38
|
+
476.907k i/100ms
|
39
|
+
Apply simple style (long)
|
40
|
+
482.203k i/100ms
|
41
|
+
Apply complex style (short)
|
42
|
+
381.682k i/100ms
|
43
|
+
Apply complex style (medium)
|
44
|
+
455.559k i/100ms
|
45
|
+
Apply complex style (long)
|
46
|
+
417.965k i/100ms
|
47
|
+
Apply hex style (short)
|
48
|
+
470.351k i/100ms
|
49
|
+
Calculating -------------------------------------
|
50
|
+
Create simple style 27.161k (± 6.4%) i/s (36.82 μs/i) - 135.792k in 5.024378s
|
51
|
+
Create complex style 23.009k (± 4.3%) i/s (43.46 μs/i) - 115.440k in 5.027763s
|
52
|
+
Apply simple style (short)
|
53
|
+
5.264M (± 3.8%) i/s (189.96 ns/i) - 26.489M in 5.039995s
|
54
|
+
Apply simple style (medium)
|
55
|
+
4.621M (± 3.1%) i/s (216.40 ns/i) - 23.368M in 5.061823s
|
56
|
+
Apply simple style (long)
|
57
|
+
4.478M (± 4.8%) i/s (223.34 ns/i) - 22.664M in 5.074611s
|
58
|
+
Apply complex style (short)
|
59
|
+
3.685M (± 2.4%) i/s (271.36 ns/i) - 18.702M in 5.078168s
|
60
|
+
Apply complex style (medium)
|
61
|
+
4.536M (± 4.8%) i/s (220.45 ns/i) - 22.778M in 5.036293s
|
62
|
+
Apply complex style (long)
|
63
|
+
4.271M (± 7.5%) i/s (234.13 ns/i) - 21.316M in 5.031500s
|
64
|
+
Apply hex style (short)
|
65
|
+
4.558M (± 3.7%) i/s (219.39 ns/i) - 23.047M in 5.063931s
|
66
|
+
|
67
|
+
Comparison:
|
68
|
+
Apply simple style (short): 5264329.5 i/s
|
69
|
+
Apply simple style (medium): 4621101.0 i/s - 1.14x slower
|
70
|
+
Apply hex style (short): 4558064.1 i/s - 1.15x slower
|
71
|
+
Apply complex style (medium): 4536089.7 i/s - 1.16x slower
|
72
|
+
Apply simple style (long): 4477533.0 i/s - 1.18x slower
|
73
|
+
Apply complex style (long): 4271132.9 i/s - 1.23x slower
|
74
|
+
Apply complex style (short): 3685074.9 i/s - 1.43x slower
|
75
|
+
Create simple style: 27161.3 i/s - 193.82x slower
|
76
|
+
Create complex style: 23008.5 i/s - 228.80x slower
|
77
|
+
|
78
|
+
|
79
|
+
Repeated Application Benchmark:
|
80
|
+
----------------------------------------
|
81
|
+
Applying the same style 1000 times to measure caching benefit...
|
82
|
+
ruby 3.2.9 (2025-07-24 revision 8f611e0c46) [arm64-darwin24]
|
83
|
+
Warming up --------------------------------------
|
84
|
+
1000x simple style 631.000 i/100ms
|
85
|
+
1000x complex style 412.000 i/100ms
|
86
|
+
1000x hex style 540.000 i/100ms
|
87
|
+
Calculating -------------------------------------
|
88
|
+
1000x simple style 6.203k (± 2.1%) i/s (161.20 μs/i) - 31.550k in 5.088346s
|
89
|
+
1000x complex style 4.119k (± 5.2%) i/s (242.77 μs/i) - 20.600k in 5.018834s
|
90
|
+
1000x hex style 5.267k (± 2.8%) i/s (189.85 μs/i) - 26.460k in 5.027249s
|
91
|
+
|
92
|
+
Comparison:
|
93
|
+
1000x simple style: 6203.3 i/s
|
94
|
+
1000x hex style: 5267.4 i/s - 1.18x slower
|
95
|
+
1000x complex style: 4119.1 i/s - 1.51x slower
|
96
|
+
|
97
|
+
|
98
|
+
Object Allocation Analysis:
|
99
|
+
----------------------------------------
|
100
|
+
Create simple style: 117 objects allocated
|
101
|
+
Create complex style: 136 objects allocated
|
102
|
+
Apply simple style 100x: 103 objects allocated
|
103
|
+
Apply complex style 100x: 103 objects allocated
|
104
|
+
|
105
|
+
============================================================
|
106
|
+
Benchmark complete!
|
107
|
+
============================================================
|
@@ -0,0 +1,49 @@
|
|
1
|
+
FREEZE OPTIMIZATION ANALYSIS
|
2
|
+
=============================
|
3
|
+
Date: 2025-09-08
|
4
|
+
|
5
|
+
## Implementation Change
|
6
|
+
|
7
|
+
Added `.freeze` to the cached prefix string:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
# Before
|
11
|
+
@prefix = sgr_builder.prefix_codes(...)
|
12
|
+
|
13
|
+
# After
|
14
|
+
@prefix = sgr_builder.prefix_codes(...).freeze
|
15
|
+
```
|
16
|
+
|
17
|
+
## Performance Comparison
|
18
|
+
|
19
|
+
| Style Type | Without freeze | With freeze | Difference |
|
20
|
+
|------------|----------------|-------------|------------|
|
21
|
+
| Simple | 5.44M/s | 5.26M/s | **3% slower** |
|
22
|
+
| Complex | 3.83M/s | 3.69M/s | **4% slower** |
|
23
|
+
| Hex Color | 4.66M/s | 4.56M/s | **2% slower** |
|
24
|
+
|
25
|
+
## Analysis
|
26
|
+
|
27
|
+
### Why freeze didn't help (and slightly hurt):
|
28
|
+
|
29
|
+
1. **String interpolation doesn't modify strings**: The operation `"#{@prefix}#{text}#{@reset_code}"` creates a new string without modifying the original strings, so freeze protection isn't needed.
|
30
|
+
|
31
|
+
2. **Freeze call overhead**: The `.freeze` method call during initialization adds slight overhead without providing benefits for this use case.
|
32
|
+
|
33
|
+
3. **Data.define already provides immutability**: The Style instance itself is frozen after `super`, providing sufficient protection.
|
34
|
+
|
35
|
+
4. **Memory allocation patterns unchanged**: Freeze doesn't affect how string interpolation allocates memory.
|
36
|
+
|
37
|
+
### When freeze would be beneficial:
|
38
|
+
|
39
|
+
- If we were doing destructive operations like `@prefix << something`
|
40
|
+
- If the strings were being passed to untrusted code
|
41
|
+
- If we needed to prevent accidental modification in other parts of the codebase
|
42
|
+
|
43
|
+
## Conclusion
|
44
|
+
|
45
|
+
**Remove the freeze optimization** - it provides no performance benefit and adds unnecessary overhead.
|
46
|
+
|
47
|
+
The original implementation without explicit freezing is optimal for this use case. Ruby's string interpolation is already highly optimized and doesn't require the strings to be frozen for maximum performance.
|
48
|
+
|
49
|
+
**Recommendation**: Revert to the non-frozen version for best performance.
|