pairing_heap 0.1.0 → 1.0.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.
data/README.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  PairingHeap is a pure Ruby priority queue implementation using a pairing heap as the underlying data structure. While a pairing heap is asymptotically less efficient than the Fibonacci heap, it is usually faster in practice. This makes it a popular choice for Prim's MST or Dijkstra's algorithm implementations.
4
4
 
5
+ PairingHeap is currently being used as the priority queue data structure in [RGL](https://github.com/monora/rgl/).
6
+
7
+ Also implementation without priority change support is provided(`SimplePairingHeap`), while the asymptotical complexity of the methods stay the same, bookkeeping of elements is not needed making, the constant smaller.
8
+
5
9
  ## Installation
6
10
 
7
11
  Add this line to your application's Gemfile:
@@ -18,10 +22,24 @@ Or install it yourself as:
18
22
 
19
23
  $ gem install pairing_heap
20
24
 
25
+
26
+ ## Documentation
27
+ https://rubydoc.info/gems/pairing_heap
28
+
21
29
  ## Usage
22
30
  ```ruby
23
31
  require 'pairing_heap'
24
32
 
33
+ # Simple PairingHeap
34
+ simple_heap = PairingHeap::SimplePairingHeap.new
35
+ simple_heap.push(:a, 1)
36
+ simple_heap.push(:b, 2)
37
+ simple_heap.push(:c, 3)
38
+ simple_heap.peek # => :a
39
+ simple_heap.peek_priority # => [:a, 1]
40
+ simple_heap.pop_priority # => [:a, 1]
41
+ simple_heap.pop # => :b
42
+
25
43
  # Min priority queue
26
44
  best_defenses = PairingHeap::MinPriorityQueue.new
27
45
  best_defenses.push('Chelsea', 24)
@@ -72,30 +90,33 @@ This API is a drop-in replacement of [lazy_priority_queue](https://github.com/ma
72
90
  * `change_priority` returns `self` instead of the first argument
73
91
  * `enqueue` returns `self` instead of the first argument
74
92
  * Queue classes are in the `PairingHeap` namespace, so `require 'pairing_heap` does not load `MinPriorityQueue` to the global scope
75
- * `top_condidition` constructor argument is removed
93
+ * `top_condition` constructor argument is removed
76
94
 
77
95
  ## Time Complexity
78
- | Operation | Time complexity | Amortized time complexity |
79
- | --------------- | --------------- | ------------------------- |
80
- | enqueue | O(1) | O(1) |
81
- | peek | O(1) | O(1) |
82
- | change_priority | O(1) | o(log n) |
83
- | dequeue | O(n) | O(log n) |
84
- | delete | O(n) | O(log n) |
96
+ | Operation | Time complexity | Amortized time complexity |
97
+ | --------------- | --------------- | ------------------------- |
98
+ | enqueue | O(1) | O(1) |
99
+ | peek | O(1) | O(1) |
100
+ | dequeue | O(n) | O(log n) |
101
+ | * change_priority | O(1) | o(log n) |
102
+ | * delete | O(n) | O(log n) |
103
+
104
+ `*` Not available in `SimplePairingHeap`
85
105
 
86
106
  ## Benchmarks
87
- I picked the two fastest pure Ruby priority queue implementations I was aware of for the comparison:
107
+ I picked the three fastest pure Ruby priority queue implementations I was aware of for the comparison:
88
108
 
89
- * [lazy_priority_queue](https://github.com/matiasbattocchia/lazy_priority_queue) that uses a lazy binomial heap. This is probably the most popular option, used for example in [RGL](https://github.com/monora/rgl/)
109
+ * [lazy_priority_queue](https://github.com/matiasbattocchia/lazy_priority_queue) that uses a lazy binomial heap. This is probably the most popular option. It was used in [RGL](https://github.com/monora/rgl/) until PairingHeap replaced it.
90
110
  * Pure Ruby implementation of Fibonacci Heap from [priority-queue](https://github.com/supertinou/priority-queue) ([link to source](https://github.com/supertinou/priority-queue/blob/master/lib/priority_queue/ruby_priority_queue.rb))
111
+ * [rb_heap](https://github.com/florian/rb_heap) that uses a binary heap. Note however that this implementation does not support change_priority operation.
91
112
 
92
- All tests except for the third one were executed by [benchmark-ips](https://github.com/evanphx/benchmark-ips) with parameters `time = 180` and `warmup = 30`, on an `Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz`.
113
+ All tests except for the third one were executed by [benchmark-ips](https://github.com/evanphx/benchmark-ips) with parameters `time = 60` and `warmup = 15`, on an `Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz`.
93
114
  ### Stress test without changing priority test(N = 1000) [source code](./test/performance.rb)
94
115
  Original performance test from [lazy_priority_queue](https://github.com/matiasbattocchia/lazy_priority_queue)
95
116
  > A stress test of 1,000,000 operations: starting with 1,000 pushes/0 pops, following 999 pushes/1 pop, and so on till 0 pushes/1000 pops.
96
117
  <table>
97
118
  <tr>
98
- <th colspan="4">ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]</th>
119
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]</th>
99
120
  </tr>
100
121
  <tr>
101
122
  <th>Library</th>
@@ -104,25 +125,37 @@ Original performance test from [lazy_priority_queue](https://github.com/matiasba
104
125
  <th>Iterations per second</th>
105
126
  </tr>
106
127
  <tr>
107
- <td>pairing_heap</td>
128
+ <td>pairing_heap (SimplePairingHeap)</td>
129
+ <td>23</td>
130
+ <td>62.014773</td>
131
+ <td>0.371</td>
132
+ </tr>
133
+ <tr>
134
+ <td>pairing_heap (PairingHeap)</td>
135
+ <td>16</td>
136
+ <td>63.135240</td>
137
+ <td>0.253(1.46x slower)</td>
138
+ </tr>
139
+ <tr>
140
+ <td>rb_heap</td>
108
141
  <td>14</td>
109
- <td>60.564595</td>
110
- <td>0.231</td>
142
+ <td>61.123304</td>
143
+ <td>0.229(1.62x slower)</td>
111
144
  </tr>
112
145
  <tr>
113
146
  <td>lazy_priority_queue</td>
114
- <td>8</td>
115
- <td>62.489819</td>
116
- <td>0.128(1.81x slower)</td>
147
+ <td>10</td>
148
+ <td>66.208647</td>
149
+ <td>0.151(2.46x slower)</td>
117
150
  </tr>
118
151
  <tr>
119
152
  <td>Fibonacci</td>
120
153
  <td>8</td>
121
- <td>68.719194</td>
122
- <td>0.116(1.99x slower)</td>
154
+ <td>66.353147</td>
155
+ <td>0.121(3.08x slower)</td>
123
156
  </tr>
124
157
  <tr>
125
- <th colspan="4">jruby 9.2.14.0 (2.5.7) 2020-12-08 ebe64bafb9 OpenJDK 64-Bit Server VM 15.0.2+7 on 15.0.2+7 +jit [darwin-x86_64]</th>
158
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) +YJIT [x86_64-darwin21]</th>
126
159
  </tr>
127
160
  <tr>
128
161
  <th>Library</th>
@@ -131,30 +164,120 @@ Original performance test from [lazy_priority_queue](https://github.com/matiasba
131
164
  <th>Iterations per second</th>
132
165
  </tr>
133
166
  <tr>
134
- <td>pairing_heap</td>
167
+ <td>pairing_heap (SimplePairingHeap)</td>
168
+ <td>25</td>
169
+ <td>60.423579</td>
170
+ <td>0.414</td>
171
+ </tr>
172
+ <tr>
173
+ <td>rb_heap</td>
174
+ <td>19</td>
175
+ <td>60.869907</td>
176
+ <td>0.312(1.33x slower)</td>
177
+ </tr>
178
+ <tr>
179
+ <td>pairing_heap (PairingHeap)</td>
135
180
  <td>17</td>
136
- <td>61.195794</td>
137
- <td>0.278</td>
181
+ <td>61.389127</td>
182
+ <td>0.277(1.49x slower)</td>
138
183
  </tr>
139
184
  <tr>
140
- <td>lazy_priority_queue</td>
185
+ <td>Fibonacci</td>
141
186
  <td>14</td>
142
- <td>64.375927</td>
143
- <td>0.218(1.28x slower)</td>
187
+ <td>64.417807</td>
188
+ <td>0.217(1.90x slower)</td>
189
+ </tr>
190
+ <tr>
191
+ <td>lazy_priority_queue</td>
192
+ <td>11</td>
193
+ <td>63.151856</td>
194
+ <td>0.174(2.38x slower)</td>
195
+ </tr>
196
+ <tr>
197
+ <th colspan="4">jruby 9.3.7.0 (2.6.8) 2022-08-16 c79ef237e0 OpenJDK 64-Bit Server VM 17.0.2+8-86 on 17.0.2+8-86 +indy +jit [x86_64-darwin]</th>
198
+ </tr>
199
+ <tr>
200
+ <th>Library</th>
201
+ <th>Iterations</th>
202
+ <th>Seconds</th>
203
+ <th>Iterations per second</th>
204
+ </tr>
205
+ <tr>
206
+ <td>pairing_heap (SimplePairingHeap)</td>
207
+ <td>47</td>
208
+ <td>60.391633</td>
209
+ <td>0.778</td>
210
+ </tr>
211
+ <tr>
212
+ <td>rb_heap</td>
213
+ <td>34</td>
214
+ <td>60.878639</td>
215
+ <td>0.559(1.39x slower)</td>
216
+ </tr>
217
+ <tr>
218
+ <td>pairing_heap (PairingHeap)</td>
219
+ <td>32</td>
220
+ <td>61.211985</td>
221
+ <td>0.523(1.49x slower)</td>
144
222
  </tr>
145
223
  <tr>
146
224
  <td>Fibonacci</td>
147
- <td>9</td>
148
- <td>67.415358</td>
149
- <td>0.134(2.08x slower)</td>
225
+ <td>23</td>
226
+ <td>60.297670</td>
227
+ <td>0.382(2.04x slower)</td>
228
+ </tr>
229
+ <tr>
230
+ <td>lazy_priority_queue</td>
231
+ <td>23</td>
232
+ <td>61.973538</td>
233
+ <td>0.371(2.10x slower)</td>
234
+ </tr>
235
+ <tr>
236
+ <th colspan="4">truffleruby 22.2.0, like ruby 3.0.3, GraalVM CE JVM [x86_64-darwin]</th>
237
+ </tr>
238
+ <tr>
239
+ <th>Library</th>
240
+ <th>Iterations</th>
241
+ <th>Seconds</th>
242
+ <th>Iterations per second</th>
243
+ </tr>
244
+ <tr>
245
+ <td>pairing_heap (SimplePairingHeap)</td>
246
+ <td>206</td>
247
+ <td>60.191686</td>
248
+ <td>3.433</td>
249
+ </tr>
250
+ <tr>
251
+ <td>rb_heap</td>
252
+ <td>97</td>
253
+ <td>60.134011</td>
254
+ <td>1.614(1.93x slower)</td>
255
+ </tr>
256
+ <tr>
257
+ <td>pairing_heap (PairingHeap)</td>
258
+ <td>85</td>
259
+ <td>60.193608s</td>
260
+ <td>1.434(2.40x slower)</td>
261
+ </tr>
262
+ <tr>
263
+ <td>lazy_priority_queue</td>
264
+ <td>19</td>
265
+ <td>63.212429</td>
266
+ <td>0.301(11.45x slower)</td>
267
+ </tr>
268
+ <tr>
269
+ <td>Fibonacci</td>
270
+ <td>2</td>
271
+ <td>83.508571</td>
272
+ <td>0.024(143.70x slower)</td>
150
273
  </tr>
151
274
  </table>
152
275
 
153
276
  ### Stress test with changing priority(N = 1000) [source code](./test/performance_with_change_priority.rb)
154
- A stress test of 2,000,000 operations: starting with 1,000 pushes/1000 change_priorities/0 pops, following 999 pushes/999 change_priorities/1 pop, and so on till 0 pushes/0 change_priorities/1000 pops.
277
+ A stress test of 1,501,500 operations: starting with 1,000 pushes/1000 change_priorities/0 pops, following 999 pushes/999 change_priorities/1 pop, and so on till 0 pushes/0 change_priorities/1000 pops.
155
278
  <table>
156
279
  <tr>
157
- <th colspan="4">ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]</th>
280
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]</th>
158
281
  </tr>
159
282
  <tr>
160
283
  <th>Library</th>
@@ -164,24 +287,24 @@ A stress test of 2,000,000 operations: starting with 1,000 pushes/1000 change_pr
164
287
  </tr>
165
288
  <tr>
166
289
  <td>pairing_heap</td>
167
- <td>13</td>
168
- <td>60.280165</td>
169
- <td>0.216</td>
290
+ <td>15</td>
291
+ <td>62.946988</td>
292
+ <td>0.238</td>
170
293
  </tr>
171
294
  <tr>
172
295
  <td>lazy_priority_queue</td>
173
- <td>8</td>
174
- <td>67.414861s</td>
175
- <td>0.119(1.82x slower)</td>
296
+ <td>9</td>
297
+ <td>61.876691</td>
298
+ <td>0.145(1.64x slower)</td>
176
299
  </tr>
177
300
  <tr>
178
301
  <td>Fibonacci</td>
179
- <td>7</td>
180
- <td>61.067436</td>
181
- <td>0.115(1.88x slower)</td>
302
+ <td>8</td>
303
+ <td>67.809982</td>
304
+ <td>0.118(2.02x slower)</td>
182
305
  </tr>
183
306
  <tr>
184
- <th colspan="4">jruby 9.2.14.0 (2.5.7) 2020-12-08 ebe64bafb9 OpenJDK 64-Bit Server VM 15.0.2+7 on 15.0.2+7 +jit [darwin-x86_64]</th>
307
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) +YJIT [x86_64-darwin21]</th>
185
308
  </tr>
186
309
  <tr>
187
310
  <th>Library</th>
@@ -192,28 +315,111 @@ A stress test of 2,000,000 operations: starting with 1,000 pushes/1000 change_pr
192
315
  <tr>
193
316
  <td>pairing_heap</td>
194
317
  <td>16</td>
195
- <td>62.519677</td>
318
+ <td>62.576693</td>
196
319
  <td>0.256</td>
197
320
  </tr>
198
321
  <tr>
199
- <td>lazy_priority_queue</td>
322
+ <td>Fibonacci</td>
200
323
  <td>13</td>
201
- <td>63.832733</td>
202
- <td>0.204(1.26x slower)</td>
324
+ <td>63.164614</td>
325
+ <td>0.206(1.24x slower)</td>
326
+ </tr>
327
+ <tr>
328
+ <td>lazy_priority_queue</td>
329
+ <td>10</td>
330
+ <td>63.172995s</td>
331
+ <td>0.158(1.62x slower)</td>
332
+ </tr>
333
+ <tr>
334
+ <th colspan="4">jruby 9.3.7.0 (2.6.8) 2022-08-16 c79ef237e0 OpenJDK 64-Bit Server VM 17.0.2+8-86 on 17.0.2+8-86 +indy +jit [x86_64-darwin]</th>
335
+ </tr>
336
+ <tr>
337
+ <th>Library</th>
338
+ <th>Iterations</th>
339
+ <th>Seconds</th>
340
+ <th>Iterations per second</th>
341
+ </tr>
342
+ <tr>
343
+ <td>pairing_heap</td>
344
+ <td>28</td>
345
+ <td>60.280368</td>
346
+ <td>0.465</td>
203
347
  </tr>
204
348
  <tr>
205
349
  <td>Fibonacci</td>
206
- <td>8</td>
207
- <td>60.250658</td>
208
- <td>0.133(1.93x slower)</td>
350
+ <td>22</td>
351
+ <td>61.405561</td>
352
+ <td>0.465(1.30x slower)</td>
353
+ </tr>
354
+ <tr>
355
+ <td>lazy_priority_queue</td>
356
+ <td>20</td>
357
+ <td>60.397535</td>
358
+ <td>0.331(1.40x slower)</td>
359
+ </tr>
360
+ <tr>
361
+ <th colspan="4">truffleruby 22.2.0, like ruby 3.0.3, GraalVM CE JVM [x86_64-darwin]</th>
362
+ </tr>
363
+ <tr>
364
+ <th>Library</th>
365
+ <th>Iterations</th>
366
+ <th>Seconds</th>
367
+ <th>Iterations per second</th>
368
+ </tr>
369
+ <tr>
370
+ <td>pairing_heap</td>
371
+ <td>70</td>
372
+ <td>60.663184</td>
373
+ <td>1.160</td>
374
+ </tr>
375
+ <tr>
376
+ <td>lazy_priority_queue</td>
377
+ <td>23</td>
378
+ <td>60.474587</td>
379
+ <td>0.382(3.04x slower)</td>
380
+ </tr>
381
+ <tr>
382
+ <td>Fibonacci</td>
383
+ <td>2</td>
384
+ <td>74.873854</td>
385
+ <td>0.027(43.44x slower)</td>
209
386
  </tr>
210
387
  </table>
211
388
 
212
- ### Stress test with changing priority(N = 10) [source code](./test/performance_with_change_priority.rb)
213
- A stress test of 200 operations: starting with 10 pushes/10 change_priorities/0 pops, following 9 pushes/9 change_priorities/1 pop, and so on till 0 pushes/0 change_priorities/10 pops.
389
+ ### Stress test with changing priority or push/pop(test ignored in summary) [source code](./test/performance_pop_versus_change_priority.rb)
390
+ Start with 500 pushes, then:
391
+ * If queue supports changing priority 500 change_priority calls, then 500 pops
392
+ * If does not support changing priority 500 push calls, then 1000 pops
214
393
  <table>
215
394
  <tr>
216
- <th colspan="4">ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]</th>
395
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]</th>
396
+ </tr>
397
+ <tr>
398
+ <th>Library</th>
399
+ <th>Iterations per second</th>
400
+ </tr>
401
+ <tr>
402
+ <td>pairing_heap (PairingHeap)</td>
403
+ <td>436.4</td>
404
+ </tr>
405
+ <tr>
406
+ <td>lazy_priority_queue</td>
407
+ <td>380.2(1.94x slower)</td>
408
+ </tr>
409
+ <tr>
410
+ <td>pairing_heap (SimplePairingHeap)</td>
411
+ <td>339.9.02(2.17x slower)</td>
412
+ </tr>
413
+ <tr>
414
+ <td>Fibonacci</td>
415
+ <td>313.9(2.35x slower)</td>
416
+ </tr>
417
+ <tr>
418
+ <td>rb_heap</td>
419
+ <td>194.7(3.78 slower)</td>
420
+ </tr>
421
+ <tr>
422
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) +YJIT [x86_64-darwin21]</th>
217
423
  </tr>
218
424
  <tr>
219
425
  <th>Library</th>
@@ -221,41 +427,84 @@ A stress test of 200 operations: starting with 10 pushes/10 change_priorities/0
221
427
  </tr>
222
428
  <tr>
223
429
  <td>pairing_heap</td>
224
- <td>5991.2</td>
430
+ <td>854.6</td>
225
431
  </tr>
226
432
  <tr>
227
433
  <td>Fibonacci</td>
228
- <td>3803.5(1.58x slower)</td>
434
+ <td>651.3(1.31x slower)</td>
229
435
  </tr>
230
436
  <tr>
231
437
  <td>lazy_priority_queue</td>
232
- <td>3681.9(1.64x slower)</td>
438
+ <td>453.6(1.88x slower)</td>
439
+ </tr>
440
+ <tr>
441
+ <td>pairing_heap(SimplePairingHeap)</td>
442
+ <td>390.9(2.19x slower)</td>
443
+ </tr>
444
+ <tr>
445
+ <td>rb_heap</td>
446
+ <td>268.8(3.18x slower)</td>
233
447
  </tr>
234
448
  <tr>
235
- <th colspan="4">jruby 9.2.14.0 (2.5.7) 2020-12-08 ebe64bafb9 OpenJDK 64-Bit Server VM 15.0.2+7 on 15.0.2+7 +jit [darwin-x86_64]</th>
449
+ <th colspan="4">jruby 9.3.7.0 (2.6.8) 2022-08-16 c79ef237e0 OpenJDK 64-Bit Server VM 17.0.2+8-86 on 17.0.2+8-86 +indy +jit [x86_64-darwin]</th>
236
450
  </tr>
237
451
  <tr>
238
452
  <th>Library</th>
239
453
  <th>Iterations per second</th>
240
454
  </tr>
241
455
  <tr>
242
- <td>pairing_heap</td>
243
- <td>6784.3</td>
456
+ <td>pairing_heap(PairingHeap)</td>
457
+ <td>1591</td>
458
+ </tr>
459
+ <tr>
460
+ <td>Fibonacci</td>
461
+ <td>1092(1.46x slower)</td>
244
462
  </tr>
245
463
  <tr>
246
464
  <td>lazy_priority_queue</td>
247
- <td>6044.5(1.12x slower)</td>
465
+ <td>986(1.61x slower)</td>
466
+ </tr>
467
+ <tr>
468
+ <td>pairing_heap(SimplePairingHeap)</td>
469
+ <td>562(2.37x slower)</td>
470
+ </tr>
471
+ <tr>
472
+ <td>rb_heap</td>
473
+ <td>623(2.55x slower)</td>
474
+ </tr>
475
+ <tr>
476
+ <th colspan="4">truffleruby 22.2.0, like ruby 3.0.3, GraalVM CE JVM [x86_64-darwin]</th>
477
+ </tr>
478
+ <tr>
479
+ <th>Library</th>
480
+ <th>Iterations per second</th>
481
+ </tr>
482
+ <tr>
483
+ <td>pairing_heap(PairingHeap)</td>
484
+ <td>7404</td>
485
+ </tr>
486
+ <tr>
487
+ <td>pairing_heap(SimplePairingHeap)</td>
488
+ <td>5104(1.45x slower)</td>
489
+ </tr>
490
+ <tr>
491
+ <td>rb_heap</td>
492
+ <td>1575(4.70x slower)</td>
248
493
  </tr>
249
494
  <tr>
250
495
  <td>Fibonacci</td>
251
- <td>4070.5(1.67x slower)</td>
496
+ <td>1258(5.88x slower)</td>
497
+ </tr>
498
+ <tr>
499
+ <td>lazy_priority_queue</td>
500
+ <td>1004(7.38x slower)</td>
252
501
  </tr>
253
502
  </table>
254
503
 
255
504
  ### Dijkstra's algorithm with RGL [source code](./test/performance_rgl.rb)
256
505
  <table>
257
506
  <tr>
258
- <th colspan="4">ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]</th>
507
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]</th>
259
508
  </tr>
