WebAssembly Threads พร้อมให้ลองใช้ใน Chrome 70 แล้ว

การรองรับชุดข้อความ WebAssembly พร้อมใช้งานใน Chrome 70 ภายใต้การทดลองใช้ต้นทาง

Alex Danilo

WebAssembly (Wasm) ช่วยให้คอมไพล์โค้ดที่เขียนด้วย C++ และภาษาอื่นๆ เพื่อเรียกใช้ในเว็บได้ ฟีเจอร์ที่มีประโยชน์มากอย่างหนึ่งของแอปพลิเคชันเนทีฟคือความสามารถในการใช้เธรด ซึ่งเป็นพื้นฐานสําหรับการคํานวณแบบขนาน นักพัฒนาซอฟต์แวร์ C และ C++ ส่วนใหญ่จะคุ้นเคยกับ pthreads ซึ่งเป็น API มาตรฐานสำหรับการจัดการเธรดในแอปพลิเคชัน

กลุ่มชุมชน WebAssembly พยายามนำเธรดมาใช้กับเว็บเพื่อให้แอปพลิเคชันแบบหลายเธรดใช้งานได้จริง ด้วยเหตุนี้ V8 จึงได้ใช้การรองรับที่จำเป็นสำหรับชุดข้อความในเครื่องมือ WebAssembly ซึ่งพร้อมใช้งานผ่านช่วงทดลองใช้จากต้นทาง ช่วงทดลองใช้จากต้นทางช่วยให้นักพัฒนาซอฟต์แวร์ได้ทดลองใช้ฟีเจอร์ใหม่ๆ ของเว็บก่อนที่จะมีการกำหนดมาตรฐานอย่างเต็มรูปแบบ ซึ่งช่วยให้เรารวบรวมความคิดเห็นจากนักพัฒนาแอปที่กล้าลองใช้จริง ซึ่งเป็นสิ่งที่สําคัญในการตรวจสอบและปรับปรุงฟีเจอร์ใหม่ๆ

เวอร์ชัน Chrome 70 รองรับเธรดสำหรับ WebAssembly และเราขอแนะนำให้นักพัฒนาซอฟต์แวร์เริ่มใช้งานและส่งความคิดเห็นให้เรา

ชุดข้อความ แล้วผู้ปฏิบัติงานล่ะ

เบราว์เซอร์รองรับการทำงานแบบขนานผ่าน Web Worker มาตั้งแต่ปี 2012 ใน Chrome 4 และคุณอาจได้ยินคําว่า "ในเธรดหลัก" ฯลฯ อยู่บ่อยครั้ง แต่ Web Worker ไม่ได้แชร์ข้อมูลที่เปลี่ยนแปลงได้ระหว่างกัน แต่จะอาศัยการส่งข้อความเพื่อสื่อสารแทน อันที่จริง Chrome จัดสรรเครื่องมือ V8 ใหม่ ให้กับแต่ละรุ่น (เรียกว่าการทำงานแบบแยก) แต่ละอินสแตนซ์จะไม่แชร์โค้ดที่คอมไพล์แล้วหรือออบเจ็กต์ JavaScript ดังนั้นจึงแชร์ข้อมูลที่เปลี่ยนแปลงได้ไม่ได้ เช่น pthread

ส่วนเธรด WebAssembly นั้นคือเธรดที่แชร์หน่วยความจำ Wasm เดียวกันได้ พื้นที่เก็บข้อมูลพื้นฐานของหน่วยความจําที่ใช้ร่วมกันจะทํางานได้โดยใช้ SharedArrayBuffer ซึ่งเป็นพรอมต์เนทีฟของ JavaScript ที่อนุญาตให้แชร์เนื้อหา ArrayBuffer รายการเดียวระหว่างผู้ทํางานพร้อมกัน เทรด WebAssembly แต่ละรายการจะทำงานใน Web Worker แต่หน่วยความจำ Wasm ที่ใช้ร่วมกันช่วยให้ทำงานได้เหมือนกับที่ทำบนแพลตฟอร์มดั้งเดิม ซึ่งหมายความว่าแอปพลิเคชันที่ใช้เธรด Wasm จะมีหน้าที่รับผิดชอบในการจัดการการเข้าถึงหน่วยความจำที่แชร์ เช่นเดียวกับแอปพลิเคชันเธรดแบบดั้งเดิม ไลบรารีโค้ดที่มีอยู่จำนวนมากเขียนด้วย C หรือ C++ ซึ่งใช้ pthread และสามารถคอมไพล์เป็น Wasm และทำงานในโหมดแบบเธรดจริงได้ ซึ่งช่วยให้มีแกนประมวลผลจำนวนมากขึ้นที่ทำงานกับข้อมูลเดียวกันได้พร้อมกัน

