面试题答案
一键面试-
资源管理:
- 避免内存泄漏:
- 及时处理子进程的输出。子进程的
stdout
和stderr
流如果不处理,数据会在内存中堆积,可能导致内存泄漏。可以通过监听data
事件来读取输出并进行处理。 - 确保在子进程结束时释放相关资源。监听
exit
事件,在子进程退出后,清除任何相关的引用。
- 及时处理子进程的输出。子进程的
- 避免进程阻塞:
- 使用非阻塞 I/O 操作。Node.js 的
Child Process
模块默认是非阻塞的,但在处理子进程输出时,如果处理逻辑本身是阻塞的,也会导致问题。确保处理stdout
和stderr
数据的回调函数中执行的是异步非阻塞操作。 - 设置合适的
maxBuffer
。如果子进程输出的数据量过大,超过默认的maxBuffer
(1024 * 1024
字节),子进程会被杀死。可以根据实际情况适当增大这个值,但要注意内存的使用。
- 使用非阻塞 I/O 操作。Node.js 的
- 避免内存泄漏:
-
性能优化:
- 优化输入输出:
- 使用管道(
pipe
)操作。通过管道可以直接将文件流输送到gzip
命令的输入,而不是先读取整个文件到内存。这样可以减少内存的使用,并提高处理速度。 - 采用流式处理。对于大文件,流式处理比一次性读取整个文件更高效。在读取输入文件和处理子进程输出时都使用流的方式。
- 使用管道(
- 并行处理:如果系统资源允许,可以考虑并行处理多个文件的压缩任务,以充分利用多核 CPU 的优势。
- 优化输入输出:
-
关键代码片段:
const { exec } = require('child_process');
const fs = require('fs');
const path = require('path');
const inputFilePath = path.join(__dirname, 'largeFile.txt');
const outputFilePath = path.join(__dirname, 'largeFile.txt.gz');
// 创建写入流
const writeStream = fs.createWriteStream(outputFilePath);
// 使用管道将文件流直接输送到gzip命令
const child = exec('gzip', { maxBuffer: 1024 * 1024 * 10 });
// 监听子进程的stdout并写入输出文件
child.stdout.pipe(writeStream);
// 监听子进程的stderr
child.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
// 监听子进程的exit事件
child.on('exit', (code) => {
if (code === 0) {
console.log('文件压缩成功');
} else {
console.error(`子进程以代码 ${code} 退出`);
}
// 清理资源
writeStream.end();
});
// 使用管道将输入文件流输送到子进程的stdin
fs.createReadStream(inputFilePath).pipe(child.stdin);
// 关闭子进程的stdin
child.stdin.end();