260
509
  <tr>
261
510
  <th>Library</th>
@@ -265,24 +514,78 @@ A stress test of 200 operations: starting with 10 pushes/10 change_priorities/0
265
514
  </tr>
266
515
  <tr>
267
516
  <td>pairing_heap</td>
517
+ <td>9</td>
518
+ <td>61.469343</td>
519
+ <td>0.116</td>
520
+ </tr>
521
+ <tr>
522
+ <td>lazy_priority_queue</td>
523
+ <td>8</td>
524
+ <td>64.312672</td>
525
+ <td>0.125(1.18x slower)</td>
526
+ </tr>
527
+ <tr>
528
+ <td>Fibonacci</td>
268
529
  <td>7</td>
269
- <td>64.768526</td>
270
- <td>0.108</td>
530
+ <td>60.555716</td>
531
+ <td>0.116(1.27x slower)</td>
532
+ </tr>
533
+ <tr>
534
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) +YJIT [x86_64-darwin21]</th>
535
+ </tr>
536
+ <tr>
537
+ <th>Library</th>
538
+ <th>Iterations</th>
539
+ <th>Seconds</th>
540
+ <th>Iterations per second</th>
541
+ </tr>
542
+ <tr>
543
+ <td>pairing_heap</td>
544
+ <td>10</td>
545
+ <td>65.160945s</td>
546
+ <td>0.154</td>
547
+ </tr>
548
+ <tr>
549
+ <td>Fibonacci</td>
550
+ <td>9</td>
551
+ <td>61.950587</td>
552
+ <td>0.145(1.06x slower)</td>
271
553
  </tr>
272
554
  <tr>
273
555
  <td>lazy_priority_queue</td>
274
- <td>6</td>
275
- <td>63.278091</td>
276
- <td>0.095(1.14x slower)</td>
556
+ <td>9</td>
557
+ <td>66.592123</td>
558
+ <td>0.135(1.14x slower)</td>
559
+ </tr>
560
+ <tr>
561
+ <th colspan="4">jruby 9.3.7.0 (2.6.8) 2022-08-16 c79ef237e0 OpenJDK 64-Bit Server VM 17.0.2+8-86 on 17.0.2+8-86 +indy +jit [x86_64-darwin]</th>
562
+ </tr>
563
+ <tr>
564
+ <th>Library</th>
565
+ <th>Iterations</th>
566
+ <th>Seconds</th>
567
+ <th>Iterations per second</th>
568
+ </tr>
569
+ <tr>
570
+ <td>lazy_priority_queue</td>
571
+ <td>20</td>
572
+ <td>61.149944</td>
573
+ <td>0.328</td>
574
+ </tr>
575
+ <tr>
576
+ <td>pairing_heap</td>
577
+ <td>20</td>
578
+ <td>61.210225s</td>
579
+ <td>0.328</td>
277
580
  </tr>
278
581
  <tr>
279
582
  <td>Fibonacci</td>
