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');
a
和b
内容相同,但是是不同的字符串对象(在内存中),因为它们是在不同的generateString
调用中累积的。 str
引用 与 a
相同的 值。
在以下代码中,创建了 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');
a
和b
内容相同,但是是不同的字符串对象(在内存中),因为它们是在不同的generateString
调用中累积的。 str
引用 与 a
相同的 值。