Rapid array accesses and garbage collection


(Peter Hickman) #1

I have a small app that uses an Array as a queue. Works well enough but
(seems) to suffer from GC lockouts

Items are added and removed (<< and shift) from the Array frequently and
the queue itself rarely gets very large, 10s to 100s of records, but the
throughput is 100,000s of records

Which is, I assume, causing it to periodically freeze. The question is:

1) Should I manually start GC after every shift operation. Will this trade
off frequent small GC interruptions for less big freezes
2) Should I manually start GC after X shifts. Will large GC events be more
efficient
3) Should I create a fake Array such as below and have much larger GC events

Any pointers or will it just be trying stuff and measuring?

class SlowArray
  DEAD_ZONE = 5

  def initialize
    @data = []
    @size = 0
    @read_from = 0
  end

  def <<(value)
    @data << value
    @size += 1
  end

  def shift
    if @size == 0
      return nil
    else
      x = @data[@read_from]
      @read_from += 1

      if @read_from == DEAD_ZONE
        @data = @data[DEAD_ZONE..-1]
        GC.start
        @read_from = 0
      end

      @size -= 1
      return x
    end
  end

  def size
    @size
  end
end


(Peter Hickman) #2

For reference, frequent small GC runs stops the long freeze-up that can
occur but slows down the throughput