1 คะแนน โดย GN⁺ 2026-03-12 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ตรรกะ การวิเคราะห์ชนิด (type resolution) ของคอมไพเลอร์ Zig ถูกออกแบบใหม่ทั้งหมด ทำให้โครงสร้างภายในเรียบง่ายขึ้นและมีการปรับปรุงที่ผู้ใช้มองเห็นได้โดยตรง
  • การออกแบบใหม่ใช้การประมวลผล การวิเคราะห์ฟิลด์ของชนิดแบบ lazy จึงไม่ตรวจสอบโครงสร้างรายละเอียดของชนิดที่ยังไม่ได้เริ่มต้นโดยไม่จำเป็น
  • ข้อความข้อผิดพลาดของ dependency loop ถูกปรับปรุงให้ชัดเจนขึ้น ทำให้สามารถระบุสาเหตุของลูปได้อย่างแม่นยำ
  • มีการแก้ปัญหาการวิเคราะห์มากเกินไปและบั๊กจำนวนมากในฟีเจอร์ incremental compilation ส่งผลให้ความเร็วในการบิลด์ดีขึ้นอย่างมาก
  • การเปลี่ยนแปลงครั้งนี้รวมถึงการแก้บั๊กหลายสิบรายการและการปรับปรุงภาษาขนาดเล็ก ช่วยเสริมทั้ง ประสิทธิภาพและประสบการณ์การพัฒนา ของคอมไพเลอร์ Zig โดยรวม

การออกแบบตรรกะการวิเคราะห์ชนิดใหม่

  • มีการรวม PR ขนาดประมาณ 30,000 บรรทัด ซึ่งเขียนตรรกะการวิเคราะห์ชนิดของคอมไพเลอร์ Zig ใหม่ให้มีโครงสร้างที่มีเหตุผลและเข้าใจง่ายขึ้น
    • ในกระบวนการนี้ โครงสร้างภายในของคอมไพเลอร์ถูกจัดระเบียบใหม่ และยังให้ผลลัพธ์การปรับปรุงที่ผู้ใช้สัมผัสได้โดยตรง
  • คอมไพเลอร์ถูกเปลี่ยนให้ ประเมินการวิเคราะห์ฟิลด์ของชนิดแบบ lazy ทำให้ไม่ต้องไล่สำรวจโครงสร้างรายละเอียดของชนิดที่ยังไม่ได้เริ่มต้นโดยไม่จำเป็น
    • ในโค้ดตัวอย่าง หากโครงสร้างที่มีฟิลด์ @compileError ถูกใช้เป็นเพียง namespace ก่อนหน้านี้จะเกิดข้อผิดพลาดระหว่างคอมไพล์ แต่ตอนนี้สามารถคอมไพล์ได้ตามปกติ
    • สิ่งนี้ช่วยป้องกันการพึ่งพาโค้ดที่ไม่จำเป็นเมื่อใช้ชนิดแบบ namespace เช่น std.Io.Writer

ปรับปรุงข้อความข้อผิดพลาดของ dependency loop

  • ก่อนหน้านี้ ข้อความข้อผิดพลาดของ dependency loop ค่อนข้างกำกวม แต่ตอนนี้จะแสดงสาเหตุและตำแหน่งของลูปอย่างชัดเจน
    • ในโค้ดตัวอย่าง เมื่อโครงสร้าง Foo และ Bar อ้างอิงถึงกัน ข้อความข้อผิดพลาดจะชี้ตำแหน่งการพึ่งพาของแต่ละชนิดอย่างเฉพาะเจาะจง
    • ข้อความยังรวมถึงความยาวของลูป ตำแหน่งการประกาศแต่ละฟิลด์ และตำแหน่งของคำสั่งสอบถามการจัดเรียง
  • แม้ในกรณีของลูปที่ซับซ้อน ก็ยังให้ข้อมูลเพียงพอเพื่อให้ระบุสาเหตุของปัญหาได้ง่าย

ปรับปรุงประสิทธิภาพ incremental compilation

  • การเปลี่ยนแปลงครั้งนี้แก้ไข บั๊กจำนวนมากของฟีเจอร์ incremental compilation
    • โดยเฉพาะได้แก้ปัญหา “over-analysis” ทำให้มีการปรับให้คอมไพล์ใหม่เฉพาะส่วนที่เปลี่ยนแปลงเท่านั้น
    • ผลลัพธ์คือในหลายกรณี ความเร็วในการคอมไพล์ดีขึ้นอย่างมาก
  • นักพัฒนาสามารถเปิดใช้ incremental compilation ใน Zig เวอร์ชัน 0.15.1 ขึ้นไป เพื่อสัมผัสประสบการณ์การพัฒนาที่ดีขึ้น

