   scale: (value) =>
     @height / @maxIndex * value
 
-  drawIndex: (index) =>
+  ###
+  # Draw the line at the specified index.
+  # @param {number} index the index to draw
+  # @param {boolean} markForRedraw false if it doesn't need a redraw next time.
+  ###
+  drawIndex: (index, markForRedraw = true) =>
+    @markedForRedraw.push index if markForRedraw
     @ctx.fillRect(2 * index * @barWidth, @height - @scale(@animationIndices[index]), @barWidth, @scale(@animationIndices[index]))
 
-  redraw: =>
-    @ctx.clearRect(0, 0, @pxWidth, @height)
+  ###
+  # Redraw a part of the canvas.
+  # @param {array[number]} range array of the indices to redraw. It must
+  #   represent a range.
+  ###
+  redrawParts: (range) ->
+    @ctx.clearRect(2 * _.first(range) * @barWidth, 0, 2 * range.length * @barWidth, @height)
     @ctx.fillStyle = @colors.normal
-    for index in [0...@length]
-      @drawIndex(index)
+    for index in range
+      @drawIndex(index, false)
+
+  ###
+  # Redraw the persistent highlight.
+  ###
+  redrawPersistentHighlight: ->
     @ctx.fillStyle = @colors.persistHighlight
     for index in @currentHighlight
-      @drawIndex(index)
+      @drawIndex(index, false)
+
+  ###
+  # Redraw the parts of the canvas which were recently colorized.
+  ###
+  redrawIfNeeded: ->
+    if @markedForRedraw.length
+      for range in @markedForRedraw
+        if !$.isArray range
+          range = [range]
+        @redrawParts range
+    @redrawPersistentHighlight()
+    @markedForRedraw = []
+
+  ###
+  # Redraw all of the canvas.
+  ###
+  redraw: =>
+    @redrawParts [0...@length]
+    @redrawPersistentHighlight()
 
   shuffle: =>
     # Fisher-Yates shuffle

      @animationIndices = @indices.slice()
      @redraw()

  domStats:
    swaps: $("#js-swaps")
    inserts: $("#js-inserts")

    @shifts = 0
    @compares = 0
    @currentHighlight = []
    ###
    # List of indices or ranges which has been modified/colorized during the
    # current step. They will be redrawn on the next step.
    ###
    @markedForRedraw = []

  starting: =>
    @working = true
