• ทีม Ghostty ได้เขียน แอปพลิเคชัน GTK ขึ้นใหม่ทั้งหมด พร้อมใช้งาน ระบบชนิดข้อมูล GObject อย่างจริงจัง
  • ในกระบวนการนี้ การผสานรวมกับ ภาษา Zig และการตรวจสอบปัญหาหน่วยความจำด้วย Valgrind มีบทบาทสำคัญ
  • การนำระบบ GObject มาใช้ช่วยให้ การจัดการหน่วยความจำ และ การพัฒนาวิดเจ็ตแบบกำหนดเอง ง่ายขึ้นกว่าที่ผ่านมา
  • จากการใช้ Valgrind ทีมงานพบว่า ความปลอดภัยด้านหน่วยความจำ ของ Ghostty ดีขึ้นอย่างมาก
  • Ghostty GTK เวอร์ชันใหม่ได้กลายเป็นค่าเริ่มต้นสำหรับการบิลด์จากซอร์ส และมีกำหนดรวมอยู่ใน รีลีส 1.2

บทนำ

  • Ghostty เป็นเทอร์มินัลอีมูเลเตอร์ข้ามแพลตฟอร์มที่รองรับ macOS, Linux, FreeBSD
  • แต่ละแพลตฟอร์มมีจุดเด่นจากการใช้เนทีฟ GUI framework ของตนเอง
    • macOS: แอปขนาดใหญ่ที่พัฒนาด้วย Swift และ Xcode
    • Linux และ BSD: แอปพลิเคชันบน GTK ที่เชื่อมรวมกับ X11/Wayland โดยตรง
    • แกนกลางร่วมเขียนด้วย Zig และมี API ที่เข้ากันได้กับ C ABI
  • เหตุผลที่เขียนแอป GTK ขึ้นใหม่จากโครงสร้างเดิมสามารถดูได้จาก PR ต้นฉบับ
  • บทความนี้เน้นที่ การทำงานร่วมกับระบบชนิดข้อมูล GObject และ ประเด็นด้านหน่วยความจำที่ตรวจสอบด้วย Valgrind

ระบบชนิดข้อมูล GObject และ Zig

  • หากใช้ GTK โครงสร้างโดยพื้นฐานจำเป็นต้องทำงานร่วมกับ ระบบชนิดข้อมูล GObject
  • ในอดีตทีมพยายามหลีกเลี่ยงระบบ GObject และจัดการ วงจรชีวิตของอ็อบเจ็กต์ Zig ที่ไม่มีการนับอ้างอิงกับอ็อบเจ็กต์ GObject ด้วยตนเอง แต่พบปัญหาซ้ำ ๆ ว่าการคืนหน่วยความจำไม่สมบูรณ์
    • ตัวอย่าง: หน่วยความจำฝั่ง Zig ถูกคืนแล้ว แต่หน่วยความจำฝั่ง GTK ยังอยู่ หรือเกิดสถานการณ์ตรงกันข้ามซ้ำ ๆ
  • แนวทางนี้ไม่เพียงมีปัญหาเรื่องความถูกต้อง แต่ยังทำให้ใช้งาน ความสามารถเฉพาะของ GTK (event signal, property binding, action) ได้ยาก
  • ตัวอย่างที่ชัดเจนคือ เมื่อต้องรีโหลดโครงสร้างการตั้งค่า (config) องค์ประกอบ GUI ทั้งหมดที่เชื่อมอยู่ต้องอัปเดตอย่างสอดคล้องกัน ซึ่งกระบวนการนี้ซับซ้อนและเกิดข้อผิดพลาดบ่อย
    • ตอนนี้จัดการผ่าน GhosttyConfig GObject แบบนับอ้างอิงที่ห่อ Config struct ของ Zig และใช้การแจ้งเตือนการเปลี่ยนแปลงของ property เพื่อกระจายการเปลี่ยนแปลงไปทั่วทั้งแอปอย่างเป็นธรรมชาติ
  • การสร้างวิดเจ็ต GObject แบบกำหนดเองก็ง่ายขึ้น ทำให้สามารถใช้เทคโนโลยี UI สมัยใหม่ของ GTK เช่น Blueprint ได้
    • เมื่อไม่นานมานี้ การนำ Blueprint มาใช้ช่วยให้เพิ่มฟีเจอร์ใหม่อย่าง แท็บบน title bar ของ GTK และ ขอบกระดิ่งแบบเคลื่อนไหว ได้ง่ายขึ้น

