What's the time complexity of array.splice() in Google Chrome?

If I remove one element from an array using splice() like so:

arr.splice(i, 1);

Will this be O(n) in the worst case because it shifts all the elements after i? Or is it constant time, with some linked list magic underneath?

Answers


Worst case should be O(n) (copying all n-1 elements to new array).

A linked list would be O(1) for a single deletion.

For those interested I've made this lazily-crafted benchmark. (Please don't run on Windows XP/Vista). As you can see from this though, it looks fairly constant (i.e. O(1)), so who knows what they're doing behind the scenes to make this crazy-fast. Note that regardless, the actual splice is VERY fast.

Rerunning an extended benchmark directly in the V8 shell that suggest O(n). Note though that you need huge array sizes to get a runtime that's likely to affect your code. This should be expected as if you look at the V8 code it uses memmove to create the new array.


The Test:

I took the advice in the comments and wrote a simple test to time splicing a data-set array of size 3,000, each one containing 3,000 items in it. The test would simply splice the

  • first item in the first array
  • second item in the second array
  • third item in the third array
  • ...
  • 3000th item in the 3000th array

I pre-built the array to keep things simple.

The Findings:

The weirdest thing is that the number of times where the process of the splice even takes longer than 1ms grows linearly as you increase the size of the dataset.

I went as far as testing it for a dataset of 300,000 on my machine (but the SO snippet tends to crash after 3,000).

I also noticed that the number of splice()s that took longer than 1ms for a given dataset (30,000 in my case) was random. So I ran the test 1,000 times and plotted the number of results, and it looked like a standard distribution; leading me to believe that the randomness was just caused by the scheduler interrupts.

This goes against my hypothesis and @Ivan's guess that splice()ing from the beginning of an array will have a O(n) time complexity

Below is my test:

let data = []
const results = []
const dataSet = 3000

function spliceIt(i) {
  data[i].splice(i, 1)
}

function test() {
  for (let i=0; i < dataSet; i++) {
    let start = Date.now()
    spliceIt(i); 
    let end = Date.now()
    results.push(end - start)
  }
}

function setup() {
  data = (new Array(dataSet)).fill().map(arr => new Array(dataSet).fill().map(el => 0))
}

setup()
test()
// console.log("data before test", data)
// console.log("data after test", data)
// console.log("all results: ", results)
console.log("results that took more than 1ms: ", results.filter(r => r >= 1))

Need Your Help

How are arrays implemented in Perl?

perl data-structures language-implementation

The Perl array is an abstract data type. What's the internal mechanism for the Perl array? Is it implemented with dynamic array or linked list?

How to inject dependencies into HttpSessionListener, using Spring?

spring servlets dependency-injection httpsession servlet-listeners

How to inject dependencies into HttpSessionListener, using Spring and without calls, like context.getBean("foo-bar") ?