Latticework

Command Palette

Search for a command to run...

Debugging

Bisection Debugging

18 min

Explanation

When a bug was introduced somewhere in a long history of commits (or a long sequence of steps, or a huge input), checking every single one one-by-one is slow. Bisection debugging — the same idea as git bisect — applies binary search (from the Algorithms course) directly to the debugging process itself: check the MIDDLE candidate, and the result tells you which half to search next.

def find_first_failing_index(results):
    lo, hi = 0, len(results)
    while lo < hi:
        mid = (lo + hi) // 2
        if results[mid]:
            lo = mid + 1   # this one passed -- bug is later
        else:
            hi = mid        # this one failed -- bug is here or earlier
    return lo if lo < len(results) else -1
Try it

This precondition -- once it starts failing, it KEEPS failing -- is essential. Bisection gives a wrong answer on a 'flaky' bug that fails intermittently rather than consistently after some point.

Loading editor…
Explanation

This is precisely the O(log n) idea from the Complexity Analysis course, applied to debugging: 1,000 commits takes at most ~10 comparisons to bisect, not 1,000. git bisect automates exactly this loop — you tell it "good" or "bad" for whatever commit it checks out, and it narrows the search the same way.

def bisect_call_count(results):
    lo, hi = 0, len(results)
    count = 0
    while lo < hi:
        mid = (lo + hi) // 2
        count += 1
        if results[mid]:
            lo = mid + 1
        else:
            hi = mid
    return count
Exercise

Write `find_first_failing_index(results)`: `results` is a list of booleans (True = passed) where, once a version starts failing, every later version also fails. Using BINARY SEARCH (not a linear scan), return the index of the first failing version, or -1 if none fail.

Exercise

Write `bisect_call_count(results)`: same bisection logic, but return the NUMBER of comparisons (midpoint checks) it actually took.

Quiz

Why is bisecting through a sequence of commits (like `git bisect`) to find which one introduced a bug more efficient than checking each commit one by one?

Checkpoint

You can apply binary search to find where a bug was introduced across a long sequence, instead of checking every candidate one by one.