@@ -0,0 +1,257 @@
1+# mruby-benchmark
2+3+Benchmarking and profiling tools for mruby.
4+5+## Overview
6+7+The `mruby-benchmark` gem provides simple and lightweight benchmarking capabilities for measuring execution time and memory usage in mruby applications. It is designed for embedded systems and resource-constrained environments.
8+9+## Installation
10+11+Add the following line to your `build_config.rb`:
12+13+```ruby
14+conf.gem :core => 'mruby-benchmark'
15+```
16+17+## API
18+19+### Benchmark Module
20+21+The main interface for benchmarking operations.
22+23+#### `Benchmark.measure { block }` → Benchmark::Tms
24+25+Measures the execution time of the given block and returns a `Benchmark::Tms` object containing timing information.
26+27+```ruby
28+result = Benchmark.measure do
29+# code to benchmark
30+1000.times { "string interpolation: #{42}" }
31+end
32+33+puts result # Prints formatted timing information
34+```
35+36+#### `Benchmark.realtime { block }` → Float
37+38+Returns only the real (wall-clock) time in seconds as a floating-point number.
39+40+```ruby
41+time = Benchmark.realtime do
42+sleep(0.1)
43+end
44+45+puts "Took #{time} seconds" # => "Took 0.100... seconds"
46+```
47+48+#### `Benchmark.bm(label_width = 0) { |x| ... }`
49+50+Performs formatted benchmark comparisons with aligned output.
51+52+```ruby
53+Benchmark.bm(10) do |x|
54+ x.report("array:") { 1000.times { [1, 2, 3, 4, 5] } }
55+ x.report("hash:") { 1000.times { {a: 1, b: 2, c: 3} } }
56+ x.report("string:") { 1000.times { "hello" * 100 } }
57+end
58+```
59+60+Output example:
61+62+```
63+ user system total real
64+array: 0.010000 0.000000 0.010000 ( 0.012345)
65+hash: 0.015000 0.000000 0.015000 ( 0.016789)
66+string: 0.008000 0.000000 0.008000 ( 0.009012)
67+```
68+69+#### `Benchmark.measure(memory: true) { block }` → Benchmark::Tms
70+71+Measures both execution time and memory allocation when `memory: true` is specified.
72+73+```ruby
74+result = Benchmark.measure(memory: true) do
75+ array = []
76+1000.times { |i| array << i }
77+end
78+79+puts "Objects allocated: #{result.objects}"
80+puts "Memory used: #{result.memory} bytes"
81+```
82+83+### Benchmark::Tms Class
84+85+Holds timing measurement results. Provides methods to access individual timing components.
86+87+#### Attributes
88+89+- `utime` - User CPU time in seconds (Float)
90+- `stime` - System CPU time in seconds (Float)
91+- `cutime` - User CPU time of child processes (Float, usually 0 in mruby)
92+- `cstime` - System CPU time of child processes (Float, usually 0 in mruby)
93+- `real` - Real (wall-clock) time in seconds (Float)
94+- `objects` - Number of objects allocated (Integer, when memory tracking enabled)
95+- `memory` - Memory allocated in bytes (Integer, when memory tracking enabled)
96+97+#### Methods
98+99+##### `total` → Float
100+101+Returns the total CPU time (user + system).
102+103+```ruby
104+result = Benchmark.measure { heavy_computation }
105+puts "Total CPU time: #{result.total} seconds"
106+```
107+108+##### `to_s` → String
109+110+Returns formatted string representation of timing results.
111+112+```ruby
113+result = Benchmark.measure { sleep(0.1) }
114+puts result.to_s
115+# => " 0.000000 0.000000 0.000000 ( 0.100123)"
116+```
117+118+##### `format(format_str)` → String
119+120+Returns timing results formatted according to the format string.
121+122+Format specifiers:
123+124+- `%u` - User CPU time
125+- `%s` - System CPU time
126+- `%t` - Total CPU time
127+- `%r` - Real time
128+- `%o` - Objects allocated (if memory tracking enabled)
129+- `%m` - Memory allocated (if memory tracking enabled)
130+- `%n` - Label name
131+132+```ruby
133+result = Benchmark.measure { computation }
134+puts result.format("Real: %rs, CPU: %ts")
135+# => "Real: 0.123s, CPU: 0.100s"
136+```
137+138+### Benchmark::Report Class
139+140+Used within `Benchmark.bm` for formatted reporting.
141+142+#### `report(label = "") { block }`
143+144+Executes and reports on a single benchmark within a `bm` block.
145+146+```ruby
147+Benchmark.bm do |x|
148+ x.report("first test") { code1 }
149+ x.report("second test") { code2 }
150+end
151+```
152+153+## Usage Examples
154+155+### Basic Timing
156+157+```ruby
158+require 'benchmark'
159+160+# Simple timing
161+time = Benchmark.realtime do
162+ sum = 0
163+1000000.times { |i| sum += i }
164+end
165+puts "Calculation took #{time} seconds"
166+167+# Detailed timing
168+result = Benchmark.measure do
169+ arr = (1..10000).to_a
170+ arr.sort!
171+end
172+puts result
173+```
174+175+### Comparing Implementations
176+177+```ruby
178+require 'benchmark'
179+180+Benchmark.bm(15) do |x|
181+ x.report("Array#each:") do
182+ arr = (1..1000).to_a
183+ sum = 0
184+ arr.each { |n| sum += n }
185+end
186+187+ x.report("Array#inject:") do
188+ arr = (1..1000).to_a
189+ arr.inject(0) { |sum, n| sum + n }
190+end
191+192+ x.report("Numeric#times:") do
193+ sum = 0
194+1000.times { |n| sum += n }
195+end
196+end
197+```
198+199+### Memory Profiling
200+201+```ruby
202+require 'benchmark'
203+204+# Track memory allocation
205+result = Benchmark.measure(memory: true) do
206+ strings = []
207+1000.times { |i| strings << "string_#{i}" }
208+end
209+210+puts "Execution time: #{result.real}s"
211+puts "Objects created: #{result.objects}"
212+puts "Memory allocated: #{result.memory} bytes"
213+```
214+215+### Performance Testing in Tests
216+217+```ruby
218+# In test files
219+assert('String concatenation performance') do
220+ time = Benchmark.realtime do
221+1000.times { "hello" + "world" }
222+end
223+224+# Assert it completes within reasonable time
225+ assert_true time < 0.1, "String concat should be fast"
226+end
227+```
228+229+## Implementation Notes
230+231+### Time Measurement
232+233+mruby-benchmark uses `Process.clock_gettime` (via mruby-time) for high-resolution timing when available. User and system CPU times are measured using platform-specific APIs where available, otherwise both are set to 0.
234+235+### Memory Tracking
236+237+Memory profiling uses `ObjectSpace.count_objects` (via mruby-objectspace) to track object allocation. Memory size estimation is based on typical object overhead and may not be exact for all platforms.
238+239+### Limitations
240+241+- Child process timing (`cutime`, `cstime`) is not supported in most mruby environments and always returns 0
242+- System CPU time may not be available on all platforms
243+- Memory measurements are estimates and may not reflect actual heap usage
244+- GC activity during benchmarking may affect timing results
245+246+## Dependencies
247+248+- **mruby-time** - Required for timing measurements
249+- **mruby-objectspace** - Required for memory profiling
250+251+## License
252+253+MIT License
254+255+## Authors
256+257+mruby developers