Estoy haciendo una versión modificada de la recopilación de co-ocurrencias de palabras, así que escribí mi propio javascript y estoy rastreando las ocurrencias en tres objetos. Sin embargo, una vez que los objetos se vuelven grandes (~8 millones, 3 millones y 172000), una función que tardaba 5 segundos por 100000 oraciones ahora tarda minutos en hacer una oración con 30 palabras (30 tokens). No estoy cerca de mi límite de RAM (tengo 12 GB más de RAM que podría estar usando, y el programa solo usa 2.2 GB). Usando Node.js v17.3.1.
¿Por qué mi función tarda tanto cuando los objetos se hacen más grandes (aunque las oraciones siguen siendo de la misma longitud)? ¿Debería usar un objeto diferente además del objeto predeterminado de Javascript, o hay alguna forma de mejorar la velocidad de acceso y configurar estos objetos cuando son tan grandes?
Código:
let posCounts = {}; let negCounts = {}; // the number of times each word occurs let wordCounts = {}; let tokens = // some function that gets tokens; for (let k = 0; k < tokens.length; k++) { // count word occurences if (tokens[k] in wordCounts) { wordCounts[tokens[k]] += 1; } else { wordCounts[tokens[k]] = 1; } for(let tok = k + 1; tok < tokens.length; tok++) { if (tok == k) { // avoid word to self cooccurrence // should no longer be possible continue; } else { // check which form of the cooccurence exists already in either count actual_tok = (tokens[k] + "-" + tokens[tok]); if(actual_tok in posCounts || actual_tok in negCounts) { // no-op } else { actual_tok = (tokens[tok] + "-" + tokens[k]); } // condition set before this block of code if(condition) { if (actual_tok in posCounts) { posCounts[actual_tok] += 1; } else { posCounts[actual_tok] = 1; } } else { if (actual_tok in negCounts) { negCounts[actual_tok] += 1; } else { negCounts[actual_tok] = 1; } } } } } Actualización: he intentado aumentar el tamaño del montón a través node train_matrices.js --max-old-space-size=12288 y node train_matrices.js --max_old_space_size=12288 (subrayado en lugar de guión), y eso tampoco funcionó .
Probablemente no sea el problema principal en su código, pero puede reducir la cantidad de búsquedas cambiando esta estructura de esto:
if (tokens[k] in wordCounts) { wordCounts[tokens[k]] += 1; } else { wordCounts[tokens[k]] = 1; }a esto:
let token = tokens[k]; let cnt = wordCounts[token] || 0; wordCounts[token] = cnt + 1; Y, como dije en un comentario, he leído que un objeto Map con .get() y .set() se adapta mejor cuando hay muchas claves creadas dinámicamente, mientras que los objetos simples se adaptan mejor cuando hay muchos objetos. con todas las mismas claves (ya que el compilador JS a veces puede crear una estructura similar a C para él), pero esto no se puede hacer cuando agrega nuevas claves regularmente.