Last active
March 14, 2023 18:09
-
-
Save cgiosy/26a140cfc3e2f021ba7b672e7651813a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const filenum = 30; // or 100 | |
const lines = 2000000; // or 1000000 | |
const errors = 100000; | |
const ratio = lines / errors | 0; | |
const count = lines / ratio | 0; | |
for (let i = 1; i <= filenum; i += 1) { | |
const stream = fs.createWriteStream(`test${i}-log.xml`, { flags: 'a' }); | |
let text = `<error><!\[CDATA\[${i}#${Math.random()}\]\]><\/error>\n`; | |
for (let j = 2; j <= ratio; j += 1) | |
text += `<info><!\[CDATA\[${i}#${Math.random()}\]\]><\/info>\n`; | |
text | 0; | |
for (let j = 1; j <= count; j += 1) | |
stream.write(text); | |
stream.end(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { resolve } = require('path'); | |
const { writeFile, readFile, readdir } = require('fs').promises; | |
const walkDir = (fn, startingDir = '.') => { | |
const _walkDir = (currentDir) => readdir(currentDir, { withFileTypes: true }).then((children) => Promise.all( | |
children.map((child) => { | |
const res = resolve(currentDir, child.name); | |
if (child.isDirectory()) return _walkDir(res); | |
return Promise.resolve(fn(res)); | |
}) | |
)); | |
return _walkDir(startingDir); | |
}; | |
const flatten = (str) => { | |
str | 0; | |
return str; | |
}; | |
const extractErrors = async () => { | |
const filenames = []; | |
await walkDir((filename) => { | |
if (!filename.toLowerCase().endsWith('-log.xml')) return; | |
filenames.push(filename); | |
}); | |
let errors = []; | |
for (const filename of filenames) { | |
console.log(filename); | |
const text = await readFile(filename, { encoding: 'utf-8' }); // Out Of Memory! mem usage 97~99% | |
errors = errors.concat( | |
(text.match(/<error><!\[CDATA\[(.+?)\]\]><\/error>/g) || []) | |
.filter(str => !str.includes(' ')) | |
.map(str => str.slice(16, -11)) | |
// .map(flatten) | |
); | |
} | |
await writeFile('errors.txt', JSON.stringify([...new Set(errors)])); | |
}; | |
setTimeout(extractErrors, 0 * 1000); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
삽질 과정:
substr
때문에 GC가 안 도는구나 싶어 flatten 함수를 추가했다. (기존에 알려져 있던 대로라면str | 0
혹은Number(str)
처럼 하면 문자열이flatten
되어 slice에 대한 참조가 해제되어야 한다. #1 #2)flatten
이 잘못되었나 싶어 다른 방법으로 좀 수정해보거나((str += ' ') | 0
등),substr
을 지워봤다. 문제는 그대로였다.toString
에서 메모리의 98%를 차지했다. UCS-2로의 변환이 문제거나 뭔가 내부적으로 비효율적인 게 아닐까 추측했다.errors
의 길이를 제한하니 (당연하게도) 원하는 답은 안 구해지지만 돌긴 한다는 것을 확인했다.toString
등 변환 과정이 아니라 어디에선가 참조가 해제되지 않고 있다는 생각으로 다시 기울었다.flatten
함수와substr
에 대한 검증을 마친 상태였기 때문에, 해당 부분은 문제되지 않을 것이라 생각했다. 그런데 저기를 빼놓고 보니 문제될만한 부분이 없었다. 여전히 답은 보이지 않았다.flatten
함수로 해결되지 않고 있었기 때문에, 좀 다른 부분이 문제일 것이라 생각했다.flatten
함수의str | 0
부분만str = (' ' + str).slice(1)
로 바꿨다. 됐다.flatten
이었다...!!! 노드가 버전업돼서 그런 것인지 아무 작동도 수행하지 않았고, 따라서 내부적으로 slice에 대한 참조 역시 해제되지 않아 GC가 문자열을 수집하지 못하는 것이었다...!배운 점: