Class: TIMEx::Composers::Adaptive::InMemoryStore
- Inherits:
-
Object
- Object
- TIMEx::Composers::Adaptive::InMemoryStore
- Defined in:
- lib/timex/composers/adaptive.rb
Overview
#estimate_ms is intentionally lock-free; it may briefly return a stale value while #record runs on another thread.
O(1) streaming quantile estimator (P² algorithm, Jain & Chlamtac 1985).
#record updates markers; #estimate_ms reads the last published estimate without locking. Markers reset every window samples.
Constant Summary collapse
- P_DEFAULT =
0.99
Instance Method Summary collapse
-
#estimate_ms ⇒ Float?
Lock-free read: #record publishes a fresh estimate at the end of every call under the mutex.
-
#initialize(window: 200, alpha: 0.2, p: P_DEFAULT) ⇒ InMemoryStore
constructor
A new instance of InMemoryStore.
-
#record(ms) ⇒ self
Records a latency sample in milliseconds and refreshes the published estimate.
Constructor Details
#initialize(window: 200, alpha: 0.2, p: P_DEFAULT) ⇒ InMemoryStore
Returns a new instance of InMemoryStore.
26 27 28 29 30 31 32 33 34 35 |
# File 'lib/timex/composers/adaptive.rb', line 26 def initialize(window: 200, alpha: 0.2, p: P_DEFAULT) @window = window @alpha = alpha @p = p @ewma = nil @count = 0 @mutex = Mutex.new @last_estimate_ms = nil reset_markers end |
Instance Method Details
#estimate_ms ⇒ Float?
Lock-free read: #record publishes a fresh estimate at the end of every call under the mutex. Readers don’t need to synchronize.
65 66 67 |
# File 'lib/timex/composers/adaptive.rb', line 65 def estimate_ms @last_estimate_ms end |
#record(ms) ⇒ self
Records a latency sample in milliseconds and refreshes the published estimate.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/timex/composers/adaptive.rb', line 41 def record(ms) @mutex.synchronize do reset_markers if @count >= @window @count += 1 @ewma = @ewma.nil? ? ms : (@alpha * ms) + ((1 - @alpha) * @ewma) if @q.nil? @initial << ms promote_to_psquare if @initial.size == 5 else psquare_step(ms) end # Publish the post-record estimate for lock-free reads. Single ivar # write is atomic in MRI; readers see either the previous or new # value, both of which are valid. @last_estimate_ms = compute_estimate end self end |