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

معرفی
- بررسی اجمالی موضوع: روشی که Node.js با وقفه های زمانی مدیریت می کند می تواند منجر به نشت حافظه قابل توجهی شود.
-
زمینه:
setTimeout
API معمولا در هر دو مرورگر و 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 کمک کند و عملکرد و ثبات بهتری را تضمین کند.