node.js의 fs.createReadStream 대 fs.readFile의 장단점은 무엇입니까?
나는 node.js에 대해 비웃고 있으며 파일이 존재한다는 것을 확인하고 writeHead로 적절한 MIME 유형을 보냈을 때 파일을 읽고 전송하는 두 가지 방법을 발견했습니다.
// read the entire file into memory and then spit it out
fs.readFile(filename, function(err, data){
if (err) throw err;
response.write(data, 'utf8');
response.end();
});
// read and pass the file as a stream of chunks
fs.createReadStream(filename, {
'flags': 'r',
'encoding': 'binary',
'mode': 0666,
'bufferSize': 4 * 1024
}).addListener( "data", function(chunk) {
response.write(chunk, 'binary');
}).addListener( "close",function() {
response.end();
});
문제의 파일이 비디오와 같이 크기가 큰 경우 fs.createReadStream이 더 나은 사용자 경험을 제공 할 수 있다고 가정하는 것이 맞습니까? 덜 뭉툭한 것처럼 느껴집니다. 이것이 사실입니까? 내가 알아야 할 다른 장단점,주의 사항 또는 문제가 있습니까?
"data"를 "write ()"에 연결하고 "close"를 "end ()"에 연결하려는 경우 더 나은 방법입니다.
// 0.3.x style
fs.createReadStream(filename, {
'bufferSize': 4 * 1024
}).pipe(response)
// 0.2.x style
sys.pump(fs.createReadStream(filename, {
'bufferSize': 4 * 1024
}), response)
read.pipe(write)
또는 sys.pump(read, write)
접근 방식은 또한 흐름 제어를 추가 할 수있는 이점이있다. 따라서 쓰기 스트림이 데이터를 빠르게 받아 들일 수없는 경우 메모리에 버퍼링되는 데이터의 양을 최소화하기 위해 읽기 스트림에 백 오프를 지시합니다.
flags:"r"
와는 mode:0666
그것이 사실에 의해 암시된다 FileReadStream
. binary
인코딩되지 않습니다 - 인코딩을 지정하지 않으면, 그냥 원시 데이터 버퍼 도와 드리겠습니다.
또한 파일을 훨씬 더 매끄럽게 제공하는 다른 기능을 추가 할 수 있습니다.
- 에 대한 도청
req.headers.range
과 같은 문자열을 일치하는지 확인/bytes=([0-9]+)-([0-9]+)/
. 그렇다면 해당 시작 위치에서 끝 위치로 스트리밍하기 만하면됩니다. (누락 된 숫자는 0 또는 "끝"을 의미합니다.) - stat () 호출의 inode 및 생성 시간을 ETag 헤더로 해시합니다. 해당 헤더와 일치하는 "if-none-match"가있는 요청 헤더를 받으면
304 Not Modified
. - 통계 개체
if-modified-since
의mtime
날짜에 대해 헤더를 확인 합니다. 제공된 날짜 이후 수정되지 않은 경우 304.
또한 일반적으로 가능하면 Content-Length
헤더를 보냅니다 . ( stat
파일을 -ing하고 있으므로 이것을 가지고 있어야합니다.)
fs.readFile
지적한대로 전체 파일을 메모리에로드하고 fs.createReadStream
지정한 크기의 청크로 파일을 읽습니다.
클라이언트는 또한 fs.createReadStream
읽을 때 청크 단위로 전송되므로 데이터 수신을 더 빨리 시작 fs.readFile
하고 전체 파일을 읽은 다음 클라이언트로 전송하기 시작합니다. 이는 무시해도 좋을 수 있지만 파일이 매우 크고 디스크 속도가 느린 경우 차이를 만들 수 있습니다.
이 두 기능을 100MB 파일에서 실행하면 첫 번째 기능은 파일을로드하는 데 100MB 메모리를 사용하고 후자는 최대 4KB 만 사용하므로 이에 대해 생각해보십시오.
편집 : 나는 fs.readFile
당신이 큰 파일을 열 것이라고 말했기 때문에 특히 당신이 사용하는 이유를 알지 못합니다 .
큰 파일 인 경우 "readFile"은 메모리에있는 모든 파일 내용을 버퍼링하므로 메모리를 잡아 먹고 시스템이 중단 될 수 있습니다. ReadStream이 청크로 읽는 동안.
이 코드를 실행하고 작업 관리자의 성능 탭에서 메모리 사용량을 관찰하십시오.
var fs = require('fs');
const file = fs.createWriteStream('./big_file');
for(let i=0; i<= 1000000000; i++) {
file.write('Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n');
}
file.end();
//..............
fs.readFile('./big_file', (err, data) => {
if (err) throw err;
console.log("done !!");
});
사실, "done !!"이 표시되지 않습니다. 메시지. "readFile"은 버퍼가 파일 내용을 담을만큼 충분히 크지 않기 때문에 파일 내용을 읽을 수 없습니다.
이제 "readFile"대신 readStream을 사용하고 메모리 사용량을 모니터링하십시오.
참고 : 코드는 Pluralsight의 Samer buna Node 과정에서 가져옵니다.
잘 알려지지 않은 또 다른 점은 Node가 .NET에 fs.readFile
비해 사용 후 사용되지 않는 메모리를 정리하는 데 더 좋다고 생각한다는 것 fs.createReadStream
입니다. 어떤 것이 가장 잘 작동하는지 확인하려면 이것을 테스트해야합니다. 또한 Node의 모든 새 버전에서 이것이 더 나아 졌다는 것을 알고 있습니다 (즉, 이러한 유형의 상황에서 가비지 수집기가 더 똑똑해졌습니다).
'program story' 카테고리의 다른 글
project.lock.json은 무엇입니까? (0) | 2020.10.30 |
---|---|
정수를 정수로 변환하는 방법? (0) | 2020.10.30 |
재정의 된 메서드에 대한 C # 선택적 매개 변수 (0) | 2020.10.30 |
ASP.NET Core (.NET Core)와 ASP.NET Core (.NET Framework)의 차이점 (0) | 2020.10.30 |
jQuery 표시 / 숨기기가 visible : hidden 대신 display : none을 사용하는 이유는 무엇입니까? (0) | 2020.10.30 |