Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the algorithmic complexity of string slicing? (Practical, Real World)

In modern, v8 Javascript, what is the algorithmic complexity of String.prototype.slice?

To be clear, I'm looking for real-world, practical figures or rules of thumb.

Quick Tests

I tried to get a rough estimate by running two quick tests in the most recent Chrome. Test 1 slices a string of length N in half. Test 2 slices a string of length N each index in the string (so N times). Confusingly, both run in O(N) time. What is going on?

Test 1

let input = '';
let string = ' '.repeat(20000000);
for (let i = 0; i < 50; i++) {
    input += string;
    console.time(i);
    const y = input.slice(i / 2);
    console.timeEnd(i);
}

Test 2

let input = '';
let string = ' '.repeat(20000000);
for (let i = 0; i < 50; i++) {
    input += string;
    console.time(i);
    for (let j = 0; j < i; j++) {
        const y = input.slice(j);
    }
    console.timeEnd(i);
}

Chrome version: Chrome Version 63.0.3239.84 (Official Build) (64-bit)

like image 460
Will Avatar asked Mar 07 '23 09:03

Will


1 Answers

Yes, V8 has optimised string slicing to O(1). This does of course depend a lot on what else happens to all the strings, they might need to get copied later on.

The relevant implementation from the above link is:

Sliced String diagram

// The Sliced String class describes strings that are substrings of another
// sequential string.  The motivation is to save time and memory when creating
// a substring.  A Sliced String is described as a pointer to the parent,
// the offset from the start of the parent string and the length.  Using
// a Sliced String therefore requires unpacking of the parent string and
// adding the offset to the start address.  A substring of a Sliced String
// are not nested since the double indirection is simplified when creating
// such a substring.
// Currently missing features are:
//  - handling externalized parent strings
//  - external strings as parent
//  - truncating sliced string to enable otherwise unneeded parent to be GC'ed.
class SlicedString: public String {
  // ...
};

Also beware of your quick test results. As you are doing nothing with the y variable, the slicing and even the whole loop might get eliminated as dead code by the optimiser. If you are doing benchmarks, do them on practical real world data.

like image 146
Bergi Avatar answered Apr 07 '23 04:04

Bergi