برنامه نویسی
Node.js وقفه های زمانی و نشت حافظه

معرفی
- بررسی اجمالی موضوع: روشی که Node.js با وقفه های زمانی مدیریت می کند می تواند منجر به نشت حافظه قابل توجهی شود.
-
زمینه:
setTimeoutAPI معمولا در هر دو مرورگر و Node.js استفاده می شود. در حالی که به طور مشابه کار می کند، Node.js یک شی پیچیده تر را برمی گرداند، که می تواند مشکلاتی ایجاد کند.
میانای برنامهسازی کاربردی پایه Timeout
-
در مرورگرها:
- رمز: یک عدد ساده که نشان دهنده شناسه وقفه است.
const token = setTimeout(() => {}, 100);
clearTimeout(token);
-
در Node.js:
- رمز: یک شی با چندین ویژگی و مرجع.
const token = setTimeout(() => {});
console.log(token);
نمونه ای از Timeout Object در Node.js
Timeout {
_idleTimeout: 1,
_idlePrev: [TimersList],
_idleNext: [TimersList],
_idleStart: 4312,
_onTimeout: [Function (anonymous)],
_timerArgs: undefined,
_repeat: null,
_destroyed: false,
[Symbol(refed)]: true,
[Symbol(kHasPrimitive)]: false,
[Symbol(asyncId)]: 78,
[Symbol(triggerId)]: 6
}
- خواص: شامل ابرداده در مورد مهلت زمانی، ارجاع به اشیاء دیگر و توابع است.
- موضوع: این ارجاعات مانع از جمعآوری زبالههای شی زمانبندی میشوند، حتی پس از پاکسازی یا تکمیل.
مثال کلاسی که منجر به نشت حافظه می شود
class MyThing {
constructor() {
this.timeout = setTimeout(() => { /*...*/ }, INTERVAL);
}
clearTimeout() {
clearTimeout(this.timeout);
}
}
-
مرجع دائمی:
Timeoutشی در حافظه باقی می ماند زیرا یک شی با ارجاع است نه یک عدد ساده.
تاثیر AsyncLocalStorage
- AsyncLocalStorage: یک API جدید که حالت اضافی را به وقفه ها، وعده ها و سایر عملیات ناهمزمان متصل می کند.
- مثال:
const { AsyncLocalStorage } = require('node:async_hooks');
const als = new AsyncLocalStorage();
let t;
als.run([...Array(10000)], () => {
t = setTimeout(() => {
const theArray = als.getStore();
}, 100);
});
- نتیجه: اکنون شی timeout ارجاع به یک آرایه بزرگ را از طریق یک نماد سفارشی دارد که حتی پس از پاک شدن یا تکمیل مهلت زمانی باقی می ماند.
Timeout {
[Symbol(kResourceStore)]: [Array] // reference to that large array is held here
}
راه حل پیشنهادی: استفاده از شناسه های اولیه
-
رویکرد: تبدیل کنید
Timeoutبرای جلوگیری از نگهداری ارجاع به یک عدد اعتراض کنید.
class MyThing {
constructor() {
this.timeout = +setTimeout(() => { /*...*/ }, INTERVAL);
}
clearTimeout() {
clearTimeout(this.timeout);
}
}
- مشکل فعلی: به دلیل وجود یک اشکال در Node.js، این رویکرد در حال حاضر باعث نشت حافظه غیرقابل بازیابی می شود.
راه حل: باطل کردن تهاجمی
- استراتژی: برای کمک به جمع آوری زباله، مرجع وقفه را به صورت دستی پاک کنید.
class MyThing {
constructor() {
this.timeout = setTimeout(() => {
this.timeout = null;
// Additional logic
}, INTERVAL);
}
clearTimeout() {
if (this.timeout) {
clearTimeout(this.timeout);
this.timeout = null;
}
}
}
مفاهیم گسترده تر
- موضوع گسترده: بسیاری از برنامههای Node.js از وقفهها و بازههای زمانی استفاده میکنند که خطر نشت حافظه را افزایش میدهد.
- بارگذاری مجدد کد داغ: تایم اوت های طولانی مدت یا مکرر می تواند مشکل را تشدید کند.
-
راه حل Next.js: وصله ها
setTimeoutوsetIntervalبرای پاک کردن فواصل دوره ای، اما همچنان می تواند با اشکال Node.js مواجه شود.
ملاحظات بلند مدت
-
بهبودهای API: Node.js می تواند یک شی پراکسی سبک وزن را به جای کامل برگرداند
Timeoutشی، که مدیریت آن آسان تر و کمتر مستعد نشت است. - مدیریت AsyncLocalStorage: ارائه API برای جلوگیری از انتشار حالت غیر ضروری می تواند به کاهش نشت حافظه کمک کند.
نتیجه
- مدیریت حافظه: توسعهدهندگان باید بهدقت زمانبندیها و مراجع آنها را مدیریت کنند تا از نشت حافظه جلوگیری کنند.
- در انتظار رفع Node.js: رفع دائمی باگ Node.js برای مدیریت موثر حافظه بسیار مهم است.
درک این تفاوتها و اتخاذ بهترین روشها میتواند به کاهش نشت حافظه در برنامههای Node.js کمک کند و عملکرد و ثبات بهتری را تضمین کند.



