From: "byroot (Jean Boussier) via ruby-core" Date: 2025-12-12T09:12:41+00:00 Subject: [ruby-core:124168] [Ruby Feature#21721] Allow `Queue` and `SizedQueue` to be used as LIFO queues Issue #21721 has been updated by byroot (Jean Boussier). So I did a number of other patches to squeeze some more performance out of `Monitor#synchronize` ``` ruby 4.0.0dev (2025-12-12T09:08:05Z master ff831eb057) +YJIT +PRISM [arm64-darwin25] Warming up -------------------------------------- Mutex 2.101M i/100ms Monitor 1.674M i/100ms Calculating ------------------------------------- Mutex 24.995M (� 0.4%) i/s (40.01 ns/i) - 126.063M in 5.043652s Monitor 19.830M (� 0.0%) i/s (50.43 ns/i) - 100.422M in 5.064205s ``` I think if `Monitor` wasn't defined in an extension, we could get it about as fast as Mutex. But other than that I'm kinda out of idea on how to improve perf further. But ultimately the gap on the Queue benchmark is still pretty big: ``` ruby 4.0.0dev (2025-12-12T09:08:05Z master ff831eb057) +YJIT +PRISM [arm64-darwin25] Warming up -------------------------------------- core-queue 1.451M i/100ms ar-queue 622.727k i/100ms cp gem 250.732k i/100ms Calculating ------------------------------------- core-queue 16.400M (� 1.2%) i/s (60.98 ns/i) - 82.723M in 5.044941s ar-queue 7.253M (� 0.9%) i/s (137.88 ns/i) - 36.741M in 5.066157s cp gem 2.491M (� 1.1%) i/s (401.43 ns/i) - 12.537M in 5.033115s Comparison: core-queue: 16399547.5 i/s ar-queue: 7252771.9 i/s - 2.26x slower cp gem: 2491110.9 i/s - 6.58x slower ``` ---------------------------------------- Feature #21721: Allow `Queue` and `SizedQueue` to be used as LIFO queues https://bugs.ruby-lang.org/issues/21721#change-115631 * Author: byroot (Jean Boussier) * Status: Open ---------------------------------------- ### Context Since `Queue` and `SizedQueue` gained a proper timeout mechanism, I've been wanting to use them to implement simpler and more efficient connection pools. However for connection pools you ideally want a LIFO queue because it's preferable to checkout the most recently used connection. ### Problem Both `Queue` and `SizedQueue` only support FIFO because you can only enqueue elements at the beginning of the backing array, and only dequeue at the end. `Queue#push` (aliased as `Queue#<<` and `Queue#enq`) calls `Array#unshift` on the backing array and `Queue#pop` (aliased as `Queue#deq` and `Queue#shift`) calls `Array#pop`. Hence it is impossible to use these two classes for anything other than FIFO queues. I tried to use `git blame` to see if there was a justification for this, but I ended up in a git blame loop around May 2000 https://github.com/ruby/ruby/commit/9da4f78db46764be6dae5e7e83ff48cbecb3fb23 ### Feature I'd like to introduce either of two new methods (or both) to allow for LIFO: - A method to dequeue from the beginning of the backing array (`array_shift`). - A method to enqueue from the end of the backing array (`array_push`). A difficulty I have however is that since the common `shift/pop/push` terms are already used with uncommon meaning, it's hard to come up with good names. Ideas welcome. ### Possible alternatives - Define different classes for LIFO queues - But I find that less flexible, and it means exposing new constant names in the global namespace. - Add an initializer argument to define the queue ordering, e.g. `Queue.new([], lifo: true)` - Similarly, I find this less flexible than to decide the order during enqueue/dequeue - Add an argument to `Queue#pop` and `Queue#push`, e.g. `queue.push(element, front: true)`. -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/