njh / ruby-mqtt

Pure Ruby gem that implements the MQTT protocol, a lightweight protocol for publish/subscribe messaging.
http://www.rubydoc.info/gems/mqtt
MIT License
538 stars 135 forks source link

Improve `Packet.read_byte` performance #134

Closed tenderlove closed 3 years ago

tenderlove commented 3 years ago

Packet.read_byte reads a byte from the socket and returns it. Before this commit it would allocate a string and an array, after this commit it makes 0 allocations.

Here is a benchmark:

require "mqtt/packet"

def count_alloc
  x = GC.stat(:total_allocated_objects)
  yield
  GC.stat(:total_allocated_objects) - x
end

File.open(__FILE__) do |f|
  10.times do
    allocations = count_alloc do
      MQTT::Packet.read_byte f
    end

    p ALLOCATIONS: allocations
  end
end

On the master branch:

$ ruby --disable-gems -I lib -rmqtt/packet test.rb
{:ALLOCATIONS=>11}
{:ALLOCATIONS=>3}
{:ALLOCATIONS=>3}
{:ALLOCATIONS=>3}
{:ALLOCATIONS=>3}
{:ALLOCATIONS=>3}
{:ALLOCATIONS=>3}
{:ALLOCATIONS=>3}
{:ALLOCATIONS=>3}
{:ALLOCATIONS=>3}

On this branch:

$ ruby --disable-gems -I lib -rmqtt/packet test.rb
{:ALLOCATIONS=>6}
{:ALLOCATIONS=>0}
{:ALLOCATIONS=>0}
{:ALLOCATIONS=>0}
{:ALLOCATIONS=>0}
{:ALLOCATIONS=>0}
{:ALLOCATIONS=>0}
{:ALLOCATIONS=>0}
{:ALLOCATIONS=>0}
{:ALLOCATIONS=>0}
njh commented 3 years ago

Thanks Aaron!