-
[NodeJs] Buffer와 Stream개발/Javascript 2022. 6. 28. 15:34
Buffer는 바이너리 데이터를 직접 다루는 클래스이며
Stream은 이름에서 알 수 있듯 데이터를 스트리밍할 수 있는 클래스입니다.
Buffer는 처리할 데이터를 그대로 메모리에 올리고
Stream은 적은 메모리만을 사용해 데이터를 스트리밍합니다.
때문에 가용 메모리 용량이 충분하다면 Buffer가 빠르겠지만 메모리 사용 효율은 좋지 않을 것이고
Stream을 사용하면 Buffer보다 처리 속도가 느릴 수 있지만 메모리를 효율적으로 사용합니다.
node로 500mb 상당의 파일을 불러와서 처리한다고 해볼게요.
다음 코드는 특정 문자에 대한 블록을 확인해 카운트하는 로직이므로
내용은 신경 안 써도 될 것 같습니다.
Stream 사용
const rs = fs.createReadStream('local/big_file', { encoding: 'utf-8', //highWaterMark: 65536 // default 청크 사이즈 조절 }); const { log } = console; /** * @type {Object.<string, number>} */ const characterBlockCount = { a: 0, b: 0, }; /** @type {string | undefined} */ let prevChar = ''; /** @type {number} */ let chunkCount = 0; // everytime it reads rs.on('data', (data) => { // default data is Buffer chunkCount += 1; if (typeof data !== 'string') { return; } for (let i = 0; i < data.length; i += 1) { const character = data[i]; if (!character) continue; if (prevChar !== character) { prevChar = character; characterBlockCount[character] += 1; } } });
Buffer 사용
const fs = require('fs'); const data = fs.readFileSync('local/big_file', 'utf-8'); const { log } = console; /** * @type {Object.<string, number>} */ const characterBlockCount = { a: 0, b: 0, }; /** @type {string | undefined} */ let prevChar = ''; for (let i = 0; i < data.length; i += 1) { const character = data[i]; if (!character) continue; if (prevChar !== character) { prevChar = character; characterBlockCount[character] += 1; } }
테스트 전 메모리 상태입니다. 7.3GB가 사용 중인데요.
Buffer를 이용해 데이터를 불러오면 순간적으로 8.2GB까지 올라갑니다.
console.time(), console.timeEnd()를 이용해 측정한 처리 시간은 1.739s입니다
Stream을 사용하면 7.6GB까지 올라간 적도 있고 안 올라간 적도 있습니다.
소요 시간은 2.039초였습니다.
이 결과는 당연합니다.
데이터를 스트리밍하면 데이터가 메모리에 올라갔다가 내려오는 오버헤드가 발생하기 때문입니다.
버퍼를 이용할 경우 메모리 공간이 충분하지 않아 스와핑이 생긴다면 성능 상의 이점이 상쇄될 겁니다.
시스템 사양과 사용 목적, 환경에 따라 두 라이브러리를 잘 선택해야 할 것 같습니다.
마지막으로 스트림의 경우 언제나 온전한 상태의 데이터 청크를 받을 것이라고 보장할 수 없습니다.
구분자 등의 기준점이 있다면, 청크 데이터를 이어 붙여서 온전하게 만들어서 목적에 맞게 파싱해야 합니다.
'개발 > Javascript' 카테고리의 다른 글
[MongoDB] MongoAPIError: URI must include hostname, domain name, and tld (0) 2022.07.04 [Express] 스태틱 파일 경로 (0) 2022.07.02 [NPM] Sementic Versioning (0) 2022.06.26 [RegExp] $1 (0) 2022.06.26 [JavaScript]중복 제거(feat. Set의 한계) (0) 2022.06.21