pairing_heap 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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