ตอนนี้การเพิ่มประสิทธิภาพ WasmGC และ Wasm Tail Call พร้อมใช้งานใน Baseline แล้ว

เผยแพร่: 29 มกราคม 2025

บริการเก็บขยะ WebAssembly (WasmGC)

ภาษาโปรแกรมมี 2 ประเภท ได้แก่ ภาษาโปรแกรมที่มีการรวบรวมขยะและภาษาโปรแกรมที่ต้องจัดการหน่วยความจำด้วยตนเอง ตัวอย่างภาษาแบบแรก ได้แก่ Kotlin, PHP หรือ Java ตัวอย่างภาษาหลัง ได้แก่ C, C++, หรือ Rust โดยทั่วไปแล้ว ภาษาโปรแกรมระดับสูงมีแนวโน้มที่จะใช้การเก็บขยะเป็นฟีเจอร์มาตรฐานมากกว่า

กล่าวอย่างง่ายคือ การรวบรวมขยะคือการพยายามเรียกคืนหน่วยความจำที่โปรแกรมจัดสรรไว้ แต่ไม่มีการอ้างอิงอีกต่อไป หน่วยความจำดังกล่าวเรียกว่า "ขยะ" การใช้การเก็บขยะมีกลยุทธ์มากมาย วิธีที่เข้าใจง่ายที่สุดอย่างหนึ่งคือการนับการอ้างอิง ซึ่งมีวัตถุประสงค์เพื่อนับจํานวนการอ้างอิงถึงออบเจ็กต์ในหน่วยความจํา

ฟังดูอาจเหมือนเป็นการเริ่มต้น แต่ภาษาโปรแกรมก็ใช้กับภาษาโปรแกรมอื่นๆ ได้ เช่น รันไทม์ PHP ส่วนใหญ่จะเขียนด้วย C หากนักพัฒนาแอปต้องการคอมไพล์ภาษาอย่าง PHP เป็น Wasm โดยทั่วไปแล้วจะต้องคอมไพล์ทุกส่วน เช่น โปรแกรมแยกวิเคราะห์ของภาษา การสนับสนุนไลบรารี การเก็บขยะ และคอมโพเนนต์สำคัญอื่นๆ

Wasm จะทํางานในเบราว์เซอร์ในบริบทของภาษาโฮสต์ JavaScript ใน Chrome นั้น JavaScript และ Wasm จะทำงานใน V8 ซึ่งเป็นเครื่องมือ JavaScript แบบโอเพนซอร์สของ Google และ V8 มีโปรแกรมเก็บขยะอยู่แล้ว ซึ่งหมายความว่านักพัฒนาซอฟต์แวร์ที่ใช้ PHP ที่คอมไพล์เป็น Wasm จะต้องนำโปรแกรมเก็บขยะที่ใช้กับภาษาที่พอร์ต (PHP) ไปไว้ในเบราว์เซอร์ที่มีโปรแกรมเก็บขยะอยู่แล้ว ซึ่งเป็นเรื่องที่สิ้นเปลือง ด้วยเหตุนี้ WasmGC จึงเข้ามามีบทบาท

หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับ WasmGC โปรดอ่านตอนนี้เปิดใช้การเก็บขยะ WebAssembly (WasmGC) โดยค่าเริ่มต้นใน Chrome แล้ว และหากต้องการเจาะลึกจริงๆ โปรดอ่านบล็อกโพสต์ V8 วิธีใหม่ในการนําภาษาโปรแกรมที่มีการเก็บขยะมาใช้กับ WebAssembly อย่างมีประสิทธิภาพ

การเพิ่มประสิทธิภาพการเรียกใช้โค้ดท้ายของ Wasm

การเรียกจะอยู่ในตำแหน่งท้ายหากเป็นคำสั่งสุดท้ายที่ดำเนินการก่อนที่จะออกจากฟังก์ชันปัจจุบัน คอมไพเลอร์สามารถเพิ่มประสิทธิภาพการเรียกดังกล่าวได้โดยทิ้งเฟรมของผู้เรียกและแทนที่การเรียกด้วย Jump ซึ่งจะเป็นประโยชน์อย่างยิ่งสำหรับฟังก์ชันที่เรียกซ้ำ ตัวอย่างเช่น ฟังก์ชัน C นี้ซึ่งรวมองค์ประกอบของลิงค์ลิสต์

int sum(List* list, int acc) {
  if (list == nullptr) return acc;
  return sum(list->next, acc + list->val);
}

เมื่อใช้การเรียกแบบปกติ การดำเนินการนี้จะกินพื้นที่สแต็ก O(n) โดยแต่ละองค์ประกอบของลิสต์จะเพิ่มเฟรมใหม่ในสแต็กการเรียก รายการที่ยาวมากอาจทำให้สแต็กล้นอย่างรวดเร็ว การเปลี่ยนการเรียกด้วยคำสั่ง Jump จะทำให้การเพิ่มประสิทธิภาพการเรียกซ้ำเปลี่ยนฟังก์ชันที่เรียกซ้ำนี้ให้เป็นลูปที่ใช้พื้นที่สแต็ก O(1) อย่างมีประสิทธิภาพ

int sum(List* list, int acc) {
  while (list != nullptr) {
    acc = acc + list->val;
    list = list->next;
  }
  return acc;
}

การเพิ่มประสิทธิภาพนี้สำคัญอย่างยิ่งสำหรับภาษาเชิงฟังก์ชัน โดยภาษาเหล่านี้ใช้ฟังก์ชันแบบซ้ำซ้อนอย่างมาก และภาษาแบบบริสุทธิ์อย่าง Haskell ก็ไม่ได้มีโครงสร้างการควบคุมลูปด้วย โดยทั่วไปแล้ว การทำซ้ำที่กำหนดเองทุกประเภทจะใช้การเรียกซ้ำไม่ทางใดก็ทางหนึ่ง หากไม่มีการเพิ่มประสิทธิภาพการเรียกใช้โค้ดส่วนท้าย โปรแกรมที่ซับซ้อนจะพบปัญหาสแต็กล้นอย่างรวดเร็ว ซึ่งจะทำให้พื้นที่สแต็กหมดลงอย่างรวดเร็ว

ในตอนแรก WebAssembly ไม่อนุญาตให้ใช้การเพิ่มประสิทธิภาพการเรียกใช้โค้ดย่อยแบบเทลเทิร์ค แต่สิ่งนี้ได้เปลี่ยนแปลงไปพร้อมกับข้อเสนอการขยายการเรียกใช้โค้ดย่อยแบบเทลเทิร์ค หากต้องการดูรายละเอียดเพิ่มเติม โปรดอ่านบทความการเรียกใช้ส่วนท้ายของ WebAssembly ในบล็อก V8

สรุป

ตอนนี้เมื่อ WasmGC และการเพิ่มประสิทธิภาพการเรียกใช้โค้ดท้ายพร้อมใช้งานใน Baseline ใหม่แล้ว แอปจำนวนมากขึ้นจึงสามารถใช้ฟีเจอร์เหล่านี้เพื่อประสิทธิภาพที่ดียิ่งขึ้นได้ เช่น Google ชีตที่พอร์ตเวิร์กเกอร์การคํานวณของ Google ชีตไปยัง WasmGC