280
- <td>6</td>
281
- <td>65.898081</td>
282
- <td>0.091(1.19x slower)</td>
583
+ <td>18</td>
584
+ <td>62.330882</td>
585
+ <td>0.292(1.12x slower)</td>
283
586
  </tr>
284
587
  <tr>
285
- <th colspan="4">jruby 9.2.14.0 (2.5.7) 2020-12-08 ebe64bafb9 OpenJDK 64-Bit Server VM 15.0.2+7 on 15.0.2+7 +jit [darwin-x86_64]</th>
588
+ <th colspan="4">truffleruby 22.2.0, like ruby 3.0.3, GraalVM CE JVM [x86_64-darwin]</th>
286
589
  </tr>
287
590
  <tr>
288
591
  <th>Library</th>
@@ -292,28 +595,29 @@ A stress test of 200 operations: starting with 10 pushes/10 change_priorities/0
292
595
  </tr>
293
596
  <tr>
294
597
  <td>pairing_heap</td>
295
- <td>12</td>
296
- <td>60.277567</td>
297
- <td>0.199</td>
598
+ <td>59</td>
599
+ <td>60.053843</td>
600
+ <td>0.991</td>
298
601
  </tr>
299
602
  <tr>
300
603
  <td>lazy_priority_queue</td>
