การดู : 0

12/04/2026 18:16น.

JS2GO EP.40 การ Optimize Performance ของโค้ด: Go vs JavaScript ภาษาไหนเร็วกว่า?

JS2GO EP.40 การ Optimize Performance ของโค้ด: Go vs JavaScript ภาษาไหนเร็วกว่า?

#Garbage Collection

#Benchmark

#Optimize Performance

#JavaScript

#Go

ในโลกของการพัฒนาโปรแกรม “ความเร็ว” คือหัวใจของทั้ง 🧠 ประสบการณ์ผู้ใช้ (UX) และ ⚙️ ประสิทธิภาพระบบ (System Performance)

 

โดยเฉพาะอย่างยิ่งในระบบที่ต้อง

  • จัดการข้อมูลจำนวนมหาศาล
  • รองรับคำขอพร้อมกันหลายพันครั้ง
  • หรือประมวลผลงานคำนวณหนัก (CPU-intensive tasks)

 

ในบทความนี้ เราจะมาดูแนวทางการเพิ่มประสิทธิภาพของโค้ดทั้งใน JavaScript (Node.js) และ Go (Golang) พร้อมตัวอย่างจริง เทคนิคการ profiling และการ benchmark เพื่อค้นหาว่า “ภาษาไหนทำงานได้เร็วกว่า” ในสถานการณ์ต่าง ๆ 🧩

 

1. ภาพรวมสถาปัตยกรรมของทั้งสองภาษา

 

ประเด็นJavaScript (Node.js)Go (Golang)
Execution ModelSingle-threaded (Event Loop)Multi-threaded (Goroutines)
CompilationJust-In-Time (JIT) ผ่าน V8 EngineAhead-Of-Time (AOT) Compiler
ConcurrencyAsync/await, PromiseGoroutines + Channels
Memory ModelManaged via V8 Garbage CollectorStatic allocation + GC
เหมาะกับงานประเภทI/O-boundCPU-bound & Parallel workloads

 

🔍 สรุปสั้น ๆ:

  • Node.js เหมาะกับงานที่ “รอ I/O” เช่น API, file I/O, หรือ network request
  • Go เหมาะกับงาน “คำนวณหนัก” และระบบที่ต้องการ throughput สูง

 

2. Garbage Collection (GC)

 

Garbage Collection (GC) คือกลไกในการคืนหน่วยความจำของ object ที่ไม่ได้ใช้งานแล้ว

 

🔹 Node.js

Node.js ใช้ V8 Engine GC แบบ Generational + Incremental Collection

ช่วยลด pause time ระหว่างการเก็บกวาดหน่วยความจำ

 

global.gc(); // trigger GC (ต้องเปิดด้วย flag --expose-gc)
console.log(process.memoryUsage());

 

แนวทางเพิ่มประสิทธิภาพ GC ใน Node.js:
✅ หลีกเลี่ยง object ซ้อนลึกเกินไป (nested object)
✅ ใช้ Buffer แทน string สำหรับข้อมูล binary
✅ หลีกเลี่ยงการสร้าง object จำนวนมากภายใน loop
✅ ใช้ WeakMap หรือ WeakSet สำหรับ cache ที่ไม่ต้องถือ reference

 

🔹 Go

Go ใช้ Concurrent Garbage Collector (non-stop world) ที่ออกแบบให้ทำงานไปพร้อมกับโปรแกรมหลักจึงแทบไม่เกิด pause เหมือนใน Node.js

 

package main

import (
	"fmt"
	"runtime"
)

func main() {
	m := &runtime.MemStats{}
	runtime.ReadMemStats(m)
	fmt.Printf("Alloc = %v KB\n", m.Alloc/1024)
}

 

จุดแข็งของ GC ใน Go:
✅ ทำงานพร้อมกับ goroutine อื่น ๆ (concurrent GC)
✅ Latency ต่ำมาก เหมาะกับระบบที่ต้อง “ออนไลน์ตลอดเวลา”
✅ เสถียรในระบบ production ที่มี load สูง เช่น API server หรือ streaming system

 

3. Memory Profiling

 

การวิเคราะห์หน่วยความจำช่วยให้เราทราบว่า “โค้ดส่วนไหนใช้หน่วยความจำมากเกินไป” และสามารถลด bottleneck ได้ตรงจุด

 

🔹 Node.js: Chrome DevTools / Clinic.js

 

เปิดโหมดวิเคราะห์ได้ด้วย flag:

node --inspect index.js

 

หรือใช้เครื่องมือ Clinic.js จาก NearForm

npx clinic doctor -- node index.js

 

จะได้กราฟแสดง Heap Usage, Event Loop Delay, และ GC Timeline

 

🔹 Go: pprof

 

Go มีเครื่องมือ pprof ติดมาในตัว ใช้วิเคราะห์ CPU, Memory, และ Block Profile

import (
	"net/http"
	_ "net/http/pprof"
)

func main() {
	go func() {
		http.ListenAndServe("localhost:6060", nil)
	}()
	select {}
}

 

เปิดดูใน browser ได้ที่
👉 http://localhost:6060/debug/pprof/heap

 

ข้อดี:
✅ ไม่ต้องติดตั้งเพิ่ม (อยู่ใน standard library)
✅ ใช้ใน production ได้โดยไม่กระทบ performance
✅ วิเคราะห์ได้ทั้ง CPU, Heap, Goroutine และ Mutex

 

