node.js آخرالزمان حافظه: چرا برنامه شما روی پرونده های بزرگ می میرد (و چگونه می توان آن را برای همیشه متوقف کرد)

اسکریپت Node.js شما کاملاً با داده های آزمون کار می کند. سپس آن را به یک پرونده ورود به سیستم 10 گیگابایتی واقعی تغذیه می کنید. ناگهان: سقوطبشر بدون هشدار ، فقط ENOMEM
بشر در اینجا به همین دلیل است که حتی توسعه دهندگان فصلی این اشتباه را انجام می دهند – و راه حل ضد گلوله.
ریشه همه شر: fs.readFile
fs.readFile
معادل ریختن محتویات کامیون کمپرسی در اتاق نشیمن شماست. بار می کند هر بایت قبل از اینکه بتوانید آن را لمس کنید ، به رم وارد شوید. مشاهده:
// Processing a 3GB database dump? Enjoy 3GB RAM usage
fs.readFile('./mega-database.sql', 'utf8', (err, data) => {
parseSQL(data); // Hope you have 3GB to spare
});
- ابزارهای CLI پردازش تصادف CSV های بزرگ
- خط لوله داده روی پرونده های ویدیویی منفجر شوید
- خدمات پس زمینه ساعت 3 صبح بی صدا بمیرید
این “کد بد” نیست – چگونه است fs.readFile
عمل می کند و به همین دلیل است که سیستم تولید شما فاجعه بار شکست می خورد.
جریان: تکنیک Ninja Memory
جریان داده ها مانند یک کمربند نقاله – تکه های کوچک وارد می شوند ، پردازش می شوند ، سپس حافظه را برای همیشه رها می کنند. بدون انفجار RAM:
// Process 100GB file with ~50MB memory
const stream = fs.createReadStream('./giant-dataset.csv');
stream.on('data', (chunk) => {
analyzeChunk(chunk); // Work with 64KB-1MB pieces
});
stream.on('end', () => {
console.log('Processed entire file without going nuclear');
});
قتل عام دنیای واقعی: پردازش پرونده
رویکرد خودکشی (اشتباه مشترک)
// Data import script that crashes on big files
function importUsers() {
fs.readFile('./users.json', (err, data) => {
JSON.parse(data).forEach(insertIntoDatabase); // 💀
});
}
راهنمای زنده ماندن جریان (روش صحیح)
// Processes 50GB JSON file without memory issues
const ndjsonStream = fs.createReadStream('./users.ndjson');
const jsonParser = new TransformStream({ /* parse line-by-line */ });
ndjsonStream.pipe(jsonParser)
.on('data', (user) => insertIntoDatabase(user));
جریان ها پرونده های در مقیاس Terabyte را مانند آنها هیچ چیز ندارند. برنامه شما پاسخگو می ماند – بدون خراب شدن.
نکته حرفه ای: جریان + خطوط لوله = غیرقابل توقف
جریان ها را با node.js 'ترکیب کنید pipeline
برای پردازش ضد خطا:
const { pipeline } = require('stream');
const zlib = require('zlib');
// Compress 20GB log file with constant memory
pipeline(
fs.createReadStream('./server.log'),
zlib.createGzip(), // Compress chunk-by-chunk
fs.createWriteStream('./server.log.gz'),
(err) => {
if (err) console.error('Pipeline failed:', err);
else console.log('Compressed 20GB file like a boss');
}
);
چه زمانی از کدام سلاح استفاده کنیم
fs.readFile
(با دقت کار کنید):
- پرونده های پیکربندی (<5MB)
- دارایی های استاتیک کوچک (نمادها ، JSON کوچک)
- فقط وقتی کاملاً به تمام داده های حافظه احتیاج دارید
fs.createReadStream
(انتخاب پیش فرض):
- پردازش ورود به سیستم
- رمزگذاری رسانه/رمزگذاری
- واردات/صادرات پایگاه داده
- هر پرونده ای بزرگتر از رم تلفن شما
حقیقت خشن
fs.readFile
نسخه Node.js از یک اسلحه بارگذاری شده است – در محیط های کنترل شده ، در تولید کشنده است. جریان ها تکنیک های “پیشرفته” نیستند. آنها مهارت های اساسی بقای برای هر توسعه دهنده Node.js جدی.
دفعه بعد که می نویسید fs.readFile
، بپرسید: “آیا این پرونده هرگز رشد خواهد کرد؟” اگر جواب مثبت است (و همیشه هست) ، شما فقط نشت حافظه خود را پیدا کرده اید. تغییر به جریان –قبل از اینکه پیجر شما نیمه شب خاموش شود.