code: function TimeHeap(options) {
      var self = this;
      options = options || {};
  
      self.timers = options.timers || globalTimers;
      self.minTimeout = options.minTimeout || null;
      self.array = [];
      self.expired = [];
      self.lastTime = self.timers.now();
      self.timer = null;
      self.end = 0;
      self.lastRun = 0;
      self.drainUntil = 0;
  
      self.scheduledDrain = null;
  
      self.boundDrainExpired = boundDrainExpired;
  
      function boundDrainExpired() {
          var now = self.scheduledDrain;
          self.scheduledDrain = null;
  
          self.drainExpired(now);
      }
  }
docs: /* A specialized min-time heap
  
  new TimeHeap({
  timer: {now, setTimeout, clearTimeout},
  minTimeout: Number | (now) -> Number
  })
  
  The items on the heap must have two properties:
  - item.timeout is ms timeout, relative to heap add time
  - item.onTimeout is a callback which gets called once the item has expired;
  the callback is passed the current time in ms.
  
  Overview:
  - timeHeap.array is an array of TimeHeapElement objects
  
  - timeHeap.lastTime is the timestamp (ms) that all times in the heap are
  relative to
  
  - timeHeap.timer is the currently pending timer object or null
  
  - timeHeap.expired are any items pending having their .onTimeout called; this
  call is defered until next tick after a drain to avoid any heap
  interactions/changes while draining (if the callback adds something else
  to the heap)
  
  The primary public API is:
  timeHeap.update(item, ?now)
  
  Note the method is is intentionally not named something simple like "add" or
  "append" since it does a bit more:
  - pop any expired times, and defer a call to their .onTimeout
  - push the new item and its expiration time onto the heap
  - set a timer if there is none or the newly added item is the next to expire
  
  TODO: shrink array if end is << array.length/2 (trigger in pop and/or a
  sweep on an interval)