4. Parallel Execution (การทำงานแบบขนาน)

 

🔹 JavaScript

แม้ Node.js จะเป็น single-threaded แต่สามารถทำงานแบบขนานได้ด้วย Worker Threads

 

const { Worker } = require('worker_threads');

new Worker(`
  const { parentPort } = require('worker_threads');
  let sum = 0;
  for (let i = 0; i < 1e7; i++) sum += i;
  parentPort.postMessage(sum);
`, { eval: true })
.on('message', result => console.log('✅ Result:', result));

 

ข้อจำกัด:
❌ ต้องสร้าง thread ใหม่ทุกครั้ง (overhead สูง)
❌ ใช้ message passing ในการสื่อสารระหว่าง thread

 

🔹 Go

Go รองรับการประมวลผลแบบขนานโดยธรรมชาติผ่าน Goroutines

 

package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	sum := 0
	mu := sync.Mutex{}

	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			mu.Lock()
			for j := 0; j < 1e6; j++ {
				sum += j
			}
			mu.Unlock()
		}()
	}

	wg.Wait()
	fmt.Println("✅ Result:", sum)
}

 

ข้อดีของ Go:
✅ ไม่ต้องจัดการ thread เอง (runtime จัดการให้)
✅ ใช้หน่วยความจำเพียง ~2KB ต่อ goroutine
✅ รองรับการทำงานพร้อมกันหลายพัน task ได้ในระบบเดียว

 

5. Benchmark Tools

 

🔹 Node.js

 

ใช้ console.time() / console.timeEnd() สำหรับ quick test

console.time("Loop");
for (let i = 0; i < 1e7; i++) {}
console.timeEnd("Loop");

 

หรือใช้ Benchmark.js สำหรับการทดสอบที่แม่นยำกว่า

npm install benchmark

 

🔹 Go

 

Go มีระบบ benchmark ในตัว (ผ่าน package testing)

package main

import "testing"

func Sum() {
	for i := 0; i < 1e7; i++ {}
}

func BenchmarkSum(b *testing.B) {
	for i := 0; i < b.N; i++ {
		Sum()
	}
}

 

รันด้วยคำสั่ง:

go test -bench=.

 

6. ผลการทดสอบเปรียบเทียบ (จาก benchmark จริง)

 

การทดสอบNode.jsGoหมายเหตุ
การอ่านไฟล์ (I/O)⚡ เร็วมาก⚡ เร็วมากต่างกันน้อยมาก
งานคำนวณหนัก (CPU)🐢 ช้ากว่า🚀 เร็วกว่ามากGo รันแบบ parallel ได้จริง
Memory usageใช้มากกว่า ~2xใช้น้อยกว่าStatic allocation
Startup timeเร็วกว่ามากช้ากว่าเล็กน้อยNode.js = dynamic runtime
Long-running stabilityปานกลางดีเยี่ยมGC ของ Go เสถียรกว่า

 

7. เทคนิคการ Optimize ของแต่ละภาษา

 

🟨 JavaScript (Node.js)

✅ ใช้ asynchronous I/O ให้มากที่สุด (fs.promises, fetch, etc.)
✅ ใช้ Cluster / Worker Threads สำหรับงาน CPU
✅ หลีกเลี่ยงการสร้าง object ซ้ำใน loop
✅ ใช้ DevTools / Clinic.js ตรวจสอบ event loop lag
✅ ใช้ caching (เช่น Redis หรือ in-memory) ลด load ที่ซ้ำซ้อน

 

🟦 Go (Golang)

✅ ใช้ Goroutines แทน Thread
✅ ใช้ Buffered Channels เพื่อลด blocking
✅ ใช้ sync.Pool สำหรับ reuse object ขนาดใหญ่
✅ ใช้ pprof วิเคราะห์ bottleneck จริง
✅ หลีกเลี่ยง allocation ซ้ำโดย pre-allocate slice หรือ struct

 

8. สรุปเปรียบเทียบ

 

ประเด็นNode.jsGo
ความเร็วในการเริ่มต้น⚡ เร็วปานกลาง
การประมวลผลแบบขนานจำกัด (ผ่าน worker threads)เต็มรูปแบบ (ผ่าน goroutines)
การใช้หน่วยความจำสูงกว่าต่ำกว่า
เหมาะกับงานประเภทWeb / API / I/O-heavyBackend / CPU-heavy / Data pipeline
การ Optimizeผ่าน async tuning & DevToolsผ่าน Goroutines, Profiling, Benchmark

 

💡 สรุปสุดท้าย:

  • ถ้าระบบของคุณเน้น I/O-intensive เช่น API, Web Server → ใช้ Node.js
  • ถ้าระบบของคุณเน้น High Performance, Low Latency, และ Concurrency → Go คือคำตอบที่ชัดเจน 💥

 


 

ตอนต่อไป

 

ใน EP.41 ของซีรีส์ JS2GO เราจะพาคุณก้าวสู่ระดับถัดไปกับหัวข้อ 🧩 “การจัดการ Concurrency Patterns ขั้นสูงใน Go และ JavaScript” คุณจะได้เรียนรู้ Patterns สำคัญ เช่น Worker Pool, Fan-in/Fan-out, Rate Limiter และ Pipeline Optimization เพื่อออกแบบระบบที่รองรับโหลดสูงได้อย่างมีประสิทธิภาพในระดับ Production 🚀