title: d3 got slow all of a sudden
body: <p>Unfortunately, by 'all of a sudden', I mean between versions 3.1.1.10 and 3.2.0.  I have a scatterplot with about 3000 points in it, and we are trying to make a mouse click based tooltip work since tooltips based on mouseover events don't really work for us.</p>
  
  <p>So, while testing our initial attempt, we saw that it took a full 2 or 3 seconds before anything happened.  I thought that was a little odd.  I mean sure, we're doing a nearest-neighbor calculation, but it's only 3000 points, so what gives?  I profiled it and found that <em>once we got the event trigger</em>, our calculations were only taking about 22 msec, so that's good.  So what is causing d3 to take so much time in getting us active on mouse clicks?  I started dropping in different versions of d3 to see if it was the culprit and sure enough, things were slow until I got back to version 3.1.0.  That one have us the mouse event pretty much immediately and our tooltip popups were now working well.</p>
  
  <p>Only problem is I can't use 3.1.10 because I need the zoom().center() functionality that was added more recently.</p>
  
  <p>So any ideas?  Anybody know why the slowdown occurred there? Can it be patched?  Can someone suggest a clever workaround? I can't be the only one who has seen this problem.
  I brought it up in the d3 forum, topic number qfz11UYgMC8</p>
  
  <p>I understand why I cannot post codepen demos here without code, but the 2  demos I have demonstrate my point above by differing only in what version of d3 is included in them. I will include the code here if people really want to see it, but it's pretty much standard d3.js where I create my scatterplot from a json object, and it's thousands of lines of code.</p>
  
  <p>And the problem is definitely based on the size of the scatterplot.  A small plot of a dozen or so points pops up the tooltip right away, and the one with 3000 points is slow (on all d3.js libraries 3.2 and later).</p>
  
  <p>Edit: adding code snippets, and codepen links
  The code itself is thousands of lines long because the data itself gets embedded in the html.  Here is what I hope is the relevant code...</p>
  
  <pre><code>&lt;html&gt;
  &lt;head&gt;
      &lt;title&gt;Rolling D3 speed test&lt;/title&gt;
      &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.2.0/d3.min.js"&gt;&lt;/script&gt;
      &lt;!-- &lt;script src="file://C:/d3.v3.5.16.min.js"&gt;&lt;/script&gt; --&gt;
      &lt;script type="text/javascript" charset="utf8" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"&gt;&lt;/script&gt;
      &lt;script type="text/javascript" language="javascript" class="init"&gt;
  
  // variable init left out for brevity
  ...
  var svg = d3.select("body").append("svg")
              .attr("width",viewportWidth)
              .attr("height",viewportHeight)
              .call(zoom)
              .append("g")
      .attr("class", "main")
              .attr("transform","translate("+(left_shift)+","+(top_shift)+")");
  ...
  //mouse click on svg (to display tooltip on nearest point)
  d3.select('svg').on("click",  function() {
    var startTime = new Date();
    var coords = [0, 0];
    coords = d3.mouse(this);
    var isClicked = isPointClicked(point_clicked);
    if(!isClicked) clicked(coords[0], coords[1]);
    point_clicked = false;
  
    var finalEndTime = new Date();
    var finalTimeDiff = finalEndTime - startTime;
    console.log('all click actions completed in '+finalTimeDiff+' milliseconds.');
  });
   //mouse-right click event to remove tooltip
    d3.select('body').on("contextmenu", function() {
    d3.event.preventDefault();
    var ele = d3.select('div.tooltip');
    //if(ele!=="undefined" &amp;&amp; ele!==null)
  ele.style("opacity",0);
  });
  
  ...
  // x and y axis rendering removed for brevity
  ...
  
  //draw all data
  //var radius = 2.5; // 2.5 normally, 8 is good for testing small sets
  var side = 2;     // takes place of radius
  // shiftrect needs to be half the square size to center square on data point
  var shiftrect = 1;
  for(var k=0;k&lt;plot_data.series.length;++k) {
      if(plot_data.series[k].visible === true) {
          var y_list = plot_data.series[k].ydata;
          var x_list = plot_data.series[k].xdata;
          svg.selectAll("dot")
             .data(x_list)
             .enter().append("rect")
         .attr("id", function(d, i) { return "rect"+k+i;})
             .attr("x", function(d) {return x(parseFloat(d))-shiftrect;})
             .attr("y", function(d,i) {return y(parseFloat(y_list[i]))-shiftrect;})
             .attr("height", side)
             .attr("width", side)
             .attr("fill",function() { return color(k);})
             .attr("clip-path", "url(#plot-clip)");
      }
  }
  </code></pre>
  
  <p>Codepen that is slow
  <a href="http://codepen.io/pkrouse/details/ONwQmz/" rel="nofollow">http://codepen.io/pkrouse/details/ONwQmz/</a></p>
  
  <p>Codepen that is fast.  Only diff is version of D3 used
  <a href="http://codepen.io/pkrouse/details/JXBpKo/" rel="nofollow">http://codepen.io/pkrouse/details/JXBpKo/</a></p>