mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
a4e9dd2e7d
Currently, the Ring class is written with help of Hash as backend store. According to the comments, the implementation should behave like a circular buffer, however it doesn't. Upon reaching maximum capacity Ring doesn't replace old elements but keeps writing to new cells, deleting old cells, so that the hash contains `nil` entries. The new implementation is based on Array and seems to be closer to the actual Ring. Older elemens get overwritten with newer ones. This class also includes Enumerable, however none of our APIs take advantage of it, so it seems like an overkill. There was also a problem with with this API because of the above-mentioned nils. For example, if the ring exceeds its maximum size, then callin `Enumerable#first` on it returns `nil`. The new implementation deals with this with removal of Enumerable. The `#[]` syntax is preserved, and now `ring[0]` returns an actual element instead of `nil`. In case users need the Enumerable functionality, they can call `Ring#to_a` to build the array, which supports the wanted methods. As for the speed, the new implementation is: * slower overall because it's thread-safe * faster without mutexes for `#<<` * slower without mutexes for `#[]` Benchmark for old implementation: ``` Warming up -------------------------------------- Ring#<< 223.451k i/100ms Ring#[] 2.837k i/100ms Calculating ------------------------------------- Ring#<< 223.157B (± 3.4%) i/s - 778.097B Ring#[] 82.485M (± 9.4%) i/s - 402.602M in 4.957792s ``` Benchmark for this implementation: ``` Warming up -------------------------------------- Ring#<< 211.587k i/100ms Ring#[] 1.974k i/100ms Calculating ------------------------------------- Ring#<< 211.385B (± 2.8%) i/s - 698.439B Ring#[] 40.292M (±17.0%) i/s - 190.069M in 4.971195s ``` The benchmark: ```rb require './lib/pry' require 'benchmark/ips' Benchmark.ips do |x| empty_ring = Pry::Ring.new(100) populated_ring = Pry::Ring.new(100) 150.times { |i| populated_ring << i } x.report("Ring#<<") do |times| empty_ring << times end x.report("Ring#[]") do |times| populated_ring[0] populated_ring[1] populated_ring[2] populated_ring[-1] populated_ring[-2] populated_ring[-3] populated_ring[1..2] populated_ring[-2..-1] populated_ring[-2..3] populated_ring[0..-1] populated_ring[2..-1] populated_ring[-1..10] populated_ring[-1..0] populated_ring[-1..1] end end ``` |
||
---|---|---|
.. | ||
commands | ||
config | ||
fixtures | ||
helpers | ||
integration | ||
method | ||
spec_helpers | ||
cli_spec.rb | ||
code_object_spec.rb | ||
code_spec.rb | ||
color_printer_spec.rb | ||
command_helpers_spec.rb | ||
command_integration_spec.rb | ||
command_set_spec.rb | ||
command_spec.rb | ||
completion_spec.rb | ||
config_spec.rb | ||
control_d_handler_spec.rb | ||
documentation_helper_spec.rb | ||
editor_spec.rb | ||
exception_whitelist_spec.rb | ||
helper.rb | ||
history_spec.rb | ||
hooks_spec.rb | ||
indent_spec.rb | ||
method_spec.rb | ||
pager_spec.rb | ||
prompt_spec.rb | ||
pry_defaults_spec.rb | ||
pry_output_spec.rb | ||
pry_repl_spec.rb | ||
pry_spec.rb | ||
pryrc_spec.rb | ||
ring_spec.rb | ||
run_command_spec.rb | ||
sticky_locals_spec.rb | ||
syntax_checking_spec.rb | ||
wrapped_module_spec.rb |