Binaryen เป็นไลบรารีโครงสร้างพื้นฐานคอมไพเลอร์และเครื่องมือสำหรับ WebAssembly ซึ่งเขียนด้วย C++ โดยมีจุดประสงค์เพื่อทำให้คอมไพล์เป็น WebAssembly เป็นไปอย่างง่ายดาย รวดเร็ว และมีประสิทธิภาพ ในโพสต์นี้ เราจะใช้ตัวอย่างภาษาจำลองที่เรียกว่า ExampleScript เพื่อเรียนรู้วิธีเขียนโมดูล WebAssembly ใน JavaScript โดยใช้ Binaryen.js API คุณจะได้เรียนรู้พื้นฐานของการสร้างโมดูล การเพิ่มฟังก์ชันลงในโมดูล และการส่งออกฟังก์ชันจากโมดูล ซึ่งจะช่วยให้คุณมีความรู้เกี่ยวกับกลไกโดยรวมของการคอมไพล์ภาษาโปรแกรมจริงเป็น WebAssembly นอกจากนี้ คุณจะได้เรียนรู้วิธีเพิ่มประสิทธิภาพโมดูล Wasm ทั้งกับ Binaryen.js และในบรรทัดคำสั่งด้วย wasm-opt
ข้อมูลเบื้องต้นเกี่ยวกับ Binaryen
Binaryen มี C API ที่ใช้งานง่ายในเฮดเดอร์เดียว และใช้จาก JavaScript ได้ด้วย โดยยอมรับอินพุตในรูปแบบ WebAssembly และยังยอมรับกราฟการไหลของการควบคุมทั่วไปสําหรับคอมไพเลอร์ที่ต้องการรูปแบบดังกล่าวด้วย
การนําเสนอระดับกลาง (IR) คือโครงสร้างข้อมูลหรือโค้ดที่คอมไพเลอร์หรือเครื่องเสมือนใช้ภายในเพื่อแสดงซอร์สโค้ด IR ภายในของ Binaryen ใช้โครงสร้างข้อมูลที่กะทัดรัดและออกแบบมาเพื่อการสร้างและการเพิ่มประสิทธิภาพโค้ดแบบขนานทั้งหมดโดยใช้แกน CPU ทั้งหมดที่มี IR ของ Binaryen จะคอมไพล์เป็น WebAssembly เนื่องจากเป็นชุดย่อยของ WebAssembly
เครื่องมือเพิ่มประสิทธิภาพของ Binaryen มีการผ่านหลายรอบที่จะช่วยปรับปรุงขนาดและความเร็วของโค้ดได้ การเพิ่มประสิทธิภาพเหล่านี้มีจุดประสงค์เพื่อทำให้ Binaryen มีประสิทธิภาพเพียงพอที่จะใช้เป็นแบ็กเอนด์คอมไพเลอร์ได้ ซึ่งรวมถึงการเพิ่มประสิทธิภาพสำหรับ 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 หลายไฟล์เข้าเป็นไฟล์เดียว โดยเชื่อมต่อการนําเข้าที่เกี่ยวข้องเข้ากับการส่งออกขณะดำเนินการ คล้ายกับเครื่องมือรวมไฟล์สำหรับ JavaScript แต่สำหรับ Wasm
การคอมไพล์เป็น WebAssembly
การคอมไพล์ภาษาหนึ่งเป็นภาษาอื่นมักมีหลายขั้นตอน โดยขั้นตอนที่สำคัญที่สุดมีดังนี้
- การวิเคราะห์เชิงคําศัพท์: แบ่งซอร์สโค้ดออกเป็นโทเค็น
- การวิเคราะห์ไวยากรณ์: สร้างต้นไม้ไวยากรณ์นามธรรม
- การวิเคราะห์เชิงความหมาย: ตรวจหาข้อผิดพลาดและบังคับใช้กฎทางภาษา
- การสร้างโค้ดระดับกลาง: สร้างการนําเสนอที่นามธรรมมากขึ้น
- การสร้างโค้ด: แปลเป็นภาษาเป้าหมาย
- การเพิ่มประสิทธิภาพโค้ดเฉพาะเป้าหมาย: เพิ่มประสิทธิภาพสําหรับเป้าหมาย
ในระบบ Unix เครื่องมือที่ใช้บ่อยในการคอมไพล์ ได้แก่ lex
และ yacc
lex
(Lexical Analyzer Generator):lex
เป็นเครื่องมือที่สร้างโปรแกรมวิเคราะห์เชิงคำศัพท์ หรือที่เรียกว่า Lexer หรือ Scanner โดยจะใช้นิพจน์ทั่วไปชุดหนึ่งและการดำเนินการที่เกี่ยวข้องเป็นอินพุต และสร้างโค้ดสำหรับเครื่องมือวิเคราะห์เชิงคําศัพท์ที่จดจํารูปแบบในซอร์สโค้ดอินพุต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 รายการ ได้แก่ ผลบวกรายการแรกและรายการที่ 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');
หลังจากประมวลผลต้นไม้ไวยากรณ์นามธรรมแล้ว โมดูลจะมีเมธอด 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
Binaryen มี 2 วิธีในการเพิ่มประสิทธิภาพโค้ด Wasm 1 รายการใน Binaryen.js เอง และอีก 1 รายการสำหรับบรรทัดคำสั่ง การตั้งค่าแบบแรกจะใช้ชุดกฎการเพิ่มประสิทธิภาพมาตรฐานโดยค่าเริ่มต้นและให้คุณตั้งค่าการเพิ่มประสิทธิภาพและระดับการบีบอัดได้ ส่วนการตั้งค่าแบบหลังจะไม่ใช้กฎใดๆ โดยค่าเริ่มต้น แต่อนุญาตให้ปรับแต่งได้อย่างเต็มที่ ซึ่งหมายความว่าเมื่อทำการทดสอบมากพอแล้ว คุณจะปรับแต่งการตั้งค่าเพื่อให้ได้ผลลัพธ์ที่ดีที่สุดตามโค้ดของคุณได้
การเพิ่มประสิทธิภาพด้วย Binaryen.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
Binaryen มี
wasm-opt
เครื่องมือบรรทัดคำสั่งสำหรับการปรับแต่งบัตรที่จะใช้อย่างเต็มรูปแบบ หากต้องการดูรายการตัวเลือกการเพิ่มประสิทธิภาพทั้งหมดที่เป็นไปได้ ให้ดูข้อความความช่วยเหลือของเครื่องมือ เครื่องมือ wasm-opt
น่าจะเป็นเครื่องมือที่ได้รับความนิยมมากที่สุด และเครื่องมือนี้ถูกใช้โดยเครื่องมือคอมไพเลอร์หลายชุดเพื่อเพิ่มประสิทธิภาพโค้ด Wasm ซึ่งรวมถึง Emscripten,
J2CL,
Kotlin/Wasm,
dart2wasm,
wasm-pack และอื่นๆ
wasm-opt --help
ต่อไปนี้เป็นตัวอย่างของบัตรบางส่วนที่เข้าใจได้โดยไม่ต้องมีความรู้เฉพาะทาง
- CodeFolding: หลีกเลี่ยงโค้ดที่ซ้ำกันโดยการผสาน (เช่น หาก
if
อาร์ม 2 รายการมีคำสั่งที่แชร์กันอยู่) - DeadArgumentElimination: การเพิ่มประสิทธิภาพเวลาลิงก์เพื่อนำอาร์กิวเมนต์ออกจากฟังก์ชันหากมีการเรียกใช้ด้วยค่าคงที่เดียวกันเสมอ
- MinifyImportsAndExports: ย่อขนาดเป็น
"a"
,"b"
- DeadCodeElimination: นำโค้ดที่ตายแล้วออก
มีตำราการเพิ่มประสิทธิภาพพร้อมเคล็ดลับหลายประการในการระบุว่าการตั้งค่าใดสำคัญกว่าและควรลองใช้ก่อน ตัวอย่างเช่น บางครั้งการเรียกใช้ wasm-opt
ซ้ำๆ จะทำให้อินพุตเล็กลงอีก ในกรณีเช่นนี้ การทํางานด้วยFlag --converge
จะทําซ้ำไปเรื่อยๆ จนกว่าจะไม่มีการเพิ่มประสิทธิภาพอีกและถึงจุดคงที่
สาธิต
หากต้องการดูแนวคิดที่นำเสนอในโพสต์นี้ในการใช้งานจริง ให้ลองใช้ตัวอย่างที่ฝังอยู่โดยป้อนอินพุต ExampleScript ที่คุณนึกออก นอกจากนี้อย่าลืมดูซอร์สโค้ดของเดโมด้วย
สรุป
Binaryen มีชุดเครื่องมือที่มีประสิทธิภาพสำหรับการคอมไพล์ภาษาเป็น WebAssembly และเพิ่มประสิทธิภาพโค้ดที่ได้ ไลบรารี JavaScript และเครื่องมือบรรทัดคำสั่งมีความยืดหยุ่นและใช้งานง่าย โพสต์นี้แสดงหลักการหลักของการคอมไพล์ Wasm โดยเน้นประสิทธิภาพและศักยภาพของ Binaryen ในการเพิ่มประสิทธิภาพสูงสุด แม้ว่าตัวเลือกการปรับแต่งการเพิ่มประสิทธิภาพของ Binaryen จำนวนมากจะต้องใช้ความรู้เชิงลึกเกี่ยวกับข้อมูลภายในของ Wasm แต่โดยปกติแล้วการตั้งค่าเริ่มต้นก็มีประสิทธิภาพดีอยู่แล้ว เรายินดีที่ได้ช่วยให้คุณคอมไพล์และเพิ่มประสิทธิภาพด้วย Binaryen
ขอขอบคุณ
โพสต์นี้ผ่านการตรวจสอบโดย Alon Zakai, Thomas Lively และ Rachel Andrew