301
- <td>12</td>
302
- <td>61.238395</td>
303
- <td>0.196(1.02x slower)</td>
604
+ <td>34</td>
605
+ <td>60.586461</td>
606
+ <td>0.563(1.76x slower)</td>
304
607
  </tr>
305
608
  <tr>
306
609
  <td>Fibonacci</td>
307
- <td>10</td>
308
- <td>62.687378</td>
309
- <td>0.160(1.25x slower)</td>
610
+ <td>31</td>
611
+ <td>60.633711</td>
612
+ <td>0.520(1.90x slower)</td>
310
613
  </tr>
311
614
  </table>
312
615
 
313
616
  ### Simple Dijkstra's algorithm implementation [source code](./test/performance_dijkstra.rb)
617
+ Heaps that support change_priority operation use it. Heaps that do not support it use dijkstra implementation that do not rely on change_priority instead and do additional pops and pushes instead(see Dijkstra-NoDec from [Priority Queues and Dijkstra’s Algorithm](https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf)).
314
618
  <table>
315
619
  <tr>
316
- <th colspan="4">ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]</th>
620
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]</th>
317
621
  </tr>
318
622
  <tr>
319
623
  <th>Library</th>
@@ -322,25 +626,76 @@ A stress test of 200 operations: starting with 10 pushes/10 change_priorities/0
322
626
  <th>Iterations per second</th>
