       Range(start, @getEnd(id))
 
   getStart: (id) ->
-    @rootNode.getStart(id)
+    if entry = @rangeCache[id]
+      entry.start ?= @rootNode.getStart(id)
 
   getEnd: (id) ->
-    @rootNode.getEnd(id)
+    if entry = @rangeCache[id]
+      entry.end ?= @rootNode.getEnd(id)
 
   findContaining: (start, end) ->
     containing = new Set


  insert: (id, start, end) ->
    assertValidId(id)
    if splitNodes = @rootNode.insert(new Set().add(id + ""), start, end)
      @rootNode = new Node(splitNodes)

  delete: (id) ->
    assertValidId(id)
    @rootNode.delete(id)
    @condenseIfNeeded()

  splice: (position, oldExtent, newExtent) ->
    if splitNodes = @rootNode.splice(position, oldExtent, newExtent, @exclusiveIds, new Set)
      @rootNode = new Node(splitNodes)
    @condenseIfNeeded()

  dump: (offset, snapshot) ->
    end = offset.traverse(@extent)
    @ids.forEach (id) ->
      snapshot[id].start ?= offset
      snapshot[id].end = end
    end

  findContaining: (point, set) ->