Valgrind กับ GTK และ Zig

  • ตลอดกระบวนการพัฒนา มีการใช้ Valgrind เพื่อตรวจสอบปัญหาอย่างเป็นระบบ ทั้ง memory leak และการเข้าถึงหน่วยความจำที่ยังไม่ถูกกำหนด
  • การตรวจ Valgrind กับแอป GTK ทำได้ยาก และต้องใช้ ไฟล์ suppression จำนวนมาก (80% เป็นของ GTK เอง ที่เหลือเป็นไลบรารีภายนอกและไดรเวอร์ GPU)
  • การตรวจซ้ำอย่างต่อเนื่องทำให้สามารถค้นพบบั๊กหน่วยความจำซับซ้อนที่เกิดเฉพาะในบางกรณีได้ล่วงหน้า
    • ตัวอย่าง: หากไม่กำหนดค่าเริ่มต้นให้ GObject WeakRef อย่างถูกต้อง เมื่ออ็อบเจ็กต์เป้าหมายถูกคืนหน่วยความจำภายหลังจะเกิดการเข้าถึงหน่วยความจำที่ยังไม่ถูกกำหนด ซึ่ง Valgrind ตรวจพบได้ก่อน
  • จากประสบการณ์จริง ปัญหาภายใน โค้ดเบส Zig มีเพียง 2 กรณีเท่านั้น (leak 1 ครั้ง, การเข้าถึงที่ยังไม่ถูกกำหนด 1 ครั้ง) และทั้งสองก็เกิดขึ้นระหว่างการเชื่อมกับ 3rd party C API
    • ตัวจัดสรรหน่วยความจำสำหรับดีบักของ Zig และความสามารถในการผสานรวมกับ Valgrind ก็พิสูจน์แล้วว่าได้ผลจริง
  • ปัญหาหน่วยความจำอื่น ๆ ที่พบส่วนใหญ่เกิดจากขอบเขตของ C API และการจัดการวงจรชีวิตอันซับซ้อนของระบบ GObject
    • สรุปคือ หากต้องการใช้ C API ของไลบรารีที่ซับซ้อนอย่างปลอดภัย จำเป็นต้องมีเครื่องมืออย่าง Valgrind
  • ฟีเจอร์ช่วยด้านความปลอดภัยหน่วยความจำของ Zig ไม่ได้พิสูจน์ได้แค่ในเชิงทฤษฎี แต่ยังยืนยันได้จาก ประสบการณ์จริงในโครงการ

บทสรุป

  • นี่เป็นครั้งที่ ห้า ที่ผู้เขียนสร้างส่วน GUI ของ Ghostty ขึ้นใหม่ตั้งแต่ต้น
    • ตามลำดับคือ GLFW, macOS SwiftUI, macOS AppKit+SwiftUI, Linux GTK (เชิงกระบวนวิธี), Linux GTK+ระบบชนิดข้อมูล GObject
  • ในแต่ละรอบของการเขียนใหม่ ได้บทเรียนและการเติบโตทางเทคนิคใหม่ ๆ ทุกครั้ง
    • มีแผนจะนำบางส่วนของประสบการณ์ครั้งนี้ไปใช้กับโปรเจกต์ macOS ด้วย
  • ยังเน้นย้ำถึงความร่วมมืออย่างแข็งขันของทีมดูแลระบบ Ghostty GTK
  • แอปพลิเคชัน Ghostty GTK ที่เขียนขึ้นใหม่ได้กลายเป็นค่าเริ่มต้นสำหรับการบิลด์จากซอร์สแล้ว และจะถูกนำไปใช้ใน รีลีสทางการ 1.2

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น