Binaryen เป็นไลบรารีโครงสร้างพื้นฐานคอมไพเลอร์และเครื่องมือสำหรับ WebAssembly ซึ่งเขียนด้วย C++ โดยมีจุดประสงค์เพื่อทำให้คอมไพล์เป็น WebAssembly เป็นไปอย่างง่ายดาย รวดเร็ว และมีประสิทธิภาพ ในโพสต์นี้ เราจะใช้ตัวอย่างภาษาจำลองที่เรียกว่า ExampleScript เพื่อเรียนรู้วิธีเขียนโมดูล WebAssembly ใน JavaScript โดยใช้ Binaryen.js API คุณจะได้เรียนรู้พื้นฐานของการสร้างโมดูล การเพิ่มฟังก์ชันลงในโมดูล และการส่งออกฟังก์ชันจากโมดูล ซึ่งจะช่วยให้คุณมีความรู้เกี่ยวกับกลไกโดยรวมของการคอมไพล์ภาษาโปรแกรมจริงเป็น WebAssembly นอกจากนั้น คุณจะได้เรียนรู้วิธีเพิ่มประสิทธิภาพโมดูล Wasm ทั้งด้วย Branchen.js และในบรรทัดคำสั่งกับ wasm-opt
ข้อมูลเบื้องต้นเกี่ยวกับ Binaryen
Binaryen มี C API ที่ใช้งานง่ายในเฮดเดอร์เดียว และยังสามารถใช้จาก JavaScript ได้ด้วย และยอมรับอินพุตในฟอร์ม WebAssembly แต่ก็ยอมรับโฟลว์การควบคุมทั่วไปสำหรับคอมไพเลอร์ที่ต้องการ
การนําเสนอระดับกลาง (IR) คือโครงสร้างข้อมูลหรือโค้ดที่คอมไพเลอร์หรือเครื่องเสมือนใช้ภายในเพื่อแสดงซอร์สโค้ด IR ภายในของ Binaryen ใช้โครงสร้างข้อมูลที่กะทัดรัดและออกแบบมาเพื่อการสร้างและการเพิ่มประสิทธิภาพโค้ดแบบขนานทั้งหมดโดยใช้แกน CPU ทั้งหมดที่มี IR ของ Binaryen จะคอมไพล์เป็น WebAssembly เนื่องจากเป็นชุดย่อยของ WebAssembly
เครื่องมือเพิ่มประสิทธิภาพของ Binaryen มีการผ่านหลายรอบที่จะช่วยปรับปรุงขนาดและความเร็วของโค้ดได้ การเพิ่มประสิทธิภาพเหล่านี้มีเป้าหมายเพื่อทำให้ Branchen มีประสิทธิภาพมากพอที่จะใช้เป็นแบ็กเอนด์ของคอมไพเลอร์ด้วยตัวเอง ซึ่งรวมถึงการเพิ่มประสิทธิภาพสำหรับ WebAssembly โดยเฉพาะ (ซึ่งคอมไพเลอร์อเนกประสงค์อาจไม่ทำ) ซึ่งคุณอาจมองเป็นการปรับขนาด Wasm
AssemblyScript เป็นตัวอย่างผู้ใช้ Binaryen
โปรเจ็กต์หลายรายการใช้ Binaryen เช่น AssemblyScript ซึ่งใช้ Binaryen เพื่อคอมไพล์จากภาษาที่คล้ายกับ TypeScript เป็น WebAssembly โดยตรง ลองใช้ตัวอย่างในเพลย์กราวน์ AssemblyScript
อินพุต AssemblyScript
export function add(a: i32, b: i32): i32 {
return a + b;
}
โค้ด WebAssembly ที่เกี่ยวข้องในรูปแบบข้อความที่ Binaryen สร้างขึ้น
(module
(type $0 (func (param i32 i32) (result i32)))
(memory $0 0)
(export "add" (func $module/add))
(export "memory" (memory $0))
(func $module/add (param $0 i32) (param $1 i32) (result i32)
local.get $0
local.get $1
i32.add
)
)
เครื่องมือชุดค่าผสมของ Binaryen
เครื่องมือทางเทคนิคของ Binaryen มีเครื่องมือที่มีประโยชน์มากมายสำหรับทั้งนักพัฒนา JavaScript และผู้ใช้บรรทัดคำสั่ง ข้อมูลชุดย่อยของเครื่องมือเหล่านี้จะแสดงอยู่ในรายการเครื่องมือทั้งหมดที่มีอยู่ในไฟล์ README
ของโปรเจ็กต์
binaryen.js
: ไลบรารี JavaScript แบบสแตนด์อโลนที่แสดงเมธอด Binaryen สำหรับการสร้างและการเพิ่มประสิทธิภาพโมดูล Wasm สำหรับบิลด์ โปรดดู binaryen.js ใน npm (หรือดาวน์โหลดจาก GitHub หรือ unpkg โดยตรง)wasm-opt
: เครื่องมือบรรทัดคำสั่งที่โหลด WebAssembly และเรียกใช้ IR ของ Binaryen กับ WebAssemblywasm-as
และwasm-dis
: เครื่องมือบรรทัดคำสั่งที่ประกอบและถอดประกอบ WebAssemblywasm-ctor-eval
: เครื่องมือบรรทัดคำสั่งที่เรียกใช้ฟังก์ชัน (หรือส่วนต่างๆ ของฟังก์ชัน) ได้ในเวลาคอมไพล์wasm-metadce
: เครื่องมือบรรทัดคำสั่งสำหรับนำบางส่วนของไฟล์ Wasm ออกอย่างยืดหยุ่นโดยขึ้นอยู่กับวิธีใช้โมดูลwasm-merge
: เครื่องมือบรรทัดคำสั่งที่รวมไฟล์ Wasm หลายไฟล์เข้าเป็นไฟล์เดียว และเชื่อมต่อการนำเข้าที่เกี่ยวข้องไปยังการส่งออก เช่นเดียวกับ Bundler สำหรับ JavaScript แต่สำหรับ Wasm
การคอมไพล์เป็น WebAssembly
การคอมไพล์ภาษาหนึ่งเป็นภาษาอื่นมักมีหลายขั้นตอน โดยขั้นตอนที่สำคัญที่สุดมีดังนี้
- การวิเคราะห์เชิงคําศัพท์: แบ่งซอร์สโค้ดออกเป็นโทเค็น
- การวิเคราะห์ไวยากรณ์: สร้างต้นไม้ไวยากรณ์นามธรรม
- การวิเคราะห์เชิงความหมาย: ตรวจหาข้อผิดพลาดและบังคับใช้กฎทางภาษา
- การสร้างโค้ดระดับกลาง: สร้างการนําเสนอที่นามธรรมมากขึ้น
- การสร้างโค้ด: แปลเป็นภาษาเป้าหมาย
- การเพิ่มประสิทธิภาพโค้ดเฉพาะเป้าหมาย: เพิ่มประสิทธิภาพสําหรับเป้าหมาย
ในระบบ Unix เครื่องมือที่ใช้บ่อยในการคอมไพล์มีดังนี้
lex
และ
yacc
lex
(Lexical analyticser Generator):lex
คือเครื่องมือสร้างนักวิเคราะห์คลังศัพท์ หรือที่รู้จักกันในชื่อ lexers หรือเครื่องมือสแกน โดยจะใช้นิพจน์ทั่วไปชุดหนึ่งและการดำเนินการที่เกี่ยวข้องเป็นอินพุต และสร้างโค้ดสำหรับเครื่องมือวิเคราะห์เชิงคําศัพท์ที่จดจํารูปแบบในซอร์สโค้ดอินพุตyacc
(Yet Another Compiler Compiler):yacc
เป็นเครื่องมือที่สร้างโปรแกรมแยกวิเคราะห์สําหรับการวิเคราะห์ไวยากรณ์ โดยจะใช้คำอธิบายไวยากรณ์อย่างเป็นทางการของภาษาโปรแกรมเป็นอินพุตและสร้างโค้ดสำหรับโปรแกรมแยกวิเคราะห์ โดยทั่วไปโปรแกรมแยกวิเคราะห์ จะสร้าง โครงสร้างไวยากรณ์แบบนามธรรม (AST) ที่แสดงถึงโครงสร้างลำดับชั้นของซอร์สโค้ด
ตัวอย่างที่ใช้งานได้
ขอบเขตของบทความนี้ทำให้ไม่สามารถครอบคลุมภาษาโปรแกรมอย่างสมบูรณ์ได้ ดังนั้นเพื่อลดความซับซ้อน เราจึงขอแนะนำภาษาโปรแกรมสังเคราะห์ที่มีประโยชน์น้อยมากและมีข้อจำกัดมากอย่าง ExampleScript ซึ่งทำงานโดยการแสดงการดำเนินการทั่วไปผ่านตัวอย่างที่ชัดเจน
- หากต้องการเขียนฟังก์ชัน
add()
คุณต้องเขียนโค้ดตัวอย่างของการบวกใดๆ เช่น2 + 3
- หากต้องการเขียนฟังก์ชัน
multiply()
ให้เขียน6 * 12
ตามคำเตือนล่วงหน้า ข้อมูลนี้ไม่มีประโยชน์ใดๆ เลย แต่ง่ายพอที่เครื่องมือวิเคราะห์เชิงคําศัพท์จะนิพจน์ทั่วไปได้เพียงรายการเดียว: /\d+\s*[\+\-\*\/]\s*\d+\s*/
ถัดไปต้องมี parser จริงๆ แล้ว คุณสามารถสร้างต้นไม้ไวยากรณ์นามธรรมเวอร์ชันที่ง่ายมากได้โดยใช้นิพจน์ทั่วไปที่มีกลุ่มการจับคู่ที่มีชื่อ ดังนี้
/(?<first_operand>\d+)\s*(?<operator>[\+\-\*\/])\s*(?<second_operand>\d+)/
คำสั่ง ExampleScript ต้องมี 1 คำสั่งต่อบรรทัดเพื่อให้โปรแกรมแยกวิเคราะห์ประมวลผลโค้ดทีละบรรทัดโดยแบ่งตามอักขระขึ้นบรรทัดใหม่ ขั้นตอนนี้เพียงพอที่จะตรวจสอบ 3 ขั้นตอนแรกจากรายการหัวข้อก่อนหน้านี้ ได้แก่ การวิเคราะห์เชิงคําศัพท์ การวิเคราะห์ไวยากรณ์ และการวิเคราะห์ความหมาย รหัสสำหรับขั้นตอนเหล่านี้อยู่ใน รายการต่อไปนี้
export default class Parser {
parse(input) {
input = input.split(/\n/);
if (!input.every((line) => /\d+\s*[\+\-\*\/]\s*\d+\s*/gm.test(line))) {
throw new Error('Parse error');
}
return input.map((line) => {
const { groups } =
/(?<first_operand>\d+)\s*(?<operator>[\+\-\*\/])\s*(?<second_operand>\d+)/gm.exec(
line,
);
return {
firstOperand: Number(groups.first_operand),
operator: groups.operator,
secondOperand: Number(groups.second_operand),
};
});
}
}
การสร้างโค้ดระดับกลาง
ตอนนี้โปรแกรม ExampleScript สามารถแสดงเป็นแผนผังไวยากรณ์นามธรรม (แม้ว่าจะเป็นโครงสร้างที่ค่อนข้างซับซ้อน) ขั้นตอนถัดไปคือการสร้างตัวแทนขั้นกลางที่เป็นนามธรรม ขั้นตอนแรกคือการสร้างโมดูลใหม่ใน Binaryen โดยทำดังนี้
const module = new binaryen.Module();
แต่ละบรรทัดของต้นไม้ไวยากรณ์นามธรรมประกอบด้วยชุด 3 รายการที่ประกอบด้วย firstOperand
, operator
และ secondOperand
สําหรับโอเปอเรเตอร์ 4 รายการที่เป็นไปได้ใน ExampleScript ซึ่งได้แก่ +
, -
, *
, /
จะต้องเพิ่มฟังก์ชันใหม่ลงในโมดูลด้วยเมธอด Module#addFunction()
ของ Binaryen พารามิเตอร์ของวิธี
Module#addFunction()
มีดังนี้
name
:string
แสดงถึงชื่อของฟังก์ชันfunctionType
:Signature
แสดงถึงลายเซ็นของฟังก์ชันvarTypes
:Type[]
ระบุตำแหน่งเพิ่มเติมตามลำดับที่ระบุbody
:Expression
ซึ่งเป็นเนื้อหาของฟังก์ชัน
ยังมีรายละเอียดเพิ่มเติมที่ควรพิจารณาและแยกย่อย และเอกสารประกอบ Binaryen ช่วยให้คุณไปยังส่วนต่างๆ ได้ แต่สุดท้ายแล้ว คุณจะพบกับเมธอด Module#i32.add()
ซึ่งเป็นการดำเนินการกับจำนวนเต็มที่พร้อมใช้งานเพียงไม่กี่รายการสำหรับโอเปอเรเตอร์ +
ของ ExampleScript
การเพิ่มต้องใช้ตัวดำเนินการ 2 ตัว ได้แก่ ตัวบวกแรกและตัวบวกที่สอง ฟังก์ชันต้องส่งออกด้วย Module#addFunctionExport()
จึงจะเรียกใช้ได้
module.addFunction(
'add', // name: string
binaryen.createType([binaryen.i32, binaryen.i32]), // params: Type
binaryen.i32, // results: Type
[binaryen.i32], // vars: Type[]
// body: ExpressionRef
module.block(null, [
module.local.set(
2,
module.i32.add(
module.local.get(0, binaryen.i32),
module.local.get(1, binaryen.i32),
),
),
module.return(module.local.get(2, binaryen.i32)),
]),
);
module.addFunctionExport('add', 'add');
หลังจากประมวลผล Abstract Syntax Tree แล้ว โมดูลจะมีเมธอด 4 รายการ ซึ่ง 3 รายการทำงานกับตัวเลขจำนวนเต็ม ได้แก่ add()
โดยอิงตาม Module#i32.add()
, subtract()
โดยอิงตาม Module#i32.sub()
, multiply()
โดยอิงตาม Module#i32.mul()
และค่าที่ผิดปกติ divide()
โดยอิงตาม Module#f64.div()
เนื่องจาก ExampleScript ทำงานกับผลลัพธ์ที่เป็นทศนิยมด้วย
for (const line of parsed) {
const { firstOperand, operator, secondOperand } = line;
if (operator === '+') {
module.addFunction(
'add', // name: string
binaryen.createType([binaryen.i32, binaryen.i32]), // params: Type
binaryen.i32, // results: Type
[binaryen.i32], // vars: Type[]
// body: ExpressionRef
module.block(null, [
module.local.set(
2,
module.i32.add(
module.local.get(0, binaryen.i32),
module.local.get(1, binaryen.i32)
)
),
module.return(module.local.get(2, binaryen.i32)),
])
);
module.addFunctionExport('add', 'add');
} else if (operator === '-') {
module.subtractFunction(
// Skipped for brevity.
)
} else if (operator === '*') {
// Skipped for brevity.
}
// And so on for all other operators, namely `-`, `*`, and `/`.
หากต้องจัดการกับฐานโค้ดจริง บางครั้งอาจมีโค้ดที่ตายแล้วซึ่งไม่เคยเรียกใช้ หากต้องการแทรกโค้ดที่ตายแล้ว (ซึ่งจะได้รับการปรับปรุงและนําออกในขั้นตอนถัดไป) ในตัวอย่างการคอมไพล์ ExampleScript เป็น Wasm ที่ทํางานอยู่ การเพิ่มฟังก์ชันที่ไม่ได้ส่งออกจะทํางานได้
// This function is added, but not exported,
// so it's effectively dead code.
module.addFunction(
'deadcode', // name: string
binaryen.createType([binaryen.i32, binaryen.i32]), // params: Type
binaryen.i32, // results: Type
[binaryen.i32], // vars: Type[]
// body: ExpressionRef
module.block(null, [
module.local.set(
2,
module.i32.div_u(
module.local.get(0, binaryen.i32),
module.local.get(1, binaryen.i32),
),
),
module.return(module.local.get(2, binaryen.i32)),
]),
);
คอมไพเลอร์เกือบพร้อมใช้งานแล้ว แม้จะไม่จำเป็นก็ได้ แต่ถือเป็นแนวทางปฏิบัติที่ดีในการตรวจสอบโมดูลด้วยเมธอด Module#validate()
if (!module.validate()) {
throw new Error('Validation error');
}
การนําโค้ด Wasm ที่เป็นผลมา
หากต้องการรับโค้ด Wasm ที่ได้ จะมี 2 วิธีใน Binaryen สำหรับการรับการนำเสนอแบบข้อความเป็นไฟล์ .wat
ใน นิพจน์ S ในรูปแบบที่มนุษย์อ่านได้ และการนำเสนอแบบไบนารีเป็นไฟล์ .wasm
ที่ทำงานในเบราว์เซอร์ได้โดยตรง โค้ดไบนารีจะทำงานในเบราว์เซอร์ได้โดยตรง หากต้องการตรวจสอบว่าการส่งออกทำงานหรือไม่ การบันทึกการส่งออกอาจช่วยได้
const textData = module.emitText();
console.log(textData);
const wasmData = module.emitBinary();
const compiled = new WebAssembly.Module(wasmData);
const instance = new WebAssembly.Instance(compiled, {});
console.log('Wasm exports:\n', instance.exports);
การแสดงข้อความที่สมบูรณ์สำหรับโปรแกรม ExampleScript พร้อมการดำเนินการทั้ง 4 แบบมีดังนี้ โปรดทราบว่าโค้ดที่ตายแล้วยังคงอยู่ แต่ไม่ได้แสดงตามภาพหน้าจอของ WebAssembly.Module.exports()
(module
(type $0 (func (param i32 i32) (result i32)))
(type $1 (func (param f64 f64) (result f64)))
(export "add" (func $add))
(export "subtract" (func $subtract))
(export "multiply" (func $multiply))
(export "divide" (func $divide))
(func $add (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local.set $2
(i32.add
(local.get $0)
(local.get $1)
)
)
(return
(local.get $2)
)
)
(func $subtract (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local.set $2
(i32.sub
(local.get $0)
(local.get $1)
)
)
(return
(local.get $2)
)
)
(func $multiply (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local.set $2
(i32.mul
(local.get $0)
(local.get $1)
)
)
(return
(local.get $2)
)
)
(func $divide (param $0 f64) (param $1 f64) (result f64)
(local $2 f64)
(local.set $2
(f64.div
(local.get $0)
(local.get $1)
)
)
(return
(local.get $2)
)
)
(func $deadcode (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local.set $2
(i32.div_u
(local.get $0)
(local.get $1)
)
)
(return
(local.get $2)
)
)
)
การเพิ่มประสิทธิภาพ WebAssembly
ไบนารีมี 2 วิธีในการเพิ่มประสิทธิภาพโค้ด Wasm สิ่งหนึ่งใน Branchen.js เอง และอีกรายการหนึ่ง สำหรับบรรทัดคำสั่ง การตั้งค่าแบบแรกจะใช้ชุดกฎการเพิ่มประสิทธิภาพมาตรฐานโดยค่าเริ่มต้นและให้คุณตั้งค่าการเพิ่มประสิทธิภาพและระดับการบีบอัดได้ ส่วนการตั้งค่าแบบหลังจะไม่ใช้กฎใดๆ โดยค่าเริ่มต้น แต่อนุญาตให้ปรับแต่งได้อย่างเต็มที่ ซึ่งหมายความว่าเมื่อทำการทดสอบมากพอแล้ว คุณจะปรับแต่งการตั้งค่าเพื่อให้ได้ผลลัพธ์ที่ดีที่สุดตามโค้ดของคุณได้
การเพิ่มประสิทธิภาพด้วย Branchen.js
วิธีที่ตรงที่สุดในการเพิ่มประสิทธิภาพโมดูล Wasm ด้วย Binaryen คือเรียกใช้เมธอด Module#optimize()
ของ Binaryen.js โดยตรง และตั้งค่าการเพิ่มประสิทธิภาพและระดับการบีบอัด (ไม่บังคับ)
// Assume the `wast` variable contains a Wasm program.
const module = binaryen.parseText(wast);
binaryen.setOptimizeLevel(2);
binaryen.setShrinkLevel(1);
// This corresponds to the `-Os` setting.
module.optimize();
ซึ่งจะนําโค้ดที่ตายแล้วซึ่งนําเข้าก่อนหน้านี้ออก ดังนั้นการนําเสนอแบบข้อความของตัวอย่างของ ExampleScript เวอร์ชัน Wasm จะไม่มีโค้ดดังกล่าวอีกต่อไป โปรดสังเกตด้วยว่าขั้นตอนการเพิ่มประสิทธิภาพ SimplifyLocals (การเพิ่มประสิทธิภาพที่เกี่ยวข้องกับตัวแปรย่อยอื่นๆ) และ Vacuum (นำโค้ดที่ไม่จำเป็นออกอย่างเห็นได้ชัด) นำคู่ local.set/get
ออกได้อย่างไร และ RemoveUnusedBrs (นำการหยุดพักออกจากตำแหน่งที่ไม่จำเป็น) นำ return
ออกได้อย่างไร
(module
(type $0 (func (param i32 i32) (result i32)))
(type $1 (func (param f64 f64) (result f64)))
(export "add" (func $add))
(export "subtract" (func $subtract))
(export "multiply" (func $multiply))
(export "divide" (func $divide))
(func $add (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32)
(i32.add
(local.get $0)
(local.get $1)
)
)
(func $subtract (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32)
(i32.sub
(local.get $0)
(local.get $1)
)
)
(func $multiply (; has Stack IR ;) (param $0 i32) (param $1 i32) (result i32)
(i32.mul
(local.get $0)
(local.get $1)
)
)
(func $divide (; has Stack IR ;) (param $0 f64) (param $1 f64) (result f64)
(f64.div
(local.get $0)
(local.get $1)
)
)
)
การเพิ่มประสิทธิภาพมีหลายรอบ และ Module#optimize()
ใช้ชุดค่าเริ่มต้นของการเพิ่มประสิทธิภาพและระดับการลดขนาด หากต้องการปรับแต่งทั้งหมด คุณต้องใช้เครื่องมือบรรทัดคำสั่ง wasm-opt
การเพิ่มประสิทธิภาพด้วยเครื่องมือบรรทัดคำสั่ง wasm-opt
Branchen มีเครื่องมือบรรทัดคำสั่ง wasm-opt
เพื่อปรับแต่งบัตรที่จะใช้ได้อย่างเต็มที่ หากต้องการดูรายการตัวเลือกการเพิ่มประสิทธิภาพทั้งหมดที่เป็นไปได้ ให้ดูข้อความความช่วยเหลือของเครื่องมือ เครื่องมือ wasm-opt
อาจเป็นที่นิยมมากที่สุดในเครื่องมือนี้และมีชุดเครื่องมือคอมไพเลอร์หลายๆ เชนเพื่อเพิ่มประสิทธิภาพโค้ด Wasm เช่น Emscripten,
J2CL,
Kotlin/Wasm,
dart2wasm,
wasm-pack และอื่นๆ
wasm-opt --help
ต่อไปนี้เป็นตัวอย่างบางส่วนของบัตรที่เข้าใจได้โดยไม่ต้องมีความรู้เฉพาะทาง
- CodeFolding: หลีกเลี่ยงโค้ดที่ซ้ำกันโดยการผสาน (เช่น หาก
if
อาร์ม 2 รายการมีคำสั่งที่แชร์กันอยู่ท้ายๆ) - DeadArgumentElimination: การเพิ่มประสิทธิภาพเวลาลิงก์เพื่อนำอาร์กิวเมนต์ออกจากฟังก์ชัน หากมีการเรียกใช้ด้วยค่าคงที่เดียวกันเสมอ
- MinifyImportsAndExports: ลดขนาดไฟล์เป็น
"a"
,"b"
- DeadCodeElimination: นําโค้ดที่ตายแล้วออก
โดยมีตำราการเพิ่มประสิทธิภาพพร้อมเคล็ดลับมากมายในการระบุว่า Flag ใดสำคัญและคุ้มค่าที่จะลองทำก่อน ตัวอย่างเช่น บางครั้งการเรียกใช้ wasm-opt
ซ้ำแล้วซ้ำอีกจะทำให้อินพุตเล็กลง ในกรณีเช่นนี้ การทํางานด้วยFlag --converge
จะทําซ้ำไปเรื่อยๆ จนกว่าจะไม่มีการเพิ่มประสิทธิภาพอีกและถึงจุดคงที่
สาธิต
หากต้องการดูแนวคิดที่นำเสนอในโพสต์นี้ในการใช้งานจริง ให้ลองใช้ตัวอย่างที่ฝังอยู่โดยป้อนอินพุต ExampleScript ที่คุณนึกออก นอกจากนี้ อย่าลืมดูซอร์สโค้ดของการสาธิต
สรุป
Binaryen มีชุดเครื่องมือที่มีประสิทธิภาพสำหรับการคอมไพล์ภาษาเป็น WebAssembly และเพิ่มประสิทธิภาพโค้ดที่ได้ ไลบรารี JavaScript และเครื่องมือบรรทัดคำสั่งมีความยืดหยุ่นและใช้งานง่าย โพสต์นี้แสดงหลักการหลักของการคอมไพล์ Wasm โดยเน้นประสิทธิภาพและศักยภาพของ Binaryen ในการเพิ่มประสิทธิภาพสูงสุด แม้ว่าตัวเลือกการปรับแต่งการเพิ่มประสิทธิภาพของ Binaryen จำนวนมากจะต้องใช้ความรู้เชิงลึกเกี่ยวกับข้อมูลภายในของ Wasm แต่โดยปกติแล้วการตั้งค่าเริ่มต้นก็มีประสิทธิภาพดีอยู่แล้ว ขอให้สนุกกับการรวบรวมและ เพิ่มประสิทธิภาพด้วย Binalen!
ขอขอบคุณ
โพสต์นี้ผ่านการตรวจสอบโดย Alon Zakai, Thomas Lively และ Rachel Andrew