Skip to content

emka.web.id

writing knowledge, recording civilization

Menu
  • Home
  • Tutorial
  • Search
Menu

Sering Alami Bug Leak Memory di NodeJS? Coba Cek function setTimeout()!

Posted on June 13, 2024

Bagi developer Node.js, artikel ini penting untuk diketahui. Masalah yang dibahas di sini dapat menimbulkan banyak kesulitan. Ini terkait dengan cara Node.js menangani timeout. Singkatnya, Anda bisa dengan mudah membuat kebocoran memori [1] menggunakan fungsi setTimeout di Node.js.

setTimeout: Fungsi Jadul dengan Masalah Baru

Anda mungkin sudah familiar dengan fungsi setTimeout. Fungsi ini telah disediakan oleh browser selama bertahun-tahun. Fungsinya cukup mudah: Anda menjadwalkan fungsi untuk dipanggil nanti, dan Anda mendapatkan token yang dapat digunakan untuk menghapus timeout tersebut nantinya. Contoh singkatnya:

const token = setTimeout(() => {}, 100);
clearTimeout(token);

Di browser, token yang dikembalikan hanyalah sebuah angka. Namun, jika Anda melakukan hal yang sama di Node.js, token tersebut ternyata menjadi objek Timeout yang sebenarnya:

> setTimeout(() => {})
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
}

Hal ini “membocorkan” sebagian internal dari bagaimana timeout diimplementasikan secara internal. Selama beberapa tahun terakhir, hal ini mungkin tidak menjadi masalah. Biasanya Anda menggunakan objek ini terutama sebagai token, mirip dengan yang Anda lakukan dengan angka. Mungkin terlihat seperti ini:

class MyThing {
  constructor() {
    this.timeout = setTimeout(() => { ... }, INTERVAL);
  }

  clearTimeout() {
    clearTimeout(this.timeout);
  }
}

Awas, Objek Timeout Bisa Bocor!

Sepanjang masa pakai MyThing, bahkan setelah clearTimeout dipanggil atau timeout selesai berjalan, objek tersebut tetap memegang timeout ini. Saat selesai atau dibatalkan, timeout ditandai sebagai “destroyed” dalam Node.js dan dihapus dari pelacakan internalnya. Namun, yang terjadi adalah objek Timeout ini sebenarnya bertahan sampai seseorang menimpa atau menghapus referensi this.timeout. Hal ini terjadi karena objek Timeout yang sebenarnya yang ditahan, bukan hanya sebuah token.

Lebih lanjut, ini berarti garbage collector (pengumpul sampah) tidak akan benar-benar mengumpulkan objek ini dan semua yang direferensikannya. Ini tampaknya tidak terlalu buruk karena objek Timeout terlihat agak besar, tetapi tidak terlalu besar. Bagian yang paling bermasalah kemungkinan besar adalah member _onTimeout di dalamnya yang mungkin menarik closure (penutupan fungsi), tetapi pada praktiknya mungkin sebagian besar baik-baik saja.

Namun, objek timeout dapat bertindak sebagai wadah untuk lebih banyak state (keadaan) yang tidak begitu jelas. API baru yang telah ditambahkan selama beberapa tahun terakhir disebut AsyncLocalStorage yang mendapatkan daya tarik, sedang melampirkan state tambahan ke semua timeout yang aktif. Penyimpanan lokal asinkron diimplementasikan dengan cara di mana timeout (dan promise serta konstruksi serupa) meneruskan state tersembunyi hingga dijalankan:

const { AsyncLocalStorage } = require('node:async_hooks');
const als = new AsyncLocalStorage();

let t;
als.run([...Array(10000)], () => {
  t = setTimeout(() => {
    //
    const theArray = als.getStore();
    assert(theArray.length === 10000);
  }, 10);
});

console.log(t);

Ketika Anda menjalankan kode ini, Anda akan melihat bahwa Timeout menyimpan referensi ke array besar ini:

Timeout {
  _idleTimeout: 100,
  _idlePrev: [TimersList],
  _idleNext: [TimersList],
  _idleStart: 10,
  _onTimeout: [Function (anonymous)],
  _timerArgs: undefined,
  _repeat: null,
  _destroyed: false,
  [Symbol(refed)]: true,
  [Symbol(kHasPrimitive)]: false,
  [Symbol(asyncId)]: 2,
  [Symbol(triggerId)]: 1,
  [Symbol(kResourceStore)]: [Array] // referensi ke array besar disimpan di sini
}

