Evaluate performance of O(N) insertion
ioquatix opened this issue · 3 comments
I found this was generally acceptable because insert is fast for small arrays. For HUGE numbers of timers, this might be a bottleneck. Perhaps a segmented array or deque might be more appropriate. However, anything implemented in pure ruby is likely to be slower.
@digitalextremist @takiy33 if you want to tackle some performance issues here is a good one to review.
Step one is to profile the code in question using the performance benchmarks and perhaps make other benchmarks to see if and when it becomes a problem. Step two is to see if there is any decent way to improve performance. Technically, some kind of tree (i.e. a min-heap) might be appropriate, but pure ruby for this data structure is slow compared to insert from my tests about a year ago..
Timers::Group
Serviced 192065 events in 8.354132437 seconds, 22990.44130157285 e/s.
Thread ID: 9851640
Fiber ID: 32710700
Total: 8.350259
Sort by: self_time
%self total self wait child calls name
35.57 5.914 2.970 0.000 2.944 202100 Timers::Events#bisect_left
21.44 2.944 1.790 0.000 1.154 2595479 Timers::Events::Handle#>
13.81 1.153 1.153 0.000 0.000 2595010 Timers::Events::Handle#to_f
5.01 6.918 0.418 0.000 6.500 202065 Timers::Events#schedule
4.09 7.400 0.342 0.000 7.058 202065 Timers::Timer#reset
3.86 7.559 0.322 0.000 7.237 192065 Timers::Timer#fire
3.00 0.250 0.250 0.000 0.000 202065 Array#insert
2.24 7.746 0.187 0.000 7.559 192065 Timers::Events::Handle#fire
1.75 0.146 0.146 0.000 0.000 202065 Timers::Events::Handle#initialize
1.67 0.678 0.140 0.000 0.538 212077 *Class#new
1.55 0.129 0.129 0.000 0.000 192065 Proc#call
1.31 7.856 0.110 0.000 7.746 35 Array#reverse_each
1.05 0.087 0.087 0.000 0.000 192065 Timers::Events::Handle#cancel!
So here is the interesting data. If you look at Array#insert, it's actually relatively minor. The elephant in the room is bisect_left
, which while significantly faster than the previous implementation, is now simply the slowest part and thus warrants the most attention. Personally, I don't know if it's possible to write a better implementation in pure Ruby. It's something I did spend some time considering, but the next step might be writing it in C.
I believe performance is good enough in practice.