323
627
  </tr>
324
628
  <tr>
325
- <td>pairing_heap</td>
326
- <td>20</td>
327
- <td>60.028380</td>
328
- <td>0.334</td>
629
+ <td>pairing_heap (SimplePairingHeap)</td>
630
+ <td>28</td>
631
+ <td>62.100299</td>
632
+ <td>0.451</td>
633
+ </tr>
634
+ <tr>
635
+ <td>pairing_heap (PairingHeap)</td>
636
+ <td>23</td>
637
+ <td>60.633153</td>
638
+ <td>0.380(1.19x slower)</td>
639
+ </tr>
640
+ <tr>
641
+ <td>rb_heap</td>
642
+ <td>14</td>
643
+ <td>62.019763</td>
644
+ <td>0.226(2.00x slower)</td>
645
+ </tr>
646
+ <tr>
647
+ <td>lazy_priority_queue</td>
648
+ <td>11</td>
649
+ <td>63.105064s</td>
650
+ <td>0.174(2.58x slower)</td>
329
651
  </tr>
330
652
  <tr>
331
653
  <td>Fibonacci</td>
332
654
  <td>10</td>
333
- <td>64.471303</td>
334
- <td>0.155(2.14x slower)</td>
655
+ <td>64.407187</td>
656
+ <td>0.155(2.90x slower)</td>
657
+ </tr>
658
+ <tr>
659
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) +YJIT [x86_64-darwin21]</th>
660
+ </tr>
661
+ <tr>
662
+ <th>Library</th>
663
+ <th>Iterations</th>
664
+ <th>Seconds</th>
665
+ <th>Iterations per second</th>
666
+ </tr>
667
+ <tr>
668
+ <td>pairing_heap (SimplePairingHeap)</td>
669
+ <td>32</td>
670
+ <td>61.289321</td>
671
+ <td>0.522</td>
672
+ </tr>
673
+ <tr>
674
+ <td>pairing_heap (PairingHeap)</td>
675
+ <td>26</td>
676
+ <td>60.657625</td>
677
+ <td>0.429(1.22x slower)</td>
678
+ </tr>
679
+ <tr>
680
+ <td>rb_heap</td>
681
+ <td>19</td>
682
+ <td>60.710888s</td>
683
+ <td>0.313(1.67x slower)</td>
684
+ </tr>
685
+ <tr>
686
+ <td>Fibonacci</td>
687
+ <td>19</td>
688
+ <td>61.471203</td>
689
+ <td>0.310(1.69x slower)</td>
335
690
  </tr>
336
691
  <tr>
337
692
  <td>lazy_priority_queue</td>
338
- <td>9</td>
339
- <td>65.986618</td>
340
- <td>0.136(2.45x slower)</td>
693
+ <td>12</td>
694
+ <td>60.125779</td>
695
+ <td>0.200(2.61x slower)</td>
341
696
  </tr>
342
697
  <tr>
343
- <th colspan="4">jruby 9.2.14.0 (2.5.7) 2020-12-08 ebe64bafb9 OpenJDK 64-Bit Server VM 15.0.2+7 on 15.0.2+7 +jit [darwin-x86_64]</th>
698
+ <th colspan="4">jruby 9.3.7.0 (2.6.8) 2022-08-16 c79ef237e0 OpenJDK 64-Bit Server VM 17.0.2+8-86 on 17.0.2+8-86 +indy +jit [x86_64-darwin]</th>
344
699
  </tr>