ตัวอย่างง่ายๆ

ต่อไปนี้เป็นตัวอย่างของโปรแกรม 'C' แบบง่ายที่ใช้ชุดข้อความ

#include <pthread.h>
#include <stdio.h>

// Calculate Fibonacci numbers shared function
int fibonacci(int iterations) {
    int     val = 1;
    int     last = 0;

    if (iterations == 0) {
        return 0;
    }
    for (int i = 1; i < iterations; i++) {
        int     seq;

        seq = val + last;
        last = val;
        val = seq;
    }
    return val;
}
// Start function for the background thread
void *bg_func(void *arg) {
    int     *iter = (void *)arg;

    *iter = fibonacci(*iter);
    return arg;
}
// Foreground thread and main entry point
int main(int argc, char *argv[]) {
    int         fg_val = 54;
    int         bg_val = 42;
    pthread_t   bg_thread;

    // Create the background thread
    if (pthread_create(&bg_thread, NULL, bg_func, &bg_val)) {
        perror("Thread create failed");
        return 1;
    }
    // Calculate on the foreground thread
    fg_val = fibonacci(fg_val);
    // Wait for background thread to finish
    if (pthread_join(bg_thread, NULL)) {
        perror("Thread join failed");
        return 2;
    }
    // Show the result from background and foreground threads
    printf("Fib(42) is %d, Fib(6 * 9) is %d\n", bg_val, fg_val);

    return 0;
}

โค้ดดังกล่าวขึ้นต้นด้วยฟังก์ชัน main() ซึ่งประกาศตัวแปร 2 รายการ ได้แก่ fg_val และ bg_val นอกจากนี้ ยังมีฟังก์ชันชื่อ fibonacci() ซึ่งทั้ง 2 ชุดข้อความในตัวอย่างนี้เรียกใช้ได้ ฟังก์ชัน main() จะสร้างเธรดเบื้องหลังโดยใช้ pthread_create() ซึ่งมีภารกิจในการคำนวณค่าลำดับตัวเลขฟีโบนักชีที่สอดคล้องกับค่าของตัวแปร bg_val ในระหว่างนี้ ฟังก์ชัน main() ที่ทำงานในเธรดเบื้องหน้าจะคำนวณค่าสำหรับตัวแปร fg_val เมื่อเธรดแบ็กกราวด์ทำงานเสร็จแล้ว ระบบจะพิมพ์ผลลัพธ์

คอมไพล์เพื่อรองรับเทรด

ก่อนอื่น คุณควรติดตั้ง emscripten SDK โดยควรเป็นเวอร์ชัน 1.38.11 ขึ้นไป หากต้องการสร้างโค้ดตัวอย่างโดยเปิดใช้เธรดเพื่อเรียกใช้ในเบราว์เซอร์ เราต้องส่ง Flag เพิ่มเติม 2-3 รายการไปยังคอมไพเลอร์ emcc ของ emscripten บรรทัดคำสั่งของเรามีลักษณะดังนี้

emcc -O2 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=2 -o test.js test.c

อาร์กิวเมนต์บรรทัดคำสั่ง "-s USE_PTHREADS=1" จะเปิดการรองรับการแยกชุดข้อความสำหรับโมดูล WebAssembly ที่คอมไพล์แล้ว และอาร์กิวเมนต์ "-s PTHREAD_POOL_SIZE=2" จะบอกคอมไพเลอร์ให้สร้างกลุ่มชุดข้อความสอง (2) ชุดข้อความ

