GitHub

@@ -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

Read the original on github.com ↗