字符串切片的算法复杂度是多少?(实用,真实世界)

Wil*_*ill 2 javascript big-o v8

在现代的v8 Javascript中,String.prototype.slice的算法复杂度是多少?

明确地说,我正在寻找真实的实用数字或经验法则。

快速测试

我试图通过在最新的Chrome浏览器中运行两项快速测试来大致估算。测试1将一串长度切N成两半。测试2对字符串中N每个索引的长度(长度)进行切片N。令人困惑的是,两者都O(N)及时运行。到底是怎么回事?

测试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);
}
Run Code Online (Sandbox Code Playgroud)

测试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);
}
Run Code Online (Sandbox Code Playgroud)

Chrome版本:Chrome版本63.0.3239.84(正式版本)(64位)

Ber*_*rgi 6

是的,V8已将字符串切片优化为O(1)。当然,这确实取决于所有字符串的其他情况,以后可能需要复制它们。

上述链接的相关实现为:

切片字符串图

// 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 {
  // ...
};
Run Code Online (Sandbox Code Playgroud)

还请注意您的快速测试结果。当您对y变量不执行任何操作时,优化程序会将切片甚至整个循环作为死代码消除。如果您要进行基准测试,请在实际的实际数据上进行基准测试。

  • V8开发人员在这里。这个答案是正确的。实际上,字符串切片是如此之快,以至于基准测试甚至无法测量它。所有的时间都花在分配疯狂的大输入字符串上(最多10亿个字符!)。当然,这种分配在字符串的大小上是线性的。它显示在您的定时范围内,因为*将它们*创建为“ cons字符串”的速度很快,并且* flattening *会花费时间,这是按需完成的(即,第一次调用.slice`)。当心微基准测试,它们经常会误导您! (2认同)