345
700
  <tr>
346
701
  <th>Library</th>
@@ -349,29 +704,119 @@ A stress test of 200 operations: starting with 10 pushes/10 change_priorities/0
349
704
  <th>Iterations per second</th>
350
705
  </tr>
351
706
  <tr>
352
- <td>pairing_heap</td>
353
- <td>21</td>
354
- <td>61.727259</td>
355
- <td>0.340</td>
707
+ <td>pairing_heap (SimplePairingHeap)</td>
708
+ <td>46</td>
709
+ <td>61.226924</td>
710
+ <td>0.753</td>
711
+ </tr>
712
+ <tr>
713
+ <td>rb_heap</td>
714
+ <td>38</td>
715
+ <td>60.563995</td>
716
+ <td>0.628(1.20x slower)</td>
717
+ </tr>
718
+ <tr>
719
+ <td>pairing_heap (PairingHeap)</td>
720
+ <td>37</td>
721
+ <td>60.928350</td>
722
+ <td>0.608(1.24x slower)</td>
723
+ </tr>
724
+ <tr>
725
+ <td>Fibonacci</td>
726
+ <td>28</td>
727
+ <td>61.136970</td>
728
+ <td>0.461(1.63x slower)</td>
356
729
  </tr>
357
730
  <tr>
358
731
  <td>lazy_priority_queue</td>
359
- <td>14</td>
360
- <td>63.436863</td>
361
- <td>0.221(1.54x slower)</td>
732
+ <td>22</td>
733
+ <td>62.214796</td>
734
+ <td>0.354(2.13x slower)</td>
735
+ </tr>
736
+ <tr>
737
+ <th colspan="4">truffleruby 22.2.0, like ruby 3.0.3, GraalVM CE JVM [x86_64-darwin]</th>
738
+ </tr>
739
+ <tr>
740
+ <th>Library</th>
741
+ <th>Iterations</th>
742
+ <th>Seconds</th>
743
+ <th>Iterations per second</th>
744
+ </tr>
745
+ <tr>
746
+ <td>pairing_heap (SimplePairingHeap)</td>
747
+ <td>176</td>
748
+ <td>60.029817</td>
749
+ <td>3.006</td>
750
+ </tr>
751
+ <tr>
752
+ <td>pairing_heap (PairingHeap)</td>
753
+ <td>124</td>
754
+ <td>60.366607</td>
755
+ <td>2.078(1.45x slower)</td>
756
+ </tr>
757
+ <tr>
758
+ <td>rb_heap</td>
759
+ <td>95</td>
760
+ <td>60.021043</td>
761
+ <td>1.585(1.90x slower)</td>
362
762
  </tr>
363
763
  <tr>
364
764
  <td>Fibonacci</td>
365
- <td>10</td>
366
- <td>62.447662</td>
367
- <td>0.160(2.12x slower)</td>
765
+ <td>38</td>
766
+ <td>60.020976</td>
767
+ <td>0.636(4.72x slower)</td>
768
+ </tr>
769
+ <tr>
770
+ <td>lazy_priority_queue</td>
771
+ <td>27</td>
772
+ <td>61.349925</td>
773
+ <td>0.445(6.75x slower)</td>
368
774
  </tr>
369
775
  </table>
370
776
 
371
777
  ### Summary
778
+ #### Change priority required
372
779
  <table>
373
780
  <tr>
374
- <th colspan="4">ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]</th>
781
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]</th>
782
+ </tr>
783
+ <tr>
784
+ <th>Library</th>
785
+ <th>Slower geometric mean</th>
786
+ </tr>
787
+ <tr>
788
+ <td>pairing_heap</td>
789
+ <td>1</td>
790
+ </tr>
791
+ <tr>
792
+ <td>lazy_priority_queue</td>
793
+ <td>1.688x slower</td>
794
+ </tr>
795
+ <tr>
796
+ <td>Fibonacci</td>
797
+ <td>1.987x slower</td>
798
+ </tr>
799
+ <tr>
800
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) +YJIT [x86_64-darwin21]</th>
801
+ </tr>
802
+ <tr>
803
+ <th>Library</th>
804
+ <th>Slower geometric mean</th>
805
+ </tr>
806
+ <tr>
807
+ <td>pairing_heap</td>
808
+ <td>1</td>
809
+ </tr>
810
+ <tr>
811
+ <td>Fibonacci</td>
812
+ <td>1.256x slower</td>
813
+ </tr>
814
+ <tr>
815
+ <td>lazy_priority_queue</td>
816
+ <td>1.648x slower</td>
817
+ </tr>
818
+ <tr>
819
+ <th colspan="4">jruby 9.3.7.0 (2.6.8) 2022-08-16 c79ef237e0 OpenJDK 64-Bit Server VM 17.0.2+8-86 on 17.0.2+8-86 +indy +jit [x86_64-darwin]</th>
375
820
  </tr>
376
821
  <tr>
377
822
  <th>Library</th>
@@ -383,14 +828,14 @@ A stress test of 200 operations: starting with 10 pushes/10 change_priorities/0
383
828
  </tr>
384
829
  <tr>
385
830
  <td>Fibonacci</td>
