score:1

Accepted answer

I've played around the data, which was close to your. I had a log table (ascending timestamps) with ~350k of records. I dumped it into csv and wrote a benchmark.js suite to slice ~10% range of it (see below). I have the following results on my laptop:

Firefox

Array.prototype.filter x 38.42 ops/sec ±0.79% (64 runs sampled)
Full crossfilter.js x 11.85 ops/sec ±18.42% (30 runs sampled)
Prepared crossfilter.js x 1,196 ops/sec ±9.70% (69 runs sampled)
Binary search x 3,525 ops/sec ±4.51% (45 runs sampled)
Fastest: Binary search

Chromium

Array.prototype.filter x 33.34 ops/sec ±2.34% (44 runs sampled)
Full crossfilter.js x 5.23 ops/sec ±6.74% (17 runs sampled)
Prepared crossfilter.js x 1,321 ops/sec ±11.90% (95 runs sampled)
Binary search x 22,172 ops/sec ±1.25% (95 runs sampled)
Fastest: Binary search

A note about crossfilter.js. It's not exactly a part of D3, but a member of the family (written also by Mike Bostock). Its goal is quick filtering and grouping of multi-dimensional data. So in case you would like to slice your data interactively, it's exactly what you need. However if performance is an absolute priority and you can guarantee that data is sorted, then you'd like to adapt binary search like in example below.

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
  <title>Sorted list date range performance comparison</title>
    <script src='http://d3js.org/d3.v3.min.js' type='text/javascript'></script>
    <script src='http://square.github.io/crossfilter/crossfilter.v1.min.js' type='text/javascript'></script>
    <script src='http://rawgithub.com/bestiejs/benchmark.js/v1.0.0/benchmark.js' type='text/javascript'></script>
  <script type="text/javascript">
    function log(message)
    {
      document.getElementById('output').innerHTML += message + '\n';
    }
    function getTimestamp(item)
    {
      return item.timestamp;
    }
    function binarySearch(array, key, left, right)
    {
      var middle, result;
      while(left <= right && array[left] <= key && key <= array[right])
      {
        result = middle = left + Math.floor((right - left) / 2) 
        if(key > array[middle])
        {
          left = middle + 1;
        }
        else if(key < array[middle])
        {
          right = middle - 1;
          if(key > array[right])
          {
            result = right;
            break;
          }        
        }
        else
        {
          break;
        }
      }
      return result;
    }

    // replace to d3.json for a JSON source
    d3.csv('log.csv', function(data)
    {
      data.forEach(function(item)
      {
        item.timestamp = Number(item.timestamp);
      });

      // this should give ~35k entries which is 10% of the dataset
      var start  = Math.floor(new Date('2013-01-01').valueOf() / 1000);
      var finish = Math.floor(new Date('2013-04-01').valueOf() / 1000);

      var dataset   = crossfilter(data);
      var dimension = dataset.dimension(getTimestamp);

      var timestampArray = data.map(getTimestamp);

      new Benchmark.Suite()
        .add('Array.prototype.filter', function() 
        {
          var result = data.filter(function(item)
          {
            return item.timestamp >= start && item.timestamp < finish;
          });
          console.assert(result.length == 34694);
        })
        .add('Full crossfilter.js', function() 
        {
          var dataset   = crossfilter(data);
          var dimension = dataset.dimension(function(item)
          {
            return item.timestamp;
          });
          var result = dimension.filterRange([start, finish]);
          console.assert(result.top(Infinity).length == 34694);
        })
        .add('Prepared crossfilter.js', function() 
        {
          var result = dimension.filterRange([start, finish]);
          console.assert(result.top(Infinity).length == 34694);
        })
        .add('Binary search', function() 
        {
          var left   = binarySearch(timestampArray, start, 0, data.length - 1);
          var right  = binarySearch(timestampArray, finish, 0, data.length - 1);
          var result = data.slice(left + 1, right + 1);
          console.assert(result.length == 34694);
        })          
        .on('cycle', function(event) 
        {
          log(event.target);
        })
        .on('complete', function() 
        {
          log('Fastest: ' + this.filter('fastest').pluck('name'));
        })        
        .run({'async': true});
    });
  </script> 
</head>
<body>
  <pre id='output'></pre>
</body>
</html>

Related Query

More Query from same tag