En el siguiente código, se crean cadenas de 1Mil de igual longitud. Luego se recorren para encontrar una cadena coincidente. La primera ejecución tiene cadenas que son 3 veces más largas que la segunda ejecución.
El resultado esperado era que el tiempo que lleva hacer una comparación de igualdad de cadenas de diferentes longitudes no variaría debido a la 'internación de cadenas'. Sin embargo, los resultados muestran que una cadena con 3 veces la longitud tarda aproximadamente 3 veces en realizar una verificación de igualdad. ¿Porqué es eso?
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);Producción:
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.0El resultado esperado era que el tiempo que lleva hacer una comparación de igualdad de cadenas de diferentes longitudes no variaría debido a la 'internación de cadenas'.
No, la internación de cadenas solo significa que para algunas cadenas sabes que son iguales porque están almacenadas en la misma ubicación, por ejemplo, para valores de cadena creados a partir de los mismos literales de cadena. Pero no todas las cadenas (especialmente las creadas dinámicamente) se internan, y tener diferentes direcciones de memoria no dice nada sobre el contenido de las cadenas. Si la verificación de la ubicación de la memoria falla, aún debe comparar el contenido de la cadena como de costumbre.
Algún ejemplo para demostrar esto:
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 y b tienen el mismo contenido, pero son objetos de cadena diferentes (en la memoria) porque se acumularon en diferentes llamadas de generateString . str hace referencia al mismo valor que a .