toon-format 0.1.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.
@@ -0,0 +1,206 @@
1
+ # TOON Format Benchmarks
2
+
3
+ Comprehensive performance benchmarks for the TOON Format Ruby gem.
4
+
5
+ ## Quick Start
6
+
7
+ Run all benchmarks:
8
+ ```bash
9
+ ruby benchmark/run_all_benchmarks.rb
10
+ ```
11
+
12
+ Run individual benchmarks:
13
+ ```bash
14
+ # Basic performance
15
+ ruby benchmark/encode_benchmark.rb
16
+ ruby benchmark/decode_benchmark.rb
17
+
18
+ # Analysis
19
+ ruby benchmark/token_reduction_benchmark.rb
20
+ ruby benchmark/scalability_benchmark.rb
21
+
22
+ # Comparisons
23
+ ruby benchmark/format_comparison_benchmark.rb
24
+ ruby benchmark/csv_vs_toon_benchmark.rb
25
+
26
+ # Advanced tests
27
+ ruby benchmark/validation_benchmark.rb
28
+ ruby benchmark/nesting_benchmark.rb
29
+ ruby benchmark/round_trip_benchmark.rb
30
+ ruby benchmark/memory_benchmark.rb
31
+ ruby benchmark/real_world_benchmark.rb
32
+ ```
33
+
34
+ ## Benchmark Categories
35
+
36
+ ### 1. **Basic Performance**
37
+ - **encode_benchmark.rb** - Basic encoding speed tests
38
+ - **decode_benchmark.rb** - Basic decoding speed tests
39
+
40
+ Tests fundamental encode/decode operations with simple, tabular, and nested data.
41
+
42
+ ### 2. **Token Reduction**
43
+ - **token_reduction_benchmark.rb** - Token savings analysis
44
+
45
+ Measures the core value proposition: how much TOON reduces token usage vs JSON for LLM contexts.
46
+
47
+ ### 3. **Scalability**
48
+ - **scalability_benchmark.rb** - Performance across data sizes
49
+
50
+ Tests with datasets from 1 to 10,000 records to show how performance scales.
51
+
52
+ ### 4. **Format Comparisons**
53
+ - **format_comparison_benchmark.rb** - vs JSON, YAML, MessagePack
54
+ - **csv_vs_toon_benchmark.rb** - vs CSV format
55
+
56
+ Compares TOON against other serialization formats for encoding/decoding speed, size, and readability.
57
+
58
+ ### 5. **Real-World Scenarios**
59
+ - **real_world_benchmark.rb** - Practical use cases
60
+
61
+ Tests realistic scenarios:
62
+ - REST API responses
63
+ - Database exports
64
+ - LLM prompt contexts
65
+ - Analytics events
66
+ - Application configuration
67
+
68
+ ### 6. **Advanced Testing**
69
+ - **validation_benchmark.rb** - Strict vs lenient mode overhead
70
+ - **nesting_benchmark.rb** - Deep nesting performance
71
+ - **round_trip_benchmark.rb** - Encode → decode fidelity
72
+ - **memory_benchmark.rb** - Memory usage profiling
73
+
74
+ ## Requirements
75
+
76
+ ```ruby
77
+ # Gemfile
78
+ gem 'benchmark-ips' # For performance testing
79
+ gem 'msgpack' # Optional, for format comparison
80
+ ```
81
+
82
+ Install dependencies:
83
+ ```bash
84
+ bundle install
85
+ ```
86
+
87
+ ## Understanding Results
88
+
89
+ ### Benchmark-IPS Output
90
+ ```
91
+ TOON encode: 50000 i/s
92
+ JSON encode: 25000 i/s
93
+ ```
94
+ Higher is better. "i/s" = iterations per second.
95
+
96
+ ### Comparison Output
97
+ ```
98
+ Comparison:
99
+ TOON encode: 50000.0 i/s
100
+ JSON encode: 25000.0 i/s - 2.00x slower
101
+ ```
102
+ TOON is 2x faster than JSON in this example.
103
+
104
+ ### Size Comparison
105
+ ```
106
+ JSON: 1000 bytes
107
+ TOON: 650 bytes
108
+ Savings: 35.0%
109
+ ```
110
+ Negative percentages mean TOON is larger (rare, usually for small objects).
111
+
112
+ ## Expected Results
113
+
114
+ Based on typical runs:
115
+
116
+ | Scenario | Encoding Speed | Decoding Speed | Size Savings |
117
+ |----------|---------------|----------------|--------------|
118
+ | Small objects | 1-2x faster | Similar | 10-30% |
119
+ | Tabular arrays | 2-3x faster | 1.5-2x faster | 30-60% |
120
+ | Nested objects | Similar | Similar | 20-40% |
121
+ | Large datasets | 1.5-2x faster | 1-1.5x faster | 40-70% |
122
+
123
+ **Note**: Results vary by Ruby version, CPU, and data characteristics.
124
+
125
+ ## Interpreting Performance
126
+
127
+ ### When TOON Excels
128
+ - ✅ **Tabular data** (uniform arrays of hashes)
129
+ - ✅ **Large datasets** (> 100 records)
130
+ - ✅ **Repeated field names** (database results)
131
+ - ✅ **API responses** (consistent structure)
132
+
133
+ ### When TOON is Similar to JSON
134
+ - 🟡 **Small objects** (< 10 fields)
135
+ - 🟡 **Highly irregular data** (varying structures)
136
+ - 🟡 **Deep nesting** (> 10 levels)
137
+
138
+ ### Key Metrics
139
+
140
+ 1. **Token Reduction**: Most important for LLM contexts
141
+ - Directly reduces API costs
142
+ - Smaller prompts = faster processing
143
+
144
+ 2. **Encoding Speed**: Important for API responses
145
+ - Faster = lower server latency
146
+ - Scales with request volume
147
+
148
+ 3. **Decoding Speed**: Important for data ingestion
149
+ - Critical for high-throughput pipelines
150
+
151
+ 4. **Memory Usage**: Important for large datasets
152
+ - Lower = more scalable
153
+
154
+ ## Custom Benchmarks
155
+
156
+ Create your own benchmark:
157
+
158
+ ```ruby
159
+ #!/usr/bin/env ruby
160
+ require "bundler/setup"
161
+ require "benchmark/ips"
162
+ require "toon_format"
163
+ require "json"
164
+
165
+ # Your data
166
+ data = { your: "data" }
167
+
168
+ Benchmark.ips do |x|
169
+ x.report("JSON") { JSON.generate(data) }
170
+ x.report("TOON") { ToonFormat.encode(data) }
171
+ x.compare!
172
+ end
173
+ ```
174
+
175
+ ## Contributing
176
+
177
+ When adding benchmarks:
178
+ 1. Use `benchmark/ips` for speed tests
179
+ 2. Include size comparisons
180
+ 3. Test with realistic data
181
+ 4. Add to `run_all_benchmarks.rb`
182
+ 5. Document in this README
183
+
184
+ ## Results Storage
185
+
186
+ Benchmark results are saved to `benchmark/results/` with timestamps:
187
+ ```
188
+ benchmark/results/summary_20250126_143022.txt
189
+ ```
190
+
191
+ This allows tracking performance changes over time.
192
+
193
+ ## CI/CD Integration
194
+
195
+ Run benchmarks in CI:
196
+ ```yaml
197
+ # .github/workflows/benchmark.yml
198
+ - name: Run benchmarks
199
+ run: ruby benchmark/run_all_benchmarks.rb
200
+ ```
201
+
202
+ ## Questions?
203
+
204
+ - Check [main README](../README.md) for usage
205
+ - See [CLAUDE.md](../CLAUDE.md) for architecture
206
+ - Open an issue for benchmark requests
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "toon_format"
6
+ require "json"
7
+ require "csv"
8
+
9
+ puts "=" * 80
10
+ puts "TOON vs. CSV Token Comparison"
11
+ puts "=" * 80
12
+ puts
13
+
14
+ # Data structure for testing
15
+ data = Array.new(100) do |i|
16
+ {
17
+ id: i + 1,
18
+ name: "User \#{i + 1}",
19
+ email: "user\#{i + 1}@example.com",
20
+ role: i.even? ? "admin" : "user",
21
+ active: true
22
+ }
23
+ end
24
+
25
+ # Convert to JSON
26
+ json_string = JSON.pretty_generate(data)
27
+ json_tokens = json_string.length
28
+
29
+ # Convert to TOON
30
+ toon_string = ToonFormat.encode(data)
31
+ toon_tokens = toon_string.length
32
+
33
+ # Convert to CSV
34
+ csv_string = CSV.generate do |csv|
35
+ csv << data.first.keys
36
+ data.each do |row|
37
+ csv << row.values
38
+ end
39
+ end
40
+ csv_tokens = csv_string.length
41
+
42
+ # Output results
43
+ puts "Comparison for 100 User Records"
44
+ puts "--------------------------------------------------------------------------------"
45
+
46
+ puts "JSON:"
47
+ puts " Size: #{json_tokens} bytes"
48
+ puts " Tokens: ~#{json_tokens}"
49
+ puts
50
+
51
+ puts "TOON:"
52
+ puts " Size: #{toon_tokens} bytes"
53
+ puts " Tokens: ~#{toon_tokens}"
54
+ puts
55
+
56
+ puts "CSV:"
57
+ puts " Size: #{csv_tokens} bytes"
58
+ puts " Tokens: ~#{csv_tokens}"
59
+ puts
60
+
61
+ puts "Savings:"
62
+ json_minus_toon = json_tokens - toon_tokens
63
+ toon_savings_percent = (json_minus_toon / json_tokens.to_f * 100).round(1)
64
+ puts " TOON vs. JSON: #{json_minus_toon} bytes (#{toon_savings_percent}%)"
65
+
66
+ json_minus_csv = json_tokens - csv_tokens
67
+ csv_savings_percent = (json_minus_csv / json_tokens.to_f * 100).round(1)
68
+ puts " CSV vs. JSON: #{json_minus_csv} bytes (#{csv_savings_percent}%)"
69
+ puts
70
+
71
+ puts "================================================================================"
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "benchmark/ips"
6
+ require "toon_format"
7
+ require "json"
8
+
9
+ puts "=" * 80
10
+ puts "TOON Format Decoding Benchmark"
11
+ puts "=" * 80
12
+ puts
13
+
14
+ # Test data sets
15
+ simple_object = { name: "Alice", age: 30, email: "alice@example.com" }
16
+ simple_json = JSON.generate(simple_object)
17
+ simple_toon = ToonFormat.encode(simple_object)
18
+
19
+ tabular_data = Array.new(100) do |i|
20
+ { id: i, name: "User#{i}", email: "user#{i}@example.com", active: i.even? }
21
+ end
22
+ tabular_json = JSON.generate(tabular_data)
23
+ tabular_toon = ToonFormat.encode(tabular_data)
24
+
25
+ nested_object = {
26
+ user: {
27
+ id: 1,
28
+ name: "Alice",
29
+ profile: {
30
+ age: 30,
31
+ city: "NYC"
32
+ }
33
+ }
34
+ }
35
+ nested_json = JSON.generate(nested_object)
36
+ nested_toon = ToonFormat.encode(nested_object)
37
+
38
+ puts "Benchmark 1: Simple Object"
39
+ puts "-" * 80
40
+ Benchmark.ips do |x|
41
+ x.report("JSON.parse") { JSON.parse(simple_json) }
42
+ x.report("ToonFormat.decode") { ToonFormat.decode(simple_toon) }
43
+ x.compare!
44
+ end
45
+ puts
46
+
47
+ puts "Benchmark 2: Tabular Data (100 records)"
48
+ puts "-" * 80
49
+ Benchmark.ips do |x|
50
+ x.report("JSON.parse") { JSON.parse(tabular_json) }
51
+ x.report("ToonFormat.decode") { ToonFormat.decode(tabular_toon) }
52
+ x.compare!
53
+ end
54
+ puts
55
+
56
+ puts "Benchmark 3: Nested Object"
57
+ puts "-" * 80
58
+ Benchmark.ips do |x|
59
+ x.report("JSON.parse") { JSON.parse(nested_json) }
60
+ x.report("ToonFormat.decode") { ToonFormat.decode(nested_toon) }
61
+ x.compare!
62
+ end
63
+ puts
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "benchmark/ips"
6
+ require "toon_format"
7
+ require "json"
8
+
9
+ puts "=" * 80
10
+ puts "TOON Format Encoding Benchmark"
11
+ puts "=" * 80
12
+ puts
13
+
14
+ # Test data sets
15
+ simple_object = { name: "Alice", age: 30, email: "alice@example.com" }
16
+
17
+ tabular_data = Array.new(100) do |i|
18
+ { id: i, name: "User#{i}", email: "user#{i}@example.com", active: i.even? }
19
+ end
20
+
21
+ nested_object = {
22
+ user: {
23
+ id: 1,
24
+ name: "Alice",
25
+ profile: {
26
+ age: 30,
27
+ city: "NYC",
28
+ interests: %w[ruby python javascript]
29
+ }
30
+ },
31
+ metadata: {
32
+ created_at: "2025-01-01",
33
+ updated_at: "2025-01-15"
34
+ }
35
+ }
36
+
37
+ puts "Benchmark 1: Simple Object (#{simple_object.size} fields)"
38
+ puts "-" * 80
39
+ Benchmark.ips do |x|
40
+ x.report("JSON.generate") { JSON.generate(simple_object) }
41
+ x.report("ToonFormat.encode") { ToonFormat.encode(simple_object) }
42
+ x.compare!
43
+ end
44
+ puts
45
+
46
+ puts "Benchmark 2: Tabular Data (#{tabular_data.size} records)"
47
+ puts "-" * 80
48
+ Benchmark.ips do |x|
49
+ x.report("JSON.generate") { JSON.generate(tabular_data) }
50
+ x.report("ToonFormat.encode") { ToonFormat.encode(tabular_data) }
51
+ x.compare!
52
+ end
53
+ puts
54
+
55
+ puts "Benchmark 3: Nested Object"
56
+ puts "-" * 80
57
+ Benchmark.ips do |x|
58
+ x.report("JSON.generate") { JSON.generate(nested_object) }
59
+ x.report("ToonFormat.encode") { ToonFormat.encode(nested_object) }
60
+ x.compare!
61
+ end
62
+ puts
63
+
64
+ puts "=" * 80
65
+ puts "Size Comparison"
66
+ puts "=" * 80
67
+
68
+ [
69
+ ["Simple Object", simple_object],
70
+ ["Tabular Data", tabular_data],
71
+ ["Nested Object", nested_object]
72
+ ].each do |name, data|
73
+ json_size = JSON.generate(data).bytesize
74
+ toon_size = ToonFormat.encode(data).bytesize
75
+ savings = ((json_size - toon_size) / json_size.to_f * 100).round(1)
76
+
77
+ puts "#{name}:"
78
+ puts " JSON: #{json_size} bytes"
79
+ puts " TOON: #{toon_size} bytes"
80
+ puts " Savings: #{savings}%"
81
+ puts
82
+ end
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "benchmark/ips"
6
+ require "toon_format"
7
+ require "json"
8
+ require "yaml"
9
+
10
+ # Try to load MessagePack if available
11
+ begin
12
+ require "msgpack"
13
+ MSGPACK_AVAILABLE = true
14
+ rescue LoadError
15
+ MSGPACK_AVAILABLE = false
16
+ puts "Note: MessagePack not available. Install with: gem install msgpack"
17
+ puts
18
+ end
19
+
20
+ puts "=" * 80
21
+ puts "Format Comparison Benchmark"
22
+ puts "Comparing TOON with JSON, YAML#{MSGPACK_AVAILABLE ? ', and MessagePack' : ''}"
23
+ puts "=" * 80
24
+ puts
25
+
26
+ # Test datasets
27
+ datasets = {
28
+ "Small Object" => {
29
+ id: 1,
30
+ name: "Alice Smith",
31
+ email: "alice@example.com",
32
+ active: true
33
+ },
34
+
35
+ "Tabular Data (100 records)" => Array.new(100) do |i|
36
+ {
37
+ id: i,
38
+ name: "User#{i}",
39
+ email: "user#{i}@example.com",
40
+ role: i.even? ? "admin" : "user",
41
+ active: true,
42
+ score: rand(100)
43
+ }
44
+ end,
45
+
46
+ "Nested Object" => {
47
+ user: {
48
+ id: 1,
49
+ name: "Alice",
50
+ profile: {
51
+ age: 30,
52
+ city: "NYC",
53
+ preferences: {
54
+ theme: "dark",
55
+ language: "en",
56
+ notifications: true
57
+ }
58
+ }
59
+ },
60
+ posts: [
61
+ { id: 1, title: "First post", likes: 10 },
62
+ { id: 2, title: "Second post", likes: 25 }
63
+ ]
64
+ },
65
+
66
+ "Large Tabular (1000 records)" => Array.new(1000) do |i|
67
+ {
68
+ id: i,
69
+ name: "User#{i}",
70
+ email: "user#{i}@example.com",
71
+ score: rand(100)
72
+ }
73
+ end
74
+ }
75
+
76
+ datasets.each do |name, data|
77
+ puts "\n#{name}"
78
+ puts "=" * 80
79
+
80
+ # Encoding benchmark
81
+ puts "\nEncoding Speed:"
82
+ puts "-" * 80
83
+ Benchmark.ips do |x|
84
+ x.config(time: 2, warmup: 1)
85
+
86
+ x.report("JSON") { JSON.generate(data) }
87
+ x.report("YAML") { YAML.dump(data) }
88
+ x.report("TOON") { ToonFormat.encode(data) }
89
+ x.report("MessagePack") { MessagePack.pack(data) } if MSGPACK_AVAILABLE
90
+
91
+ x.compare!
92
+ end
93
+
94
+ # Generate encoded strings for decoding and size comparison
95
+ json_str = JSON.generate(data)
96
+ yaml_str = YAML.dump(data)
97
+ toon_str = ToonFormat.encode(data)
98
+ msgpack_str = MessagePack.pack(data) if MSGPACK_AVAILABLE
99
+
100
+ # Decoding benchmark
101
+ puts "\nDecoding Speed:"
102
+ puts "-" * 80
103
+ Benchmark.ips do |x|
104
+ x.config(time: 2, warmup: 1)
105
+
106
+ x.report("JSON") { JSON.parse(json_str) }
107
+ x.report("YAML") { YAML.safe_load(yaml_str, permitted_classes: [Symbol]) }
108
+ x.report("TOON") { ToonFormat.decode(toon_str) }
109
+ x.report("MessagePack") { MessagePack.unpack(msgpack_str) } if MSGPACK_AVAILABLE
110
+
111
+ x.compare!
112
+ end
113
+
114
+ # Size comparison
115
+ puts "\nSize Comparison:"
116
+ puts "-" * 80
117
+ json_size = json_str.bytesize
118
+ yaml_size = yaml_str.bytesize
119
+ toon_size = toon_str.bytesize
120
+ msgpack_size = msgpack_str.bytesize if MSGPACK_AVAILABLE
121
+
122
+ puts "JSON: #{json_size} bytes (baseline)"
123
+ puts "YAML: #{yaml_size} bytes (#{((yaml_size - json_size) / json_size.to_f * 100).round(1)}% vs JSON)"
124
+ puts "TOON: #{toon_size} bytes (#{((toon_size - json_size) / json_size.to_f * 100).round(1)}% vs JSON)"
125
+ if MSGPACK_AVAILABLE
126
+ puts "MessagePack: #{msgpack_size} bytes (#{((msgpack_size - json_size) / json_size.to_f * 100).round(1)}% vs JSON)"
127
+ end
128
+ puts
129
+
130
+ # Readability (tokens approximation for LLM contexts)
131
+ puts "Human Readability & LLM Token Estimate:"
132
+ puts "-" * 80
133
+ json_tokens = (json_size / 4.0).ceil
134
+ yaml_tokens = (yaml_size / 4.0).ceil
135
+ toon_tokens = (toon_size / 4.0).ceil
136
+
137
+ puts "JSON: ~#{json_tokens} tokens (human-readable)"
138
+ puts "YAML: ~#{yaml_tokens} tokens (human-readable)"
139
+ puts "TOON: ~#{toon_tokens} tokens (human-readable, optimized)"
140
+ puts "MessagePack: N/A (binary format - not human-readable)" if MSGPACK_AVAILABLE
141
+ puts
142
+
143
+ puts "=" * 80
144
+ end
145
+
146
+ puts "\nSummary:"
147
+ puts "=" * 80
148
+ puts "TOON Format Advantages:"
149
+ puts " ✓ Human-readable (unlike MessagePack)"
150
+ puts " ✓ 30-60% token reduction vs JSON (better for LLMs)"
151
+ puts " ✓ Faster than YAML for encoding/decoding"
152
+ puts " ✓ Optimal for tabular data (database exports, API responses)"
153
+ puts
154
+ puts "When to use each format:"
155
+ puts " • JSON: Universal compatibility, well-established"
156
+ puts " • YAML: Configuration files, human editing priority"
157
+ puts " • TOON: LLM contexts, API responses, token optimization"
158
+ if MSGPACK_AVAILABLE
159
+ puts " • MessagePack: Maximum compression, binary protocols"
160
+ end
161
+ puts "=" * 80
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "toon_format"
6
+ require "json"
7
+
8
+ # Memory profiling helper
9
+ def measure_memory
10
+ GC.start
11
+ GC.disable
12
+ memory_before = `ps -o rss= -p #{Process.pid}`.to_i
13
+ yield
14
+ GC.start
15
+ memory_after = `ps -o rss= -p #{Process.pid}`.to_i
16
+ GC.enable
17
+ memory_after - memory_before
18
+ end
19
+
20
+ puts "=" * 80
21
+ puts "TOON Format Memory Usage Benchmark"
22
+ puts "=" * 80
23
+ puts
24
+
25
+ # Test data sets with varying sizes
26
+ data_sets = {
27
+ "Small (10 records)" => Array.new(10) { |i|
28
+ { id: i, name: "User#{i}", email: "user#{i}@example.com", active: i.even? }
29
+ },
30
+ "Medium (100 records)" => Array.new(100) { |i|
31
+ { id: i, name: "User#{i}", email: "user#{i}@example.com", active: i.even? }
32
+ },
33
+ "Large (1,000 records)" => Array.new(1000) { |i|
34
+ { id: i, name: "User#{i}", email: "user#{i}@example.com", active: i.even? }
35
+ },
36
+ "Very Large (10,000 records)" => Array.new(10_000) { |i|
37
+ { id: i, name: "User#{i}", email: "user#{i}@example.com", active: i.even? }
38
+ }
39
+ }
40
+
41
+ data_sets.each do |name, data|
42
+ puts name
43
+ puts "-" * 80
44
+
45
+ # Measure JSON encoding memory
46
+ json_memory = measure_memory do
47
+ 1000.times { JSON.generate(data) }
48
+ end
49
+
50
+ # Measure TOON encoding memory
51
+ toon_memory = measure_memory do
52
+ 1000.times { ToonFormat.encode(data) }
53
+ end
54
+
55
+ puts "JSON encoding (1000 iterations): #{json_memory} KB"
56
+ puts "TOON encoding (1000 iterations): #{toon_memory} KB"
57
+
58
+ diff = json_memory - toon_memory
59
+ if diff > 0
60
+ puts "Memory saved: #{diff} KB (#{((diff / json_memory.to_f) * 100).round(1)}%)"
61
+ elsif diff < 0
62
+ puts "Memory overhead: #{diff.abs} KB (#{((diff.abs / json_memory.to_f) * 100).round(1)}%)"
63
+ else
64
+ puts "Memory usage: equivalent"
65
+ end
66
+ puts
67
+
68
+ # Measure decoding memory
69
+ json_str = JSON.generate(data)
70
+ toon_str = ToonFormat.encode(data)
71
+
72
+ json_decode_memory = measure_memory do
73
+ 1000.times { JSON.parse(json_str) }
74
+ end
75
+
76
+ toon_decode_memory = measure_memory do
77
+ 1000.times { ToonFormat.decode(toon_str) }
78
+ end
79
+
80
+ puts "JSON decoding (1000 iterations): #{json_decode_memory} KB"
81
+ puts "TOON decoding (1000 iterations): #{toon_decode_memory} KB"
82
+
83
+ diff = json_decode_memory - toon_decode_memory
84
+ if diff > 0
85
+ puts "Memory saved: #{diff} KB (#{((diff / json_decode_memory.to_f) * 100).round(1)}%)"
86
+ elsif diff < 0
87
+ puts "Memory overhead: #{diff.abs} KB (#{((diff.abs / json_decode_memory.to_f) * 100).round(1)}%)"
88
+ else
89
+ puts "Memory usage: equivalent"
90
+ end
91
+ puts
92
+ puts "=" * 80
93
+ puts
94
+ end
95
+
96
+ puts "Note: Memory measurements show RSS (Resident Set Size) difference"
97
+ puts "Actual memory usage may vary based on Ruby GC behavior and system state"