ข้ามไปยังเนื้อหา

ไม่มี Garbage Collector

Node.js, Python, Go, Java, C# — ทุกภาษา mainstream ที่คุณน่าจะเคยเขียนทำงานบน GC GC สแกน memory เป็นระยะ หา object ที่ไม่ถูกใช้แล้ว และคืน memory แบบนี้ปลอดภัยและสะดวก แต่มีต้นทุน:

  • Pause latency: GC stop-the-world pause สามารถ spike latency ได้อย่างคาดเดาไม่ได้
  • Throughput overhead: งาน GC แข่งกับโปรแกรมของคุณสำหรับ CPU time
  • Memory overhead: GC runtime เก็บ data structure พิเศษเพื่อ track live object
  • Non-determinism: คุณไม่สามารถทำนายได้ว่า object จะถูกคืนเมื่อไหร่

Rust ไม่มีสิ่งเหล่านี้เลย แต่ได้ memory safety มาจาก ownership model ล้วน ๆ ตัว Compiler พิสูจน์แบบ static ว่า memory ถูกจัดการถูกต้อง แล้ว generate โค้ดคืน allocation แต่ละก้อนในจุดที่ถูกต้องพอดี

คุณ implement Drop trait เพื่อ run cleanup logic แบบ custom เมื่อ value หลุด scope — เทียบเท่า destructor ของ Rust:

TypeScript
// TypeScript — ไม่มี deterministic cleanup โดย default
class Resource {
constructor(private name: string) {
console.log(`acquiring: ${name}`);
}
// ไม่มี guaranteed destructor ต้องใช้ try/finally หรือ 'using' (ES2023)
release() {
console.log(`releasing: ${this.name}`);
}
}
function useResource() {
const r = new Resource("file handle");
console.log("using resource");
r.release(); // ลืมเรียกได้ง่าย; ไม่ถูกเรียกถ้า exception
}
useResource();
Rust
struct Resource {
name: String,
}
impl Resource {
fn new(name: &str) -> Self {
println!("acquiring: {}", name);
Resource { name: name.to_string() }
}
}
impl Drop for Resource {
fn drop(&mut self) {
println!("releasing: {}", self.name);
}
}
fn main() {
println!("start");
{
let _r = Resource::new("file handle");
println!("using resource");
} // _r ถูก drop ที่นี่ — drop() ถูกเรียกอัตโนมัติ
println!("end — resource already released");
}
flowchart TD
  subgraph TS["TypeScript / Node.js"]
    a1["Object created"] --> a2["..."] --> a3["GC runs at some unknown time"] --> a4["memory freed"]
  end
  subgraph RS["Rust"]
    b1["Value created"] --> b2["owner goes out of scope"] --> b3["memory freed IMMEDIATELY"]
  end
Deterministic vs non-deterministic cleanup

ความแน่นอนนี้คือเหตุผลที่ Rust ถูกใช้สำหรับ OS kernel, game engine, WebAssembly runtime, และ database เมื่อ file handle หรือ network socket ต้องถูกปิดในจุดที่แน่นอน “GC จะจัดการในที่สุด” ไม่ใช่คำตอบที่ยอมรับได้

struct Resource {
name: String,
}
impl Resource {
fn new(name: &str) -> Self {
println!("acquiring: {}", name);
Resource { name: name.to_string() }
}
}
impl Drop for Resource {
fn drop(&mut self) {
println!("releasing: {}", self.name);
}
}
fn main() {
println!("start");
{
let _r = Resource::new("file handle");
println!("using resource");
}
println!("end — resource already released");
}
RAII ย่อมาจากอะไร และหมายความว่าอะไรใน Rust?
ฟังก์ชัน `drop` ของ value ถูกเรียกเมื่อไหร่ใน Rust?
ข้อดีหลักของ ownership-based memory model ของ Rust เมื่อเทียบกับ garbage collector คืออะไร?