Ini karena setiap penyimpanan lokal asinkron yang dibuat mendaftarkan dirinya sendiri dengan timeout dengan Symbol(kResourceStore) khusus yang bahkan tetap ada di sana setelah timeout dihapus atau timeout selesai berjalan. Ini

Terbaru

  • Redox OS: A Rust-Based Microkernel Operating System (And How It Differs from Linux)
  • Canonical Is Bringing Back Ubuntu Core Desktop — This Time With a Clearer Plan
  • systemd Officially Adds Support for Rust Components
  • Rocky Linux Creator Builds a Brand-New “Not Linux” Kernel in 11 Days Using AI
  • Building a local AI agent in Workshop on Ubuntu 26.10
  • Omarchy 4.5 RC: 5 New Apps That Actually Look Useful
  • Worth It! Switching from Fedora KDE to Kubuntu
  • I’m Happy Using ‘Herdr’, The Fastest Growing Devtool written in Rust
  • Testing Goose on Omarchy Linux (App & CLI): The Open-Source Solution for Daily Task Automation
  • GNOME Founder Attacks Omarchy Founder as “Lazy, Racist, Ignorant”
  • Why I Stopped Using Plain Command Line Docker and Use Portainer 3.0 To Make My Home Projects Fun Again
  • Why I Switched to a Proper Firewall Box with OPNSense for My Homelab Stuff
  • Fixing Windows Error 0x80070005 Hyper-V Export Access Denied Error the Right Way
  • Fixing Hyper V Export Errors and Building a Better Virtual Machine Setup (error 0x80070002, 0x80070005)
  • Fixing the Dreaded Windows Audio Service Stuck on Stopping Error
  • Windows SIM Error, Unknown error 0xc1420127
  • How I’m Building a Cat Breeding Management App with Python Qt6 + Microsoft Litebox, in 1 Week
  • Why Windows Keeps Nuking Your GPU Drivers (And How to Take Back Control)
  • Why I Finally Ditched Mainstream Windows Cleaners (And Why I Use ‘Kudu’ Instead)
  • AI Made Everything Faster, Including Bad Decisions
  • Raspberry Pi Desktop Available of PC and Mac, Based on Debian 13
  • Why I Stopped Yelling at My PC When Error; Getting Windows 11 Voice Isolation and Access to Actually Work
  • Berobat Kanker ke Malaysia: Berapa Biayanya dan Apa Saja yang Perlu Disiapkan?
  • Stop Sending Every Prompt to the Biggest AI Model You Can Find
  • Stop Building AI Agents from Scratch: My Pick for the Best Native Windows Setup
  • Jev Is Faster and Cheaper, But I Still Recommend Clef. Here’s Why.
  • Weird XCP-NG Bug or Feature? Enable Maintenance Mode = Host Not Enough Memory
  • Vinix OS: Another OS That Want to Beat Linux, Try it!
  • Trying NVX, An Ultra-Light Micro-VM Sandbox from Microsoft
  • Learning NocoDB from Scratch: Creating a Simple Greenhouse App
  • Canonical: Ubuntu coming soon to Snapdragon X2 Series platforms
  • Finally, wolfSSL adds post-quantum algorithms!
  • How to Run Gemma Embedding Models Using Docker
  • Deploy Nginx Rootful Container with Podman
  • How to Sandboxing Browser on Linux Desktop with Flatpak
  • Liquid AI Unveils LFM3: A New Generation of Multimodal Foundation Models Built Small Device
  • Google DeepMind Unveils Genie 4: The Most Advanced Real-Time Interactive World Model Yet
  • Building Long-Running AI Agents with Pi Durable: An AI SRE Agent Example
  • Prompt AI: Impressionist Portrait Art of a Woman
  • Prompt AI: Stylish Man Walking Double Exposure Photo
  • Alvin Tedjo menang jadi Wali Kota di Kanada, wong Indonesia kok iso dadi pemimpin kota gede?
  • Messi vs Ronaldo rebutan gelar Ballon d’Or of All Time, siapa yang paling jago menurut fans?
  • Ini Dia QR Link Dana Kaget 400K, 27 Oktober 2026
  • Fresh! Ini Biodata dan Fakta Unik dari Member No Na
  • Inilah Rekomendasi 10 Drama Jepang Wajib Tonton November 2026

©2026 emka.web.id | Design: Newspaperly WordPress Theme