p99-ruby 0.0.1 → 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,149 @@
1
+ #! /usr/bin/env ruby
2
+ # ######################################################################## #
3
+ # File: examples/build_histogram.rb
4
+ #
5
+ # Purpose: Example illustrating P99::Histogram usage
6
+ #
7
+ # Created: 4th August 2026
8
+ # Updated: 4th August 2026
9
+ #
10
+ # Home: http://github.com/synesissoftware/p99.Ruby
11
+ #
12
+ # Author: Matthew Wilson
13
+ #
14
+ # Copyright (c) 2026, Matthew Wilson and Synesis Information Systems
15
+ # All rights reserved.
16
+ #
17
+ # Redistribution and use in source and binary forms, with or without
18
+ # modification, are permitted provided that the following conditions are
19
+ # met:
20
+ #
21
+ # * Redistributions of source code must retain the above copyright
22
+ # notice, this list of conditions and the following disclaimer.
23
+ #
24
+ # * Redistributions in binary form must reproduce the above copyright
25
+ # notice, this list of conditions and the following disclaimer in the
26
+ # documentation and/or other materials provided with the distribution.
27
+ #
28
+ # * Neither the names of the copyright holder nor the names of its
29
+ # contributors may be used to endorse or promote products derived from
30
+ # this software without specific prior written permission.
31
+ #
32
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
33
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
34
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
35
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
36
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
37
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
38
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
39
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
40
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
+ #
44
+ # ######################################################################## #
45
+
46
+
47
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
48
+
49
+ require 'p99'
50
+
51
+
52
+ # Deterministic LCG used by the sibling p99 language examples.
53
+ class SimpleRng
54
+
55
+ def initialize(seed)
56
+
57
+ @state = seed & P99::UINT64_MAX
58
+ end
59
+
60
+ def next
61
+
62
+ @state = (@state * 6_364_136_223_846_793_005 + 1) & P99::UINT64_MAX
63
+ end
64
+ end
65
+
66
+
67
+ def format_ns(value)
68
+
69
+ value.nil? ? 'nil' : value.to_s
70
+ end
71
+
72
+ def print_percentile(label, value)
73
+
74
+ printf(" %-18s %s ns\n", label, format_ns(value))
75
+ end
76
+
77
+ def print_histogram(histogram)
78
+
79
+ occupied = []
80
+
81
+ histogram.buckets.each_with_index do |count, index|
82
+
83
+ next if count == 0
84
+
85
+ occupied << "#{index}: #{count}"
86
+ end
87
+
88
+ puts "Histogram{"
89
+ puts " implementation: #{P99::IMPLEMENTATION}"
90
+ puts " event_count: #{histogram.event_count}"
91
+ puts " event_time_total: #{format_ns(histogram.event_time_total)}"
92
+ puts " has_overflowed: #{histogram.has_overflowed?}"
93
+ puts " min_event_time: #{format_ns(histogram.min_event_time)}"
94
+ puts " max_event_time: #{format_ns(histogram.max_event_time)}"
95
+ puts " buckets: {#{occupied.join(', ')}}"
96
+ puts "}"
97
+ end
98
+
99
+
100
+ tries = 100
101
+
102
+ if ENV.key?('P99_TRIES')
103
+
104
+ begin
105
+
106
+ tries = Integer(ENV['P99_TRIES'])
107
+ rescue ArgumentError
108
+
109
+ warn "Warning: failed to parse P99_TRIES value #{ENV['P99_TRIES'].inspect}, defaulting to 100"
110
+ tries = 100
111
+ end
112
+ end
113
+
114
+ puts "Running Histogram example with #{tries} tries..."
115
+ puts "(backend: #{P99::IMPLEMENTATION})"
116
+
117
+ histogram = P99::Histogram.new
118
+ rng = SimpleRng.new(12_345)
119
+
120
+ tries.times do
121
+
122
+ delay_us = (rng.next % 1_000) + 1
123
+ start_ns = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
124
+
125
+ sleep(delay_us / 1_000_000.0)
126
+
127
+ elapsed_ns = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - start_ns
128
+
129
+ histogram.push_event_time_ns(elapsed_ns)
130
+ end
131
+
132
+ puts
133
+ puts 'Histogram summary:'
134
+ print_histogram(histogram)
135
+
136
+ puts
137
+ puts 'Percentiles (approximated):'
138
+ print_percentile('p50 (f64):', histogram.value_at_percentile(50.0))
139
+ print_percentile('p50 (integer):', histogram.value_at_p50)
140
+ print_percentile('p75 (integer):', histogram.value_at_p75)
141
+ print_percentile('p90 (integer):', histogram.value_at_p90)
142
+ print_percentile('p95 (integer):', histogram.value_at_p95)
143
+ print_percentile('p99 (integer):', histogram.value_at_p99)
144
+ print_percentile('p99.5 (integer):', histogram.value_at_p99_5)
145
+ print_percentile('p99.9 (integer):', histogram.value_at_p99_9)
146
+ print_percentile('p99.99 (integer):', histogram.value_at_p99_99)
147
+
148
+
149
+ # ############################## end of file ############################# #
@@ -0,0 +1,54 @@
1
+ # p99.Ruby Example - **measure_batch_latency** <!-- omit in toc -->
2
+
3
+ ## Summary
4
+
5
+ Example illustrating how to measure batch-operation latency with a monotonic
6
+ clock, record the elapsed duration in nanoseconds, and print fixed percentile
7
+ results.
8
+
9
+
10
+ ## Source
11
+
12
+ See [measure_batch_latency.rb](./measure_batch_latency.rb).
13
+
14
+
15
+ ## Execution
16
+
17
+ Run with the default of 20 simulated batches:
18
+
19
+ ```bash
20
+ ruby examples/measure_batch_latency.rb
21
+ ```
22
+
23
+ Set `P99_TRIES` to measure a different number of batches:
24
+
25
+ ```bash
26
+ P99_TRIES=1000 ruby examples/measure_batch_latency.rb
27
+ ```
28
+
29
+
30
+ ## Representative output
31
+
32
+ The timing values vary by machine and scheduler. A short run produces output
33
+ like:
34
+
35
+ ```text
36
+ Measuring 3 batch operations...
37
+ batch 1: 3 items
38
+ batch 2: 2 items
39
+ batch 3: 2 items
40
+
41
+ Batch count: 3
42
+ Backend: ruby
43
+ Min latency: 258000 ns
44
+ Max latency: 398000 ns
45
+
46
+ Approximate percentiles:
47
+ p50: 258000 ns
48
+ p75: 262143 ns
49
+ p90: 262143 ns
50
+ p99: 262143 ns
51
+ ```
52
+
53
+
54
+ <!-- ########################### end of file ########################### -->
@@ -0,0 +1,87 @@
1
+ #! /usr/bin/env ruby
2
+ # ######################################################################## #
3
+ # File: examples/measure_batch_latency.rb
4
+ #
5
+ # Purpose: Example illustrating batch latency measurement
6
+ #
7
+ # Created: 30th August 2026
8
+ # Updated: 30th August 2026
9
+ #
10
+ # Home: http://github.com/synesissoftware/p99.Ruby
11
+ #
12
+ # Author: Matthew Wilson
13
+ #
14
+ # Copyright (c) 2026, Matthew Wilson and Synesis Information Systems
15
+ # All rights reserved.
16
+ #
17
+ # Redistribution and use in source and binary forms, with or without
18
+ # modification, are permitted provided that the following conditions are
19
+ # met:
20
+ #
21
+ # * Redistributions of source code must retain the above copyright
22
+ # notice, this list of conditions and the following disclaimer.
23
+ #
24
+ # * Redistributions in binary form must reproduce the above copyright
25
+ # notice, this list of conditions and the following disclaimer in the
26
+ # documentation and/or other materials provided with the distribution.
27
+ #
28
+ # * Neither the names of the copyright holder nor the names of its
29
+ # contributors may be used to endorse or promote products derived from
30
+ # this software without specific prior written permission.
31
+ #
32
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
33
+ # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
34
+ # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
35
+ # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
36
+ # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
37
+ # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, THE
38
+ # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
39
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
40
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
41
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43
+ #
44
+ # ######################################################################## #
45
+
46
+
47
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
48
+
49
+ require 'p99'
50
+
51
+
52
+ tries = Integer(ENV.fetch('P99_TRIES', 20))
53
+ rng = Random.new(12_345)
54
+ histogram = P99::Histogram.new
55
+
56
+ puts "Measuring #{tries} batch operations..."
57
+
58
+ tries.times do |index|
59
+
60
+ batch_size = rng.rand(1..4)
61
+ start_ns = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
62
+
63
+ sleep(batch_size / 10_000.0)
64
+
65
+ elapsed_ns = Process.clock_gettime(
66
+ Process::CLOCK_MONOTONIC,
67
+ :nanosecond,
68
+ ) - start_ns
69
+ histogram.push_event_time_ns(elapsed_ns)
70
+
71
+ puts " batch #{index + 1}: #{batch_size} items"
72
+ end
73
+
74
+ puts
75
+ puts "Batch count: #{histogram.event_count}"
76
+ puts "Backend: #{P99::IMPLEMENTATION}"
77
+ puts "Min latency: #{histogram.min_event_time} ns"
78
+ puts "Max latency: #{histogram.max_event_time} ns"
79
+ puts
80
+ puts 'Approximate percentiles:'
81
+ histogram.fixed_percentiles.each do |label, value|
82
+
83
+ puts " #{label}: #{value} ns"
84
+ end
85
+
86
+
87
+ # ############################## end of file ############################# #