Javascript:为什么较长的字符串相等需要更长的时间?

Javascript: Why does equality of strings take longer for longer strings?

在以下代码中,创建了 100 万个等长字符串。 然后循环查找匹配的字符串。 第一个 运行 的字符串比第二个 运行.

长 3 倍

预期的结果是,对不同长度的字符串进行相等比较所花费的时间不会因 'string interning' 而发生变化。然而,结果显示长度为 3 倍的字符串需要大约 3 次来进行相等性检查。这是为什么?

import { v4 as uuidv4 } from 'uuid';

export const uuid = () => {
  return uuidv4();
};

function createSingleId(howManyUuidsInOneId1: number) {
  let id = '';
  for (let j = 0; j < howManyUuidsInOneId1; j++) {
    id += uuid();
  }
  return id;
}

function generate(howManyIds: number, howManyUuidsInOneId: number) {
  const ids = [];
  for (let i = 0; i < howManyIds; i++) {
    ids.push(createSingleId(howManyUuidsInOneId));
  }
  return ids;
}

const main = (howManyIds: number, howManyUuidsInOneId:number) => {

  const ids = generate(howManyIds, howManyUuidsInOneId);

  const toFind = createSingleId(howManyUuidsInOneId);

  console.log(`Sample id being compared: '${toFind}'`);

  const before = new Date().getTime();

  ids.filter(id => id === toFind);

  console.log(`Took '${new Date().getTime() - before}ms' to loop through and equal compare '${howManyIds}' when stacked '${howManyUuidsInOneId}' in single id`);
};

main(1000000, 3);
main(1000000, 1);

输出:

Sample id being compared: 'dc03bf00-6f2a-48d9-b3ca-b6ac45782c5cefaa92c0-9372-4f47-bcec-f9fbb41d4625e0c5c278-b574-4a9f-a77e-110cbc6bf601'
Took '64ms' to loop through and equal compare '1000000' when stacked '3' in single id
Sample id being compared: '07e693ce-49a1-4cc6-90e1-0bd99629123b'
Took '19ms' to loop through and equal compare '1000000' when stacked '1' in single id
> node --version
v15.14.0

The expected outcome was that the time it takes to do equality comparison of strings of different length would not vary due to 'string interning'.

不,字符串实习仅意味着对于某些字符串,您知道它们是相同的,因为它们存储在相同的位置,例如对于从相同的字符串文字创建的字符串值。但并非所有字符串(尤其是非动态创建的字符串)都会被驻留,并且具有不同的内存地址并不能说明字符串的内容。如果内存位置检查失败,你仍然需要像往常一样比较字符串contents

一些例子来证明这一点:

function generateString(len) {
  let x = "";
  for (let i=0; i<len; i++) x+= String.fromCharCode(64+i%64);
  return x;
}
function time(callback, desc) {
  const before = performance.now();
  const res = callback();
  console.log(`Took ${performance.now()-before}ms to ${desc}`);
  return res;
}

const strLen = 5000000;
const a = generateString(strLen);
const b = generateString(strLen);
console.assert(a === b);
const str = a;
time(() => str === a, 'compare a with itself');
time(() => str === b, 'compare a with b');

ab内容相同,但是是不同的字符串对象(在内存中),因为它们是在不同的generateString调用中累积的。 str 引用 a 相同的 值。