การปรับปรุงอื่น ๆ

  • PR นี้ยังรวมถึง การแก้บั๊ก หลายสิบรายการ การเปลี่ยนแปลงภาษาขนาดเล็ก และ การปรับปรุงประสิทธิภาพคอมไพเลอร์
    • ส่วนใหญ่เป็นรายละเอียดปลีกย่อยหรือกรณีเฉพาะทาง
  • ดูรายละเอียดการเปลี่ยนแปลงทั้งหมดได้ที่ Codeberg ใน PR #31403
  • หากพบบั๊กใหม่ แนะนำให้ รายงานอีเวนต์ปัญหา

ความสำคัญของการเปลี่ยนแปลง

  • การทำให้ตรรกะการวิเคราะห์ชนิดเรียบง่ายขึ้นและการเพิ่มประสิทธิภาพ incremental compilation ช่วยเสริม เสถียรภาพและประสิทธิภาพ ของคอมไพเลอร์ Zig
  • นักพัฒนาจะได้รับฟีดแบ็กที่รวดเร็วและชัดเจนขึ้น และสามารถคาดหวัง ประสิทธิภาพการทำงานที่ดีขึ้นแม้ในโค้ดเบสขนาดใหญ่

1 ความคิดเห็น

 
GN⁺ 2026-03-12
ความคิดเห็นจาก Hacker News
  • ฉันคือผู้เขียน devlog นี้เอง
    ผมเข้าใจความกังวลเรื่อง การพังของความเข้ากันได้ จากการเปลี่ยนแปลงภาษา แต่ขอชี้แจงว่าการเปลี่ยนคอมไพเลอร์ครั้งนี้ไม่ได้อยู่ในระดับที่จะสร้างผลกระทบวงกว้างมากนัก
    ตัวอย่างเช่น ตอน build ZLS บน branch ใหม่ ก็ต้องแก้แค่เปลี่ยน .{} เป็น .empty เท่านั้น ซึ่งเกิดจากการเอาค่าเริ่มต้นของ std.ArrayList ออก และมันก็อยู่ในสถานะ deprecated มาตั้งแต่ 1 ปีก่อนแล้ว
    อีกกรณีคือโปรเจ็กต์ Awebo ก็มีจุดที่ต้องแก้ในทั้ง dependency tree แค่สามจุด — เปลี่ยน .empty, เพิ่ม comptime, และเพิ่ม orelse @alignOf(T)
    การแก้แบบนี้ส่วนใหญ่เรียบง่ายถึงระดับที่นักพัฒนา Zig แทบจะ ทำได้แบบอัตโนมัติตามสัญชาตญาณ
    แกนหลักของ PR นี้ไม่ใช่เรื่องความพัง แต่เป็น การแก้บั๊กและการปรับปรุง incremental compilation

    • ฉันเป็นหนึ่งในคนที่เขียนคอมเมนต์เชิงวิจารณ์ต่อการเปลี่ยนแปลงนี้
      ผมคิดว่า คุณภาพและการวางแผน ของ PR นี้สูงมาก และไม่ได้มีเจตนาจะลดทอนความพยายามของผู้เขียนเลยแม้แต่น้อย
      เพียงแต่ได้บทเรียนว่าต่อไปควรใส่คำอธิบายประกอบให้มากขึ้นและแสดงความคิดเห็นอย่างระมัดระวังมากขึ้น
    • ผมไม่ได้เกี่ยวข้องกับ Zig โดยตรง แต่พอเห็นคอมเมนต์ที่เพิ่มใน lib/std/multi_array_list.zig แล้วก็เกิดคำถามขึ้นมา
      ผมไม่เข้าใจว่าทำไมการใช้ @alignOf(T) ในการนิยาม MultiArrayList(T) ถึงทำให้เกิด การพึ่งพากันแบบวนซ้ำ
      ถึง T จะเป็น MultiArrayList เอง มันก็ไม่ใช่ชนิด monomorphic ที่แยกขาดจากกันอย่างสมบูรณ์หรือ? เหมือนผมจะพลาดอะไรบางอย่าง
      โค้ดที่เกี่ยวข้อง: ลิงก์
  • อยากรู้ประสบการณ์ของคนที่ใช้ Zig ใน สภาพแวดล้อมโปรดักชัน
    ภาษานี้เปลี่ยนบ่อย เลยอยากรู้ว่ารอบการอัปเดตหรือรีไรต์เป็นอย่างไร และมีกรณีที่แพ็กเกจ dependency ตามเวอร์ชันภาษาไม่ทันบ้างไหม
    รู้ว่า Bun ใช้ Zig ได้ดี แต่ก็อยากฟังตัวอย่างอื่นด้วย

    • ผมดูแล codebase คอมไพเลอร์ที่เขียนด้วย Zig ขนาดประมาณ 250k LoC (roc-lang/roc)
      ตลอดช่วง 1–2 ปีที่ผ่านมา การเปลี่ยนแปลงของภาษาและ standard library ดำเนินไปโดย แทบไม่มีปัญหาใหญ่
      เมื่อก่อนการอัปเกรดค่อนข้างยุ่งยาก แต่ตอนนี้ให้ความรู้สึกแค่ประมาณ “น่ารำคาญเล็กน้อย
      ถ้าถามถึงประสบการณ์ใช้ Zig เรื่องนี้แทบไม่ใช่ประเด็นที่ผมจะหยิบมาพูดเลย เพราะมันนิ่งมาก
    • ผมเคยทำงานกับ codebase Zig ในโปรดักชันสองตัวคือ tigerbeetle และ sig
      โปรเจ็กต์ใหญ่แบบนี้จะอัปเกรดตาม tagged release และปกติก็ทำ migration เสร็จภายในไม่กี่วันถึงไม่กี่สัปดาห์
      dependency ก็แทบไม่มี เลยไม่ได้เป็นภาระหนักเวลาอัปเกรด
    • Zig 0.15 ค่อนข้างเสถียร
      แต่บางครั้งแค่พิมพ์ผิดเล็กน้อยก็ทำให้เกิด SIGBUS compiler crash จน debug ยาก
      .zig-cache โตได้ถึง 173GB เลยสร้างปัญหาบน ARM VPS ด้วย
      ตอนอัปเกรด lightpanda จาก 0.14→0.15 ก็ราบรื่นดี และคิดว่า 0.16 ก็คงไม่มีปัญหาใหญ่
      แต่ในฐานะนักพัฒนาไลบรารี กลับรู้สึกว่าตามความเร็วของการเปลี่ยนแปลงใน 0.16 ไม่ค่อยทัน
      ตอนนี้เลยรองรับแบบทดลองเฉพาะบน branch “dev” เท่านั้น
    • ผมรันโค้ด Zig 0.16 ขนาดประมาณ 20k LoC ในโปรดักชันด้วย DebugSafe mode
      ผมรีไรต์โมดูล Node.js/TypeScript เป็น Zig แล้วได้ผลคือ เร็วขึ้น 2 เท่าและใช้หน่วยความจำน้อยลง 70%
      การรองรับ sqlite/การ serialize JSON ของ Zig แข็งแกร่งมาก เลยเป็นข้อดีสำคัญ
      ข้อเสียคือการไม่มี closure หรือไวยากรณ์ vtable ทำให้แยกชั้นของโค้ดได้ยาก
      ผมใช้ Arcs กับ bump allocator เพื่อให้ได้ความปลอดภัยด้านหน่วยความจำ และตั้งใจจะรันต่อใน DebugSafe mode
      ตอนสลับไป ReleaseFast มีความเร็วเพิ่มขึ้น 25% แต่ไม่มากพอจะคุ้มกับการเสียความปลอดภัย
    • ผมคิดว่าคำมั่นเรื่อง backward compatibility ตลอดกาล ของ C++ กลับเป็นความผิดพลาดที่ขัดขวางการพัฒนาของภาษา
      ถึงจะต้องแก้โค้ดบ้าง แต่ในระยะยาวนี่คือ แนวทางที่ถูกต้อง
  • ประทับใจกับผลงานของทีม Zig มาก
    ผมใช้ เทอร์มินัล ghostty ที่เขียนด้วย Zig บ่อยมาก และมันเสถียรมาก
    แต่โดยส่วนตัวผมยังชอบ Rust มากกว่า
    Rust เลือกโมเดลแบบ “โลกปิด” ส่วน Zig เลือกโมเดลแบบ “โลกเปิด”
    ใน Rust ต้อง implement trait อย่างชัดเจน แต่ใน Zig ถ้า shape ของชนิดตรงกันก็ใช้งานได้
    สิ่งนี้ทำให้ Zig ทำ metaprogramming ได้ทรงพลัง แต่ก็มีข้อเสียคือ type inference ไม่ชัดเจน ทำให้ autocomplete, เอกสาร, และการรองรับ LSP ทำได้ยาก

    • อยากได้ตัวอย่างที่เป็นรูปธรรมกว่านี้
      ฟังดูคล้าย interface ของ Go แต่เท่าที่รู้ Zig ไม่มีแนวคิดที่ตรงกันแบบนั้น
  • การเปลี่ยนจาก kernel32 ไป Ntdll น่าสนใจมาก
    นี่เป็นแนวคิดที่เอาไปเทียบกับ API ฝั่ง user space ของ Linux ได้ด้วย
    โดยเฉพาะวิธี จัดการข้อผิดพลาดตรงขอบเขตระหว่าง kernel กับ user ที่คล้ายกัน
    แต่ใน Linux นั้น libc กับ kernel ผูกกันแน่นมากจนการใช้ errno เป็นสิ่งจำเป็น
    เลยสงสัยว่าเพราะอะไรบน Windows ถึงเกิดแพตเทิร์นแบบนี้เหมือนกัน

    • แพตเทิร์นอย่าง errno หรือ GetLastError() เป็น มรดกจากยุคก่อนเธรด
      สมัยก่อนเป็น cooperative scheduling เลยใช้ตัวแปร global ได้อย่างปลอดภัย แต่เมื่อมี multicore และเธรดก็เริ่มอันตราย
      ดังนั้น thread local จึงเกิดขึ้นมาเป็นทางออก
  • แทนที่จะใช้ชนิดเป็น namespace ผมสงสัยว่าการเพิ่ม namespace แบบ explicit เข้าไปในภาษาจะดีกว่าไหม

    • Zig มุ่งไปทาง language minimalism
      ถ้าเป็นฟีเจอร์ที่เพิ่มเข้ามาแล้วเกิดประโยชน์ต่อการ optimize ได้ในหลายจุด ค่อยเพิ่มในตอนนั้น
    • จริง ๆ แล้วนี่ไม่ใช่การอ้อม แต่คือ ความสง่างามของการออกแบบ
      ใน Zig, @import จะเปลี่ยนไฟล์ให้เป็น struct และ namespace ก็ถูกแทนด้วย struct ที่ซ้อนกัน แบบตรงไปตรงมา
      กล่าวคือ namespace ก็ไม่ได้ต่างจาก import อีกแบบหนึ่ง
      (กาแฟยังเข้าร่างไม่พอ เลยไม่กล้ารับประกันความแม่นยำ)
  • มีประเด็นหนึ่งที่มักถูกมองข้ามเวลาอภิปรายเรื่องการเปลี่ยนภาษาคือ ผลกระทบต่อ ecosystem
    ถ้าภาษาพังบ่อย ไม่ใช่แค่แอป แต่ ไลบรารี เครื่องมือ และบทสอน ก็ต้องวิ่งตามตลอด
    สุดท้าย ecosystem ก็จะเอนเอียงไปทางโปรเจ็กต์ที่ มีการดูแลรักษาอย่างต่อเนื่อง มากกว่าไลบรารีแบบ “ทำครั้งเดียวแล้วปล่อยทิ้ง”
    นี่เป็น trade-off ที่สมเหตุสมผลในช่วงออกแบบภาษาเริ่มต้น แต่ระยะยาวย่อมมีผลต่อการเติบโตของ ecosystem
    ภาษาเกิดใหม่หลายตัวทุ่มแรงมากกับการ ลดความล้าจากการเปลี่ยนแปลง แบบนี้
    การได้เห็นว่าแนวทางของ Zig จะนำไปสู่อะไรจึงน่าสนใจดี

    • ตัวอย่างหนึ่งคือ ecosystem ของ Blender addon
      Blender ทำ API พังบ่อย แต่การแก้ส่วนใหญ่ก็มักเล็กน้อย
      อย่างไรก็ดี ใครสักคนก็ต้องเป็นคนไปแก้ และถ้าไม่มีคนดูแลต่อ ผู้ใช้ก็ต้องแพตช์เอง
      addon แบบเสียเงินมีโอกาสถูกรักษาไว้มากกว่า แต่ก็ ไม่ได้รับประกัน
    • ถึงอย่างนั้นผมก็ยังคิดว่า Zig คุ้มค่า
      ไลบรารีที่ไม่มีคนดูแลก็เป็น โค้ดที่แย่ อยู่ดี
      แทนที่จะวิจารณ์ Zig ก็เลิกโปรโมตภาษาอื่นอย่าง C3 ได้แล้ว
  • ข้อความใน PR ของ Zig ที่บอกว่า “Chromium, boringssl, Firefox, Rust เรียก SystemFunction036 ของ advapi32.dll” นั้นไม่จริง
    พวกมันใช้ ProcessPrng กันอยู่แล้ว และบน Windows 10 ขึ้นไปมันไม่ล้มเหลว
    หลักฐานที่เกี่ยวข้องอยู่ใน Microsoft whitepaper
    การร้องขอ RNG ถูกออกแบบมาให้ไม่มีทางล้มเหลว และถ้าล้มเหลวจริงก็จะจบการทำงานของโปรเซสไปเลย
    กล่าวคือเพื่อรับประกันว่าได้ เลขสุ่มคุณภาพสูง จึงไม่ส่งคืน error code

    • (นี่เป็นคอมเมนต์ตอบ devlog อื่นในหน้าเดียวกัน)
  • semantic ของภาษา Zig ดูเรียบง่ายบนผิวหน้า แต่ปฏิสัมพันธ์ระหว่างองค์ประกอบค่อนข้างละเอียดอ่อน
    เรื่องแบบนี้อาจก่อให้เกิด corner case ที่ซับซ้อน ขึ้นตามกาลเวลา คล้ายกับกฎของ template ใน C++

  • PR ขนาด 30,000 บรรทัดถือเป็นความสำเร็จที่น่าทึ่ง
    แต่การเปลี่ยน semantic ของภาษา ก็เป็นเรื่องใหญ่มาก เลยรู้สึกตกใจอยู่เหมือนกัน
    เข้าใจว่า Zig ยังไม่ถึง 1.0 เลยเปลี่ยนเร็วได้ แต่การพูดแบบ สบาย ๆ ว่า “เราเปลี่ยน semantic บน branch นี้” ก็ทำให้ผมงงนิดหน่อย
    เลยสงสัยว่านี่เป็นวัฒนธรรมเฉพาะของ Zig หรือว่าผมตามยุคไม่ทันเอง
    คำว่า “modern Zig” ก็ชวนขำดี เพราะความเร็วในการเปลี่ยนแปลงของภาษานี่แหละ

    • อย่าตีความว่าสำนวนที่ดูสบาย ๆ คือ ท่าทีที่ไม่จริงจัง
      devlog ไม่ใช่บทความการตลาด แต่ใกล้เคียงกับบันทึกภายในสำหรับคนวงในมากกว่า และ Zig ก็ยังไม่ใช่ 1.0
      ใน PR มีบริบทและเหตุผลรองรับครบถ้วน
      การเลือกใช้ Zig ก็เท่ากับยอมรับ ความเสี่ยงจากการเปลี่ยนภาษา ในระดับหนึ่งตั้งแต่แรกแล้ว
      ที่จริงการเก็บงานให้สะอาดตั้งแต่ตอนนี้กลับเป็นผลดีในระยะยาว
      (นึกถึงมรดกที่แก้ไม่ได้อย่างลำดับความสำคัญของ bit operator ใน C ก็ได้)
    • mlugg เป็นผู้มีส่วนร่วมหลักของ Zig และเป็นสมาชิก Zig Foundation
      การเปลี่ยนครั้งนี้มีไว้เพื่อ คลี่คลายการพึ่งพาแบบวนซ้ำ และจัดระเบียบระบบชนิด
      ข้อเสนอที่เกี่ยวข้องเปิดสาธารณะอยู่ใน #3257 และ #15909
      การเปลี่ยนนี้ทำให้การ resolve type ของ Zig ถูกจัดระเบียบเป็นโครงสร้าง DAG (directed acyclic graph) ส่งผลให้เสถียรภาพของคอมไพเลอร์ดีขึ้นมาก
      Zig บริหารด้วยโมเดล BDFN (Benevolent Dictator For Now) และอำนาจตัดสินใจสุดท้ายอยู่ที่ Andrew Kelley
      แต่ทีมทำงานในรูปแบบองค์กรไม่แสวงกำไร และให้ความสำคัญสูงสุดกับ ความเชื่อมั่นของผู้ใช้และคุณภาพของภาษา
      สำหรับผม การได้ร่วมงานกับ Matthew เป็นเกียรติอย่างยิ่ง
    • เป็นไปได้ว่าท่าทีแบบนี้เกิดจากการใช้ ประวัติศาสตร์อันวุ่นวายของภาษา C เป็นบทเรียนตรงข้าม
      C ดูเหมือนจะเป็นระบบระเบียบในเชิงรูปแบบ แต่ในทางปฏิบัติกลับเป็น ภาษาที่โกลาหล มาก