386
- <td>1.720x slower</td>
831
+ <td>1.327x slower</td>
387
832
  </tr>
388
833
  <tr>
389
834
  <td>lazy_priority_queue</td>
390
- <td>1.721x slower</td>
835
+ <td>1.383x slower</td>
391
836
  </tr>
392
837
  <tr>
393
- <th colspan="4">jruby 9.2.14.0 (2.5.7) 2020-12-08 ebe64bafb9 OpenJDK 64-Bit Server VM 15.0.2+7 on 15.0.2+7 +jit [darwin-x86_64]</th>
838
+ <th colspan="4">truffleruby 22.2.0, like ruby 3.0.3, GraalVM CE JVM [x86_64-darwin]</th>
394
839
  </tr>
395
840
  <tr>
396
841
  <th>Library</th>
@@ -402,12 +847,123 @@ A stress test of 200 operations: starting with 10 pushes/10 change_priorities/0
402
847
  </tr>
403
848
  <tr>
404
849
  <td>lazy_priority_queue</td>
405
- <td>1.23x slower</td>
850
+ <td>3.878x slower</td>
851
+ </tr>
852
+ <tr>
853
+ <td>Fibonacci</td>
854
+ <td>9.889x slower</td>
855
+ </tr>
856
+ </table>
406
857
 
858
+ #### Change priority not required
859
+ <table>
860
+ <tr>
861
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-darwin21]</th>
862
+ </tr>
863
+ <tr>
864
+ <th>Library</th>
865
+ <th>Slower geometric mean</th>
866
+ </tr>
867
+ <tr>
868
+ <td>pairing_heap (SimplePairingHeap)</td>
869
+ <td>1</td>
870
+ </tr>
871
+ <tr>
872
+ <td>pairing_heap (PairingHeap)</td>
873
+ <td>1.318x slower</td>
874
+ </tr>
875
+ <tr>
876
+ <td>rb_heap</td>
877
+ <td>1.8x slower</td>
878
+ </tr>
879
+ <tr>
880
+ <td>lazy_priority_queue</td>
881
+ <td>2.519x slower</td>
882
+ </tr>
883
+ <tr>
884
+ <td>Fibonacci</td>
885
+ <td>2.989x slower</td>
886
+ </tr>
887
+ <tr>
888
+ <th colspan="4">ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) +YJIT [x86_64-darwin21]</th>
889
+ </tr>
890
+ <tr>
891
+ <th>Library</th>
892
+ <th>Slower geometric mean</th>
893
+ </tr>
894
+ <tr>
895
+ <td>pairing_heap (SimplePairingHeap)</td>
896
+ <td>1</td>
897
+ </tr>
898
+ <tr>
899
+ <td>pairing_heap (PairingHeap)</td>
900
+ <td>1.348x slower</td>
901
+ </tr>
902
+ <tr>
903
+ <td>rb_heap</td>
904
+ <td>1.490x slower</td>
905
+ </tr>
906
+ <tr>
907
+ <td>Fibonacci</td>
908
+ <td>1.792x slower</td>
909
+ </tr>
910
+ <tr>
911
+ <td>lazy_priority_queue</td>
912
+ <td>2.492x slower</td>
913
+ </tr>
914
+ <tr>
915
+ <th colspan="4">jruby 9.3.7.0 (2.6.8) 2022-08-16 c79ef237e0 OpenJDK 64-Bit Server VM 17.0.2+8-86 on 17.0.2+8-86 +indy +jit [x86_64-darwin]</th>
916
+ </tr>
917
+ <tr>
918
+ <th>Library</th>
919
+ <th>Slower geometric mean</th>
920
+ </tr>
921
+ <tr>
922
+ <td>pairing_heap (SimplePairingHeap)</td>
923
+ <td>1</td>
924
+ </tr>
925
+ <tr>
926
+ <td>rb_heap</td>
927
+ <td>1.292x slower</td>
928
+ </tr>
929
+ <tr>
930
+ <td>pairing_heap (PairingHeap)</td>
931
+ <td>1.359x slower</td>
932
+ </tr>
933
+ <tr>
934
+ <td>lazy_priority_queue</td>
935
+ <td>2.115x slower</td>
936
+ </tr>
937
+ <tr>
938
+ <td>Fibonacci</td>
939
+ <td>1.824x slower</td>
940
+ </tr>
941
+ <tr>
942
+ <th colspan="4">truffleruby 22.2.0, like ruby 3.0.3, GraalVM CE JVM [x86_64-darwin]</th>
943
+ </tr>
944
+ <tr>
945
+ <th>Library</th>
946
+ <th>Slower geometric mean</th>
947
+ </tr>
948
+ <tr>
949
+ <td>pairing_heap (SimplePairingHeap)</td>
950
+ <td>1</td>
951
+ </tr>
952
+ <tr>
953
+ <td>pairing_heap (PairingHeap)</td>
954
+ <td>1.865x slower</td>
955
+ </tr>
956
+ <tr>
957
+ <td>rb_heap</td>
958
+ <td>1.915x slower</td>
959
+ </tr>
960
+ <tr>
961
+ <td>lazy_priority_queue</td>
962
+ <td>8.791x slower</td>
407
963
  </tr>
408
964
  <tr>
409
965
  <td>Fibonacci</td>
410
- <td>1.78x slower</td>
966
+ <td>26.044x slower</td>
411
967
  </tr>
412
968
  </table>
413
969