ดูวิธีใช้ฟีเจอร์ WebAssembly ใหม่ล่าสุดไปพร้อมกับสนับสนุนผู้ใช้ในทุกเบราว์เซอร์
WebAssembly 1.0 เปิดตัวเมื่อ 4 ปีก่อน แต่การพัฒนาไม่ได้หยุดอยู่แค่นั้น เราเพิ่มฟีเจอร์ใหม่ๆ เข้ามาผ่านทางกระบวนการกำหนดมาตรฐานข้อเสนอ เช่นเดียวกับในกรณีของฟีเจอร์ใหม่บนเว็บ ลำดับการใช้งานและลำดับเวลาของเครื่องมือทั้งสองอาจแตกต่างกันอย่างมาก หากต้องการใช้ฟีเจอร์ใหม่เหล่านั้น คุณต้องตรวจสอบว่าไม่มีผู้ใช้รายใดถูกทิ้ง ในบทความนี้ คุณจะได้ทราบแนวทางในการบรรลุเป้าหมายนี้
ฟีเจอร์ใหม่ๆ บางอย่างช่วยปรับปรุงขนาดของโค้ดได้ด้วยการเพิ่มคำสั่งใหม่สำหรับการดำเนินการทั่วไป บางฟีเจอร์เพิ่มข้อมูลพื้นฐานด้านประสิทธิภาพที่ทรงประสิทธิภาพ และอื่นๆ เพื่อปรับปรุงประสบการณ์ของนักพัฒนาซอฟต์แวร์และการผสานรวมกับเวอร์ชันอื่นๆ บนเว็บ
ดูรายการข้อเสนอทั้งหมดและขั้นตอนที่เกี่ยวข้องได้ในที่เก็บอย่างเป็นทางการ หรือติดตามสถานะการติดตั้งใช้งานในเครื่องมือได้ในหน้าแผนกลยุทธ์ของฟีเจอร์อย่างเป็นทางการ
คุณต้องพิจารณาก่อนว่าคุณต้องการใช้ฟีเจอร์ใด เพื่อให้แน่ใจว่าผู้ใช้ทุกเบราว์เซอร์จะสามารถใช้แอปพลิเคชันของคุณได้ จากนั้นจึงแยกผลิตภัณฑ์ออกเป็นกลุ่มตามการรองรับของเบราว์เซอร์ จากนั้นคอมไพล์ฐานของโค้ดสำหรับแต่ละกลุ่มแยกกัน สุดท้าย คุณต้องตรวจหาฟีเจอร์ที่รองรับและโหลดแพ็กเกจ JavaScript และ Wasm ที่เกี่ยวข้องทางเบราว์เซอร์
การเลือกและจัดกลุ่มฟีเจอร์
ลองมาดูขั้นตอนเหล่านี้โดยเลือกชุดฟีเจอร์ที่กำหนดเองเป็นตัวอย่าง สมมติว่าฉันต้องการใช้การจัดการ SIMD, ชุดข้อความ และข้อยกเว้นในคลังเพื่อเหตุผลด้านขนาดและประสิทธิภาพ โดยมีการรองรับเบราว์เซอร์ดังต่อไปนี้
คุณสามารถแบ่งเบราว์เซอร์ออกเป็นกลุ่มประชากรตามรุ่นต่อไปนี้เพื่อให้ผู้ใช้แต่ละรายได้รับประสบการณ์การเพิ่มประสิทธิภาพสูงสุด
- เบราว์เซอร์แบบ Chrome: ระบบรองรับการจัดการชุดข้อความ, SIMD และข้อยกเว้นทั้งหมด
- Firefox: ระบบรองรับเทรดและ SIMD แต่ไม่สามารถจัดการข้อยกเว้น
- Safari: รองรับชุดข้อความ แต่ไม่รองรับการใช้งาน SIMD และข้อยกเว้น
- เบราว์เซอร์อื่น: สมมติเฉพาะการรองรับ WebAssembly พื้นฐานเท่านั้น
รายละเอียดนี้แยกตามการรองรับฟีเจอร์ในแต่ละเบราว์เซอร์เวอร์ชันล่าสุด เบราว์เซอร์สมัยใหม่เป็นเบราว์เซอร์ที่ใช้ได้ตลอดและอัปเดตอัตโนมัติ ดังนั้นในกรณีส่วนใหญ่ คุณแค่ต้องกังวลเกี่ยวกับรุ่นล่าสุดเท่านั้น อย่างไรก็ตาม ตราบใดที่คุณรวม WebAssembly พื้นฐานเป็นกลุ่มประชากรตามรุ่นสำรอง คุณยังคงสามารถให้บริการแอปพลิเคชันที่ใช้งานได้แม้สำหรับผู้ใช้ที่มีเบราว์เซอร์ที่ล้าสมัย
การคอมไพล์สำหรับชุดฟีเจอร์ที่แตกต่างกัน
WebAssembly ไม่มีวิธีในตัวสำหรับตรวจหาฟีเจอร์ที่รองรับในรันไทม์ จึงต้องรองรับวิธีการทั้งหมดในโมดูลในเป้าหมาย ด้วยเหตุนี้ คุณจึงต้องคอมไพล์ซอร์สโค้ดลงใน Wasm แยกกันสำหรับชุดฟีเจอร์แต่ละชุดเหล่านั้น
ระบบเครื่องมือและบิลด์แต่ละรายการมีความแตกต่างกัน และคุณจะต้องอ่านเอกสารของคอมไพเลอร์ของคุณเองเพื่อดูวิธีปรับแต่งฟีเจอร์เหล่านั้น เพื่อให้เข้าใจง่าย ต่อไปเราจะใช้ไลบรารี C++ แบบไฟล์เดียวในตัวอย่างต่อไปนี้ และแสดงวิธีคอมไพล์ด้วย Emscripten
ฉันจะใช้ SIMD ผ่านการจำลอง SSE2, เทรดผ่านการรองรับไลบรารี Pthreads และเลือกระหว่างการจัดการข้อยกเว้น Wasm และการใช้งาน JavaScript สำรอง
# First bundle: threads + SIMD + Wasm exceptions
$ emcc main.cpp -o main.threads-simd-exceptions.mjs -pthread -msimd128 -msse2 -fwasm-exceptions
# Second bundle: threads + SIMD + JS exceptions fallback
$ emcc main.cpp -o main.threads-simd.mjs -pthread -msimd128 -msse2 -fexceptions
# Third bundle: threads + JS exception fallback
$ emcc main.cpp -o main.threads.mjs -pthread -fexceptions
# Fourth bundle: basic Wasm with JS exceptions fallback
$ emcc main.cpp -o main.basic.mjs -fexceptions
โค้ด C++ เองจะใช้ #ifdef __EMSCRIPTEN_PTHREADS__
และ #ifdef __SSE2__
เพื่อกำหนดเงื่อนไขในการเลือกระหว่างการใช้งานคู่ขนาน (เทรดและ SIMD) ของฟังก์ชันเดียวกันและการติดตั้งใช้งานแบบซีเรียลในเวลาคอมไพล์ได้ ซึ่งจะมีลักษณะดังนี้
void process_data(std::vector<int>& some_input) {
#ifdef __EMSCRIPTEN_PTHREADS__
#ifdef __SSE2__
// …implementation using threads and SIMD for max speed
#else
// …implementation using threads but not SIMD
#endif
#else
// …fallback implementation for browsers without those features
#endif
}
การจัดการข้อยกเว้นไม่จำเป็นต้องใช้คำสั่ง #ifdef
เนื่องจากสามารถใช้ในลักษณะเดียวกันจาก C++ ได้โดยไม่คำนึงถึงการติดตั้งใช้งานเบื้องหลังที่เลือกผ่านแฟล็กการคอมไพล์
กำลังโหลดชุดข้อมูลที่ถูกต้อง
เมื่อสร้าง Bundle สำหรับกลุ่มประชากรตามรุ่นฟีเจอร์ทั้งหมดแล้ว คุณต้องโหลดกลุ่มที่ถูกต้องจากแอปพลิเคชัน JavaScript หลัก ก่อนอื่น ให้ตรวจหาฟีเจอร์ที่รองรับในเบราว์เซอร์ปัจจุบัน ซึ่งทำได้โดยใช้ไลบรารี wasm-feature-detect เมื่อรวมเข้ากับการนำเข้าแบบไดนามิก คุณจะโหลดชุดข้อมูลที่เพิ่มประสิทธิภาพมากที่สุดได้ในเบราว์เซอร์ใดก็ได้ ดังนี้
import { simd, threads, exceptions } from 'https://unpkg.com/wasm-feature-detect?module';
let initModule;
if (await threads()) {
if (await simd()) {
if (await exceptions()) {
initModule = import('./main.threads-simd-exceptions.mjs');
} else {
initModule = import('./main.threads-simd.mjs');
}
} else {
initModule = import('./main.threads.mjs');
}
} else {
initModule = import('./main.basic.mjs');
}
const Module = await initModule();
// now you can use `Module` Emscripten object like you normally would
คำสุดท้าย
ในโพสต์นี้ เราได้แสดงวิธีเลือก สร้าง และสลับระหว่างแพ็กเกจสำหรับชุดฟีเจอร์ที่แตกต่างกัน
เมื่อฟีเจอร์มีจำนวนเพิ่มขึ้น จำนวนกลุ่มประชากรตามรุ่นฟีเจอร์ก็อาจไม่สามารถรักษาไว้ได้ เพื่อลดปัญหานี้ คุณสามารถเลือกกลุ่มประชากรตามรุ่นฟีเจอร์โดยอิงตามข้อมูลผู้ใช้จริงของคุณ ข้ามเบราว์เซอร์ที่ได้รับความนิยมน้อยกว่าและปล่อยให้เบราว์เซอร์เหล่านี้กลับไปใช้กลุ่มประชากรตามรุ่นที่เหมาะสมน้อยลงเล็กน้อย ตราบใดที่แอปพลิเคชันยังคงเหมาะสำหรับผู้ใช้ทุกคน แนวทางนี้ก็สามารถสร้างความสมดุลระหว่างการปรับปรุงแบบต่อเนื่องและประสิทธิภาพรันไทม์
ในอนาคต WebAssembly อาจมีวิธีตรวจหาฟีเจอร์ที่รองรับในตัวและสลับการใช้งานฟังก์ชันเดียวกันแบบต่างๆ ภายในโมดูล อย่างไรก็ตาม กลไกดังกล่าวจะเป็นฟีเจอร์หลัง MVP ที่คุณจำเป็นต้องตรวจสอบและโหลดแบบมีเงื่อนไขโดยใช้วิธีการข้างต้น ในระหว่างนี้ วิธีการนี้ยังคงเป็นวิธีเดียวในการสร้างและโหลดโค้ดโดยใช้ฟีเจอร์ใหม่ของ WebAssembly ในเบราว์เซอร์ทั้งหมด