You are attaching 9420 event listeners (three for each county). A better solution would be to do the equivalent of delegate in jQuery:
var counties = map.append('g');
counties.attr('class', 'counties')
.selectAll('path')
.data(countylines.features)
.enter().append('path')
.attr('d', path);
counties.on('mouseover', function(){
if (d3.event.target.tagName == "path")
showCaption();
})
.on('mouseout', function() {
if (d3.event.target.tagName != "path")
caption.html(starter);
});
You also don't need to repeat the process on mousemove, that triggers dozens of events per second for what mouseover and mouseout already accomplished.
Try it out, I'm sure it will feel snappier.