เมื่อเรียกใช้โปรแกรม ระบบจะโหลดโมดูล WebAssembly, สร้าง Web Worker สําหรับแต่ละเธรดในพูลเธรด, แชร์โมดูลกับแต่ละเวิร์กเกอร์ ซึ่งในกรณีนี้จะมี 2 รายการ และระบบจะใช้เวิร์กเกอร์เหล่านั้นทุกครั้งที่มีการเรียกใช้ pthread_create() ผู้ปฏิบัติงานแต่ละคนจะสร้างอินสแตนซ์โมดูล Wasm ด้วยหน่วยความจำเดียวกัน ซึ่งช่วยให้สามารถให้ความร่วมมือได้ การเปลี่ยนแปลงล่าสุดของ V8 ในเวอร์ชัน 7.0 คือการใช้โค้ดเนทีฟที่คอมไพล์แล้วของโมดูล Wasm ที่ส่งผ่านระหว่างผู้ปฏิบัติงาน ซึ่งช่วยให้แอปพลิเคชันขนาดใหญ่มากปรับขนาดให้ทำงานกับผู้ปฏิบัติงานหลายคนได้ โปรดทราบว่าควรตรวจสอบว่าขนาด Thread Pool เท่ากับจำนวนสูงสุดของเทรดที่แอปพลิเคชันต้องการ ไม่เช่นนั้นอาจสร้างเทรดไม่สำเร็จ ในขณะเดียวกัน หากขนาดพูลเธรดใหญ่เกินไป คุณก็จะสร้าง Web Worker ที่ไม่จำเป็นซึ่งจะนั่งเฉยๆ โดยไม่ทำอะไรเลยนอกจากใช้หน่วยความจำ

วิธีทดลองใช้

วิธีที่เร็วที่สุดในการทดสอบโมดูล WebAssembly คือเปิดการรองรับเทรด WebAssembly แบบทดลองใน Chrome 70 เป็นต้นไป ไปที่ URL about://flags ในเบราว์เซอร์ดังที่แสดงด้านล่าง

หน้า Flag ของ Chrome

ถัดไป ให้ค้นหาการตั้งค่าเธรด WebAssembly เวอร์ชันทดลอง ซึ่งมีลักษณะดังนี้

การตั้งค่าชุดข้อความ WebAssembly

เปลี่ยนการตั้งค่าเป็นเปิดใช้ตามที่แสดงด้านล่าง แล้วรีสตาร์ทเบราว์เซอร์

เปิดใช้การตั้งค่าชุดข้อความ WebAssembly แล้ว

หลังจากเบราว์เซอร์รีสตาร์ทแล้ว เราจะลองโหลดโมดูล WebAssembly แบบใช้เธรดด้วยหน้า HTML แบบเรียบง่ายที่มีเพียงเนื้อหานี้

<!DOCTYPE html>
<html>
  <title>Threads test</title>
  <body>
    <script src="test.js"></script>
  </body>
</html>

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

เอาต์พุตคอนโซลจากโปรแกรมฟิโบนักชี

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

การทดสอบในพื้นที่ด้วยช่วงทดลองใช้จากต้นทาง

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

ช่วงทดลองใช้จากต้นทางให้คุณลองใช้ฟีเจอร์ทดลองกับผู้ใช้ได้โดยการรับโทเค็นการทดสอบที่ผูกกับโดเมนของคุณ จากนั้นคุณก็สามารถทําให้แอปใช้งานได้ในเบราว์เซอร์ที่รองรับฟีเจอร์ที่คุณทดสอบ (ในกรณีนี้คือ Chrome 70 ขึ้นไป) หากต้องการรับโทเค็นของคุณเองเพื่อเรียกใช้การทดลองใช้ต้นทาง ให้ใช้แบบฟอร์มการสมัครที่นี่

เราได้โฮสต์ตัวอย่างง่ายๆ ข้างต้นโดยใช้โทเค็นช่วงทดลองใช้จากต้นทาง คุณจึงสามารถลองใช้ด้วยตนเองได้โดยไม่ต้องสร้างอะไรเลย

หากต้องการดูว่า 4 เทรดที่ทำงานพร้อมกันจะสร้างภาพ ASCII ได้อย่างไร โปรดดูการสาธิตนี้ด้วย

ให้ข้อเสนอแนะกับเรา

เทรด WebAssembly เป็นพื้นฐานใหม่ที่มีประโยชน์อย่างยิ่งสำหรับการพอร์ตแอปพลิเคชันไปยังเว็บ ตอนนี้คุณสามารถเรียกใช้แอปพลิเคชันและไลบรารี C และ C++ ที่ต้องอาศัยการรองรับ pthreads ในสภาพแวดล้อม WebAssembly ได้แล้ว

เราต้องการความคิดเห็นจากนักพัฒนาแอปที่ลองใช้ฟีเจอร์นี้ เนื่องจากความคิดเห็นดังกล่าวจะช่วยเรากำหนดกระบวนการมาตรฐานและตรวจสอบความมีประโยชน์ของฟีเจอร์ วิธีที่ดีที่สุดในการส่งความคิดเห็นคือการรายงานปัญหาและ/หรือมีส่วนร่วมในกระบวนการมาตรฐานในกลุ่มชุมชน WebAssembly