Coding agent ต้องใช้ RAM เท่าไหร่บน VPS เพื่อให้รันได้ลื่น
Coding agent ที่ทำงานตลอดเวลาต้องการ RAM อย่างน้อย 4 GB และ 2 vCPU แต่การ build โปรเจกต์และ language server จะเป็นตัวการหลักที่ทำให้เครื่องค้างและหน่วยความจำเต็ม
Coding agent VPS ต้องการ RAM เท่าใด
เริ่มต้นที่ 4 GB ของ RAM และ 2 vCPU สำหรับ coding agent ที่ทำงานตลอดเวลาใน repository หนึ่งแห่ง ให้ขยับไปที่ 8 GB และ 4 vCPU ทันทีที่มี language server หรือการ build ด้วย Docker เข้ามาร่วมใน session ซึ่งเป็นสิ่งที่เกิดขึ้นในวันแรกสำหรับ repository ส่วนใหญ่ ตัว process ของ agent เองนั้นใช้ทรัพยากรน้อย สิ่งที่ทำให้ทรัพยากรในเครื่องเต็มคือ toolchain ที่ agent เรียกใช้งานแทนคุณ
ข้อมูลเบื้องหลังแผนภูมินี้
[
{
"plan": "Minimum viable",
"ram_gb": 4,
"vcpu": 2,
"disk_gb": 50
},
{
"plan": "Comfortable",
"ram_gb": 8,
"vcpu": 4,
"disk_gb": 100
},
{
"plan": "Team, 4 sessions",
"ram_gb": 16,
"vcpu": 8,
"disk_gb": 200
}
]ทุกแถวข้างต้นตั้งสมมติฐานว่าโมเดลทำงานที่อื่น โดยอยู่หลัง API ที่คุณเรียกผ่านเครือข่าย สมมติฐานนี้เป็นตัวตัดสินขนาดของระบบทั้งหมด ดังนั้นควรพิจารณาประเด็นนี้ให้ชัดเจนก่อนเป็นอันดับแรก
คุณกำลังรัน Agent หรือรัน Model กันแน่?
Coding agent ที่เรียกใช้งาน cloud model คือ network client ที่มี shell เชื่อมต่ออยู่ มันจะส่งไฟล์และแผนงานไปยัง API รอการตอบกลับ จากนั้นจึงแก้ไขไฟล์และรันคำสั่งในเครื่อง ในระหว่างที่รอ มันแทบไม่ได้ใช้ CPU เลย หน่วยความจำที่ตัวมันใช้มีขนาดเพียงไม่กี่ร้อยเมกะไบต์ นี่จึงเป็นเหตุผลว่าทำไมเครื่องที่มี CPU ระดับเริ่มต้นถึงเป็นเครื่องที่เหมาะสม
การรัน model ด้วยตัวเองเป็นผลิตภัณฑ์ที่ต่างออกไปและต้องใช้ฮาร์ดแวร์ที่ต่างกัน โดย weights จะถูกเก็บไว้ในหน่วยความจำตราบเท่าที่เซิร์ฟเวอร์ยังเปิดอยู่ Model ขนาด 7 พันล้านพารามิเตอร์ที่ทำ quantization เหลือ 4 บิต จะมีขนาด weights ประมาณ 4 GB (Llama 2 7B มีขนาด 3.83 GB ในรูปแบบ Q4_0 และ 4.08 GB ในรูปแบบ Q4_K_M) และผู้เผยแพร่ระบุว่าต้องใช้ RAM ตั้งแต่ 6.3 ถึง 6.6 GB เพื่อรันโดยไม่มี GPU เมื่อรวม overhead ของ runtime แล้ว บริบทที่ยาวขึ้นต้องการหน่วยความจำมากขึ้น เพราะ key/value cache จะเพิ่มขึ้นตามความยาวของบริบท ในกรณีที่ใช้เพียง CPU, vCPU ที่ใช้ร่วมกันจะสร้างได้เพียงไม่กี่ token ต่อวินาที ในขณะที่งานของ agent หนึ่งงานอาจสร้าง token ได้หลายพัน ดังนั้นงานที่ใช้เวลาไม่ถึงนาทีผ่าน API อาจใช้เวลาเกือบชั่วโมงหากทำในเครื่อง หากนั่นคือสิ่งที่คุณต้องการ ให้เลือกขนาดเครื่องตาม VRAM (หน่วยความจำวิดีโอบน GPU) และอ่าน สิ่งที่ VPS ที่มี GPU มอบให้คุณจริงๆ แทนหน้านี้
เนื้อหาทั้งหมดด้านล่างนี้ตั้งอยู่บนสมมติฐานของการใช้ cloud model
สิ่งที่ใช้หน่วยความจำจริง
ข้อมูลเบื้องหลังแผนภูมินี้
[
{
"label": "Agent CLI process, idle",
"typical_mb": 250,
"peak_mb": 600
},
{
"label": "TypeScript language server",
"typical_mb": 700,
"peak_mb": 2000
},
{
"label": "rust-analyzer, large workspace",
"typical_mb": 1200,
"peak_mb": 4000
},
{
"label": "Headless Chrome, one tab",
"typical_mb": 350,
"peak_mb": 900
},
{
"label": "Node test run, 4 workers",
"typical_mb": 1600,
"peak_mb": 3000
},
{
"label": "Docker image build",
"typical_mb": 800,
"peak_mb": 2500
}
]ตัวเลขเหล่านี้เป็นค่าที่เผยแพร่โดยทั่วไปสำหรับโปรเจกต์ขนาดกลาง ให้ถือว่าเป็นแนวทางโดยประมาณ ไม่ใช่การรับประกันสำหรับโค้ดของคุณ
ตารางนี้มี 6 แถว และตัว agent เป็นส่วนที่ใช้ทรัพยากรน้อยที่สุด โดยจะอยู่ที่ประมาณ 250 MB ในขณะที่ไม่ได้ทำงาน เนื่องจากเก็บเพียงบทสนทนาและแคชไฟล์ขนาดเล็กไว้เท่านั้น TypeScript language server จะใช้หน่วยความจำประมาณ 2000 MB ในระหว่างการทำ index เพราะต้องสร้าง type graph สำหรับทุกไฟล์ที่เข้าถึงได้จาก tsconfig.json ของคุณ แล้วเก็บกราฟนั้นไว้ในหน่วยความจำเพื่อตอบสนองคำขอถัดไปได้อย่างรวดเร็ว rust-analyzer ใน workspace ขนาดใหญ่มักจะใช้หน่วยความจำเกิน 4000 MB ด้วยเหตุผลเดียวกัน โดยครอบคลุมทุก crate ใน workspace
Headless Chrome ใช้หน่วยความจำประมาณ 350 MB สำหรับตัวเบราว์เซอร์รวมหนึ่งแท็บ และทุกแท็บที่เปิดเพิ่มจะเป็นอีกหนึ่ง process ของระบบปฏิบัติการ การรัน Node test ด้วย worker สี่ตัวจะเท่ากับมี Node process สี่ตัว ดังนั้นจึงใช้หน่วยความจำสูงสุดใกล้เคียง 3000 MB การ build Docker image จะใช้หน่วยความจำสูงสุดใกล้เคียง 2500 MB เนื่องจากกระบวนการ build จะรัน compiler ของโปรเจกต์คุณเองภายใน container ในขณะที่ daemon ทำการเขียน layer ต่างๆ
วัดค่าเหล่านี้ใน repository ของคุณเองก่อนตัดสินใจซื้อ
sudo apt update && sudo apt install -y time
/usr/bin/time -v -o /tmp/build.rusage npm run build
grep "Maximum resident set size" /tmp/build.rusageผลลัพธ์ที่ได้จะเป็น Maximum resident set size (kbytes): 1842160 ให้นำไปหารด้วย 1024 เพื่อแปลงเป็นหน่วย MB คำสั่ง GNU time จะรายงานค่าของ process เดียวที่ใหญ่ที่สุดที่มันรออยู่ ดังนั้นการ build ที่มีการ fork worker สี่ตัวจะแสดงค่าที่ต่ำกว่าความเป็นจริง สำหรับกรณีดังกล่าว ให้ตรวจสอบทั้งระบบจาก shell อีกหน้าต่างหนึ่งด้วย free -h หรือ systemd-cgtop -m
ให้ดูที่คอลัมน์ available ของ free -h ไม่ใช่คอลัมน์ free เนื่องจาก Linux จะนำหน้าหน่วยความจำที่ว่างอยู่ทั้งหมดไปใช้เป็น disk cache ดังนั้นค่า free จึงมีขนาดเล็กในเครื่องที่ทำงานปกติและไม่ได้บ่งบอกอะไร ส่วน available คือปริมาณหน่วยความจำที่ process ใหม่สามารถเรียกใช้ได้จริง
การกำหนดค่าสามรูปแบบที่ใช้งานได้จริง
ระดับเริ่มต้นขั้นต่ำ: 4 GB RAM, 2 vCPU, 50 GB disk. รองรับหนึ่ง agent session, หนึ่ง repository, หนึ่ง language server และงาน build ที่คุณรอได้ ระดับนี้ใช้งานได้จริง แต่จะเจอกับ out-of-memory killer ทันทีที่มีการรัน test ขนาดใหญ่พร้อมกับ indexing ของ language server ให้เพิ่ม swap และจำกัดจำนวน build workers ของคุณ
ระดับใช้งานสะดวก: 8 GB RAM, 4 vCPU, 100 GB disk. รองรับหนึ่ง agent, Docker, headless browser สำหรับการทดสอบ และมีพื้นที่เหลือสำหรับช่วงที่งาน build พุ่งสูงขึ้น นี่คือระดับที่นักพัฒนาที่ทำงานคนเดียวส่วนใหญ่ควรเลือกซื้อ การเพิ่มจำนวน vCPU เป็นสองเท่าจะช่วยลดระยะเวลารอ build ลงได้ประมาณครึ่งหนึ่ง ซึ่งคุณจะรู้สึกถึงความแตกต่างนี้ได้บ่อยกว่าการเพิ่มหน่วยความจำ
ระดับทีม: 16 GB RAM, 8 vCPU, 200 GB disk. รองรับสี่ session พร้อมกัน โดยแต่ละ session มี checkout และ toolchain ของตัวเอง ให้กำหนดขนาดตามช่วงเวลาที่มีการใช้งานสูงสุด เพราะ agent สี่ตัวที่ไม่ได้ทำงานแทบไม่มีค่าใช้จ่าย แต่การรัน test สี่รายการพร้อมกันจะมีค่าใช้จ่ายเป็นสี่เท่าของระดับสูงสุดในตารางด้านบน
ณ เดือนสิงหาคม 2026 ส่วนต่างราคาจากแถวแรกถึงแถวสุดท้ายอยู่ที่ประมาณสี่เท่าของราคาต่อเดือนเมื่อชำระค่า VPS แบบรายปี โดยมีราคาตั้งแต่หลักหน่วยดอลลาร์ต่อเดือนในระดับเริ่มต้น ไปจนถึงหลักสิบดอลลาร์ในระดับสูงสุด โปรดตรวจสอบรายการราคาปัจจุบันก่อนวางแผน เพราะตัวเลขเหล่านี้มีการเปลี่ยนแปลงอยู่เสมอ ค่าเซิร์ฟเวอร์มักไม่ใช่ส่วนที่มีราคาสูงที่สุด สำหรับผู้ที่ใช้งาน agent เป็นประจำทุกวัน ค่าใช้จ่าย model API จะสูงกว่าค่าเซิร์ฟเวอร์อย่างรวดเร็ว ดังนั้นควร จำกัดงบประมาณที่อนุญาตให้ agent ใช้ ก่อนที่จะลดขนาดเซิร์ฟเวอร์ลง สำหรับขั้นตอนการ build โดยเฉพาะ คู่มือการรัน coding agent บน VPS จะครอบคลุมถึงการตั้งค่าบัญชีและการรักษา session ให้คงอยู่หลังจากที่คุณตัดการเชื่อมต่อแล้ว
ทำไมพื้นที่ดิสก์ถึงเต็มก่อน RAM
ข้อมูลเบื้องหลังแผนภูมินี้
[
{
"label": "Ubuntu 24.04 base and toolchain",
"typical_gb": 6
},
{
"label": "One JS monorepo checkout",
"typical_gb": 3
},
{
"label": "node_modules across 3 branches",
"typical_gb": 4
},
{
"label": "Docker images and build cache",
"typical_gb": 20
},
{
"label": "Agent logs and journal, 90 days",
"typical_gb": 2
}
]เมื่อรวมแถวเหล่านั้นเข้าด้วยกัน ดิสก์ขนาด 50 GB ก็เกือบจะเต็มก่อนที่คุณจะได้เขียนโค้ดแม้แต่บรรทัดเดียว รายการที่ใหญ่ที่สุดคือ Docker ซึ่งมีขนาดประมาณ 20 GB เนื่องจาก BuildKit จะเก็บทุก intermediate layer ของทุกการ build ไว้จนกว่าคุณจะสั่งให้หยุด
docker system df
docker builder prune --filter until=168hdocker system df จะแสดงพื้นที่ที่สามารถกู้คืนได้แยกตามหมวดหมู่ ดังนั้นให้รันคำสั่งนี้ก่อนและหลังการจัดการ ตัวกรอง until=168h จะเก็บข้อมูล cache ที่การ build เคยใช้ในช่วงสัปดาห์ที่ผ่านมาและลบส่วนที่เหลือทิ้ง โดยอิงตามการใช้งานล่าสุดไม่ใช่ตามอายุ ดังนั้น layer ที่สร้างขึ้นเมื่อเดือนที่แล้วแต่ถูกนำมาใช้ซ้ำเมื่อวานนี้จะยังคงอยู่ ซึ่งเป็น cache ที่ช่วยประหยัดเวลาให้คุณได้ docker image prune -a จะทำงานมากขึ้นโดยลบ image ทุกตัวที่ไม่มี container ใดใช้งานอยู่ ดังนั้นคาดการณ์ได้ว่าการ build ครั้งถัดไปจะต้องดาวน์โหลดใหม่
โปรเจกต์ Node มักล้มเหลวในรูปแบบที่แปลกกว่านั้น npm install จะเขียนไฟล์ขนาดเล็กจำนวนหลายแสนไฟล์ ทำให้ระบบไฟล์อาจขาดแคลน inodes ในขณะที่ df -h ยังคงรายงานว่ามีพื้นที่ว่างเหลืออยู่หลายกิกะไบต์ การเขียนไฟล์จะล้มเหลวด้วยข้อผิดพลาด No space left on device บนดิสก์ที่ดูเหมือนยังว่างอยู่ครึ่งหนึ่ง
df -h /
df -i /หาก IUse% อ่านค่าได้ 100 ให้ลบไดเรกทอรี node_modules ของ branch ที่คุณไม่ได้ใช้งานแล้วทิ้ง หรือเปลี่ยนไปใช้ pnpm ซึ่งจะเก็บ package แต่ละเวอร์ชันไว้เพียงชุดเดียวแล้วใช้ hard-link เชื่อมโยงไปยังทุกโปรเจกต์
Log เป็นสิ่งที่มักถูกมองข้าม Agent ที่รันตลอดเวลาจะเขียนบันทึก session และ systemd journal จะขยายขนาดขึ้นจนกินพื้นที่ดิสก์โดยค่าเริ่มต้น
sudo journalctl --disk-usage
sudo journalctl --vacuum-size=200M
du -xh --max-depth=1 / 2>/dev/null | sort -h | tailตั้งค่า SystemMaxUse=200M ใน /etc/systemd/journald.conf และรัน sudo systemctl restart systemd-journald เพื่อกำหนดเพดานนี้อย่างถาวร เพราะการล้างข้อมูลเพียงครั้งเดียวจะช่วยคืนพื้นที่ได้แค่ในวันนี้เท่านั้น
Swap: สิ่งที่ได้รับและสิ่งที่ถูกบดบัง
การเพิ่ม Swap เป็นสิ่งที่คุ้มค่า เพราะช่วยเปลี่ยนสถานการณ์ที่หน่วยความจำเกินเพียงเล็กน้อยให้กลายเป็นการทำงานที่ช้าลง แทนที่จะทำให้โปรเซสหยุดทำงานไปเลย ควรตั้งขนาดไว้ที่ครึ่งหนึ่งของ RAM โดยสูงสุดไม่เกิน 4 GB สำหรับเครื่องที่ใช้คอมไพล์โปรแกรม การเพิ่มขนาดไปมากกว่านี้แทบไม่มีประโยชน์
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
swapon --showswapon --show ควรแสดงรายการ /swapfile ตามขนาดที่คุณกำหนดไว้ หากไม่มีบรรทัด /etc/fstab ค่า Swap จะหายไปหลังจากรีบูตเครื่องครั้งถัดไป และเครื่องจะกลับไปทำงานในลักษณะเดิมโดยไม่มีการแจ้งเตือน หาก fallocate ตอบกลับด้วย Operation not supported ให้สร้างไฟล์ด้วย sudo dd if=/dev/zero of=/swapfile bs=1M count=4096 แล้วดำเนินการต่อจาก chmod
echo 'vm.swappiness = 10' | sudo tee /etc/sysctl.d/99-swappiness.conf
sudo sysctl --systemการตั้งค่า swappiness ไว้ต่ำจะบอกให้ kernel คืนพื้นที่ disk cache ก่อนที่จะผลักหน่วยความจำของโปรแกรมออกไปยังดิสก์ ซึ่งช่วยให้ language server ยังคงตอบสนองได้ดี
ส่วนสิ่งที่ Swap บดบังไว้คือ เมื่อโปรเซสต้องการหน่วยความจำมากกว่าที่เครื่องมีอยู่จริง kernel จะเสียเวลาไปกับการย้ายหน้าหน่วยความจำ (pages) ระหว่าง RAM กับดิสก์ แทนที่จะประมวลผลงานของคุณ ผลคือไม่มีอะไรพัง แต่ทุกอย่างจะทำงานช้าลงอย่างมาก และค่า load average จะพุ่งสูงขึ้นในขณะที่ CPU ไม่ได้ทำงานจริง
vmstat 1 10ตัวเลขที่ไม่ใช่ศูนย์อย่างต่อเนื่องในคอลัมน์ si และ so หมายถึงมีการทำ swapping ตลอดเวลา วิธีแก้ไขคือการลด concurrency หรือเพิ่ม RAM ไม่ใช่การเพิ่ม Swap บนเครื่องขนาดเล็ก sudo apt install -y zram-tools จะให้ compressed swap ที่เก็บไว้ใน RAM ซึ่งปรับแต่งได้ใน /etc/default/zramswap วิธีนี้เร็วกว่า swap file มาก โดยเป็นการใช้ RAM เพื่อประหยัด RAM จึงช่วยได้เฉพาะกับ cold pages เท่านั้น ไม่ช่วยงานคอมไพล์ที่ต้องการ working memory จริงๆ
ทำไม Coding agent ของคุณถึงดูเหมือนค้าง
นี่คือความล้มเหลวที่วินิจฉัยผิดพลาดบ่อยที่สุดบนเครื่อง agent ขนาดเล็ก คำสั่งไม่ส่งผลลัพธ์ใดๆ, agent รอคอย, และ session ดูเหมือนค้าง กระบวนการดังกล่าวถูก kernel สั่งฆ่าด้วย OOM (Out-of-Memory) killer มันได้รับสัญญาณ SIGKILL จึงไม่สามารถพิมพ์ข้อผิดพลาด, ล้าง log, หรือแจ้งให้ agent ทราบว่าเกิดอะไรขึ้น Agent จึงเห็นเพียงผลลัพธ์ที่ว่างเปล่าและไม่มีข้อความแจ้งการจบการทำงาน
แต่ kernel ได้บันทึกเหตุการณ์นี้ไว้:
sudo dmesg -T | grep -iE "out of memory|killed process"
sudo journalctl -k -b | grep -i oomบรรทัดที่เกิดขึ้นจริงจะมีลักษณะดังนี้:
[Thu Aug 6 11:02:14 2026] Out of memory: Killed process 4711 (node) total-vm:4210880kB, anon-rss:3820104kB, file-rss:0kB, shmem-rss:0kB, UID:1000 pgtables:8236kB oom_score_adj:0anon-rss คือปริมาณหน่วยความจำที่กระบวนการนั้นถือครองอยู่ตอนที่มันตาย ให้สังเกตว่ากระบวนการใดถูกเลือก: kernel จะให้คะแนนส่วนใหญ่จากหน่วยความจำที่ใช้งานอยู่ ดังนั้นมันจึงมักฆ่า language server หรือตัว agent เอง แทนที่จะฆ่ากระบวนการ build ที่เป็นสาเหตุหลัก นี่คือเหตุผลว่าทำไมอาการที่แสดงออกมาจึงดูเหมือน "agent พัง"
ภายใน Docker เหตุการณ์เดียวกันจะทิ้งร่องรอยที่ชัดเจนกว่า Container จะจบการทำงานด้วยรหัส 137 ซึ่งมาจาก 128 บวกกับสัญญาณ 9
docker ps -a
docker inspect "$(docker ps -lq)" | grep -i oomkilled"OOMKilled": true ยืนยันว่า container ถึงขีดจำกัดหน่วยความจำของมันแล้ว แทนที่จะ crash ด้วยตัวเอง
วิธีแก้ไขคือการกำหนดเพดานให้คำสั่งที่ใช้ทรัพยากรสูง เพื่อให้การ build ตายแทนที่จะเป็นตัว agent:
systemd-run --user --scope -p MemoryMax=4G -- npm run buildตอนนี้การ build จะถูกฆ่าที่ 4 GB และ agent จะยังคงอยู่ ซึ่งเปลี่ยนอาการค้างที่หาสาเหตุไม่ได้ให้กลายเป็นคำสั่งที่ล้มเหลวตามปกติพร้อมรหัส exit code ที่อ่านเข้าใจได้ สิ่งนี้จำเป็นต้องใช้ systemd user manager ซึ่งการล็อกอินผ่าน SSH ตามปกติจะเริ่มการทำงานให้คุณอยู่แล้ว ดังนั้นคำสั่งนี้จึงทำงานผ่าน SSH ได้ทันที loginctl enable-linger $USER มีไว้สำหรับรักษา user units ให้ทำงานต่อไปหลังจากที่คุณออกจากระบบเท่านั้น MemoryHigh= จะทำการจำกัดความเร็วของกระบวนการที่จุดวิกฤตแทนการฆ่าทิ้ง ซึ่งมักเป็นการตั้งค่าที่เหมาะสมกว่าสำหรับการ build ที่คุณต้องการให้มันทำงานจนเสร็จแม้จะช้าก็ตาม
จำกัดหน่วยความจำด้วย Compose memory limits
หากเครื่องมือของ agent ทำงานในคอนเทนเนอร์ ให้กำหนดเพดานหน่วยความจำไว้ในไฟล์ Compose เพื่อให้มีผลทุกครั้งที่รัน
services:
agent:
image: node:22-bookworm
deploy:
resources:
limits:
memory: 2g
cpus: "1.5"Docker Compose v2 ใช้ deploy.resources.limits บนไฟล์ docker compose up ปกติได้เลยโดยไม่ต้องพึ่งพา swarm mode ทั้งนี้คีย์ mem_limit: 2g แบบเดิมยังคงใช้งานได้ คู่มือฉบับเต็มเกี่ยวกับ Compose memory limits จะอธิบายเรื่องการจองหน่วยความจำและสิ่งที่เกิดขึ้นเมื่อคอนเทนเนอร์ใช้งานถึงเพดานที่กำหนด หากยังไม่มี Docker บนเซิร์ฟเวอร์ ให้ ติดตั้ง Docker บน VPS ก่อน
มีกับดักหนึ่งที่ทำให้เสียเวลาไปทั้งบ่าย คอนเทนเนอร์ที่ถูกจำกัดไว้ที่ 2 GB ยังคงอ่านค่า /proc/meminfo และจำนวน CPU ของโฮสต์ได้ เนื่องจากทั้งสองค่านี้ไม่ได้ถูกทำ namespaced ตัวรันการทดสอบที่เลือกจำนวน worker ตามจำนวน CPU จะพยายามเริ่ม worker 8 ตัวภายในคอนเทนเนอร์ขนาด 2 GB บนโฮสต์ที่มี 8 vCPU แล้วจะล้มเหลวด้วย exit code 137 ให้กำหนดค่าเหล่านี้ด้วยตนเอง:
npx jest --maxWorkers=2
export NODE_OPTIONS=--max-old-space-size=1536--max-old-space-size มีหน่วยเป็น MB และใช้จำกัด V8 heap ให้ตั้งค่านี้ไว้ต่ำกว่าขีดจำกัดของคอนเทนเนอร์ เพื่อให้ Node แสดงข้อความแจ้งเตือนที่อ่านเข้าใจได้แทนที่จะหายไปเฉยๆ:
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memoryข้อความดังกล่าวมีประโยชน์มาก เพราะระบุขีดจำกัดที่ถูกใช้งานจนเต็มและระบุ process ที่เป็นต้นเหตุ ซึ่ง OOM killer ไม่เคยบอกข้อมูลเหล่านี้ให้ทราบ
การรัน agent หลายเซสชันบนเครื่องเดียว
ให้วางแผนตามจำนวนเซสชัน ไม่ใช่ตามจำนวนผู้ใช้งาน การรันสองเซสชันบน repository เดียวกันหมายถึงการมี language server สองตัว, แคชการ build สองชุดในหน่วยความจำ และการรัน test สองครั้งหาก agent ทั้งสองตัวทำงานพร้อมกัน นั่นคือเหตุผลที่แถวของทีมงานต้องเพิ่มขึ้นเป็น 16 GB
กำหนดเพดานการใช้งานสูงสุดให้กับผู้ใช้แต่ละราย เพื่อป้องกันไม่ให้เซสชันที่ทำงานผิดปกติเพียงเซสชันเดียวทำให้ทั้งเครื่องหยุดทำงาน:
id -u alice
sudo mkdir -p /etc/systemd/system/user-1001.slice.d
printf '[Slice]\nMemoryMax=6G\n' | sudo tee /etc/systemd/system/user-1001.slice.d/limit.conf
sudo systemctl daemon-reload
systemctl show user-1001.slice -p MemoryMaxแทนที่ 1001 ด้วย UID ที่ id -u แสดงผลออกมา systemctl show ควรจะแสดงค่า MemoryMax=6442450944 หลังจากที่ผู้ใช้ล็อกอินเข้าสู่ระบบแล้ว เมื่อทุกกระบวนการในเซสชันของผู้ใช้นั้นใช้หน่วยความจำเกิน 6 GB เคอร์เนลจะสั่งยุติกระบวนการภายใน slice ของผู้ใช้นั้น และเซสชันอื่น ๆ ทั้งหมดจะยังคงทำงานต่อไป สำหรับ agent ที่รันเป็น service แทนที่จะรันใน terminal ให้ใส่ MemoryMax= ลงใน unit file ของ service นั้นแทน ซึ่งเป็นรูปแบบที่ควรปฏิบัติตามเมื่อคุณ โฮสต์ agent ด้วยตนเองในรูปแบบ service ที่ทำงานตลอดเวลา
FAQ
RAM ขนาด 2 GB เพียงพอสำหรับ coding agent หรือไม่?
สำหรับตัวกระบวนการของ agent นั้นเพียงพอ แต่สำหรับงานที่ต้องประมวลผลมักจะไม่พอ ตัว agent เองใช้ RAM ประมาณ 250 MB แต่ TypeScript language server เพียงตัวเดียวอาจใช้ RAM สูงถึง 2000 MB ใน repository ขนาดกลาง ซึ่งจะทำให้เครื่องที่มี RAM 2 GB ต้องเริ่มใช้งาน swap ทันที RAM 2 GB เหมาะสำหรับการแก้ไขไฟล์ config และสคริปต์ขนาดเล็กเท่านั้น ควรใช้ RAM ขนาด 4 GB เป็นค่าเริ่มต้นสำหรับงานที่ต้องมีการคอมไพล์หรือรันชุดทดสอบ
จำเป็นต้องใช้ GPU เพื่อรัน coding agent บน VPS หรือไม่?
ไม่จำเป็นหาก agent เรียกใช้งานโมเดลผ่าน API บนคลาวด์ ภาระงานดังกล่าวขึ้นอยู่กับความเร็วเครือข่าย ดังนั้น VPS ที่ใช้ CPU ปกติจึงเป็นตัวเลือกที่เหมาะสมที่สุด ส่วน GPU จะกลายเป็นทรัพยากรที่ไม่ได้ใช้งานแต่มีราคาสูงกว่ามาก คุณจะจำเป็นต้องใช้ GPU ก็ต่อเมื่อรันโมเดลบนเครื่องเดียวกัน ซึ่งในกรณีนั้นประเด็นจะเปลี่ยนจาก RAM ไปเป็น VRAM และขนาดของโมเดลแทน
ควรเพิ่ม swap ให้กับ VPS ของ agent เท่าใด?
ควรเพิ่มประมาณครึ่งหนึ่งของ RAM โดยสูงสุดไม่เกิน 4 GB swap ช่วยป้องกันกรณีที่การใช้งานหน่วยความจำเกินขีดจำกัดชั่วคราว เพราะ kernel สามารถย้ายข้อมูลที่ไม่ได้ใช้งานไปยังดิสก์แทนการสั่ง kill กระบวนการทิ้ง แต่มันไม่ได้เป็นการเพิ่มหน่วยความจำที่ใช้งานได้จริง หาก vmstat 1 แสดงให้เห็นว่ามีการรับส่งข้อมูลอย่างต่อเนื่องในคอลัมน์ si และ so แสดงว่าเครื่องกำลังเกิดสภาวะ thrashing ซึ่งวิธีแก้ไขคือการลดจำนวน worker ที่ทำงานขนานกันหรืออัปเกรดแผนการใช้งานให้สูงขึ้น
ทำไม coding agent ของฉันถึงค้างระหว่างการ build?
การ build มักถูกสั่งยุติโดย OOM killer ของ kernel ซึ่งจะส่งสัญญาณ SIGKILL ทำให้ไม่มีข้อความแจ้งเตือนใดๆ ปรากฏขึ้น และ agent จะรอการตอบกลับจาก pipe ที่ไม่มีวันได้รับข้อมูล ให้รันคำสั่ง sudo dmesg -T | grep -i "killed process" แล้วตรวจสอบชื่อกระบวนการและค่า anon-rss ของมัน วิธีแก้ไขคือจำกัดการ build ด้วย systemd-run --user --scope -p MemoryMax=4G และลดจำนวน worker ลง หรืออัปเกรด RAM ให้สูงขึ้นหนึ่งระดับ