WebAssembly

WebAssembly概述

WebAssembly(简称wasm)是一种新的二进制指令格式,可以在现代Web浏览器中运行,提供接近原生的性能。

东巴文(db-w.cn) 认为:WebAssembly是Web技术的重大突破,它允许使用C/C++、Rust等语言编写高性能Web应用,为计算密集型任务提供了新的解决方案,是Web平台的重要补充。

WebAssembly特性

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebAssembly概述 - 东巴文</title>
    
    <style>
        body {
            font-family: 'Segoe UI', sans-serif;
            padding: 20px;
            background: #f5f5f5;
        }
        
        .container {
            max-width: 800px;
            margin: 0 auto;
            background: white;
            padding: 30px;
            border-radius: 10px;
        }
        
        h1 {
            color: #667eea;
            margin-bottom: 20px;
        }
        
        h2 {
            color: #764ba2;
            margin: 30px 0 15px;
            border-left: 4px solid #764ba2;
            padding-left: 15px;
        }
        
        .wasm-demo {
            background: #f8f9fa;
            padding: 20px;
            border: 2px solid #ddd;
            margin: 15px 0;
            border-radius: 10px;
        }
        
        .wasm-demo h3 {
            color: #667eea;
            margin-bottom: 10px;
        }
        
        .feature-list {
            list-style: none;
            padding: 0;
        }
        
        .feature-list li {
            padding: 8px 0;
            border-bottom: 1px solid #eee;
        }
        
        .feature-list li:before {
            content: "✓ ";
            color: #667eea;
            font-weight: bold;
        }
        
        .comparison-table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
        }
        
        .comparison-table th,
        .comparison-table td {
            padding: 12px;
            text-align: left;
            border: 1px solid #ddd;
        }
        
        .comparison-table th {
            background: #667eea;
            color: white;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>WebAssembly概述</h1>
        
        <h2>什么是WebAssembly</h2>
        
        <div class="wasm-demo">
            <h3>核心概念</h3>
            <p>WebAssembly是一种新的二进制指令格式,可以在现代Web浏览器中运行。它设计为一种可移植、高效的Web编译目标,使各种编程语言能够在Web上运行。</p>
            
            <ul class="feature-list">
                <li><strong>高性能:</strong> 接近原生的执行速度</li>
                <li><strong>可移植:</strong> 在所有现代浏览器中运行</li>
                <li><strong>安全:</strong> 在沙箱环境中执行</li>
                <li><strong>紧凑:</strong> 二进制格式,文件体积小</li>
                <li><strong>兼容:</strong> 与JavaScript共存</li>
                <li><strong>开放:</strong> W3C标准,开放Web平台的一部分</li>
            </ul>
        </div>
        
        <h2>WebAssembly vs JavaScript</h2>
        
        <table class="comparison-table">
            <thead>
                <tr>
                    <th>特性</th>
                    <th>WebAssembly</th>
                    <th>JavaScript</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td><strong>格式</strong></td>
                    <td>二进制</td>
                    <td>文本</td>
                </tr>
                <tr>
                    <td><strong>性能</strong></td>
                    <td>接近原生</td>
                    <td>JIT编译优化</td>
                </tr>
                <tr>
                    <td><strong>语言支持</strong></td>
                    <td>C/C++, Rust, Go等</td>
                    <td>JavaScript, TypeScript</td>
                </tr>
                <tr>
                    <td><strong>加载速度</strong></td>
                    <td>快(二进制解析)</td>
                    <td>慢(文本解析)</td>
                </tr>
                <tr>
                    <td><strong>内存管理</strong></td>
                    <td>手动管理</td>
                    <td>垃圾回收</td>
                </tr>
                <tr>
                    <td><strong>适用场景</strong></td>
                    <td>计算密集型任务</td>
                    <td>UI交互,DOM操作</td>
                </tr>
            </tbody>
        </table>
        
        <h2>WebAssembly应用场景</h2>
        
        <div class="wasm-demo">
            <h3>典型应用</h3>
            <div style="background: #2d2d2d; color: #f8f8f2; padding: 15px; border-radius: 5px; margin: 10px 0;">
                <pre>
1. 图像/视频处理
   - 图像编辑器(Photopea)
   - 视频编解码
   - 图像压缩

2. 游戏
   - 3D游戏引擎(Unity, Unreal)
   - 游戏模拟器
   - Web游戏

3. 科学计算
   - 数值计算
   - 数据可视化
   - 模拟仿真

4. 加密
   - 加密算法
   - 区块链应用
   - 安全计算

5. 音频处理
   - 音频编解码
   - 音频效果器
   - 音乐合成

6. CAD/建模
   - 3D建模工具
   - CAD应用
   - 建筑设计

7. AI/机器学习
   - 模型推理
   - 图像识别
   - 自然语言处理
                </pre>
            </div>
        </div>
        
        <h2>WebAssembly示例</h2>
        
        <div class="wasm-demo">
            <h3>基本使用</h3>
            <div style="background: #2d2d2d; color: #f8f8f2; padding: 15px; border-radius: 5px; margin: 10px 0;">
                <pre>
// 加载WebAssembly模块
WebAssembly.instantiateStreaming(fetch('simple.wasm'))
    .then(results =&gt; {
        // 调用导出的函数
        const add = results.instance.exports.add;
        const result = add(10, 20);
        console.log('10 + 20 =', result); // 30
    });

// 或使用更通用的方式
fetch('simple.wasm')
    .then(response =&gt; response.arrayBuffer())
    .then(bytes =&gt; WebAssembly.instantiate(bytes))
    .then(results =&gt; {
        const instance = results.instance;
        const add = instance.exports.add;
        console.log(add(5, 3)); // 8
    });
                </pre>
            </div>
        </div>
        
        <div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
            <strong>东巴文提示:</strong>WebAssembly是Web平台的重要补充,它为计算密集型任务提供了高性能解决方案。掌握WebAssembly,能将C/C++、Rust等语言的优势带到Web平台,扩展Web应用的能力边界。
        </div>
    </div>
</body>
</html>

Emscripten

Emscripten是将C/C++代码编译为WebAssembly的工具链,是最成熟的WebAssembly编译器。

Emscripten使用

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Emscripten - 东巴文</title>
    
    <style>
        body {
            font-family: 'Segoe UI', sans-serif;
            padding: 20px;
            background: #f5f5f5;
        }
        
        .container {
            max-width: 800px;
            margin: 0 auto;
            background: white;
            padding: 30px;
            border-radius: 10px;
        }
        
        h1 {
            color: #667eea;
            margin-bottom: 20px;
        }
        
        h2 {
            color: #764ba2;
            margin: 30px 0 15px;
            border-left: 4px solid #764ba2;
            padding-left: 15px;
        }
        
        .emscripten-demo {
            background: #f8f9fa;
            padding: 20px;
            border: 2px solid #ddd;
            margin: 15px 0;
            border-radius: 10px;
        }
        
        .emscripten-demo h3 {
            color: #667eea;
            margin-bottom: 10px;
        }
        
        .code-block {
            background: #2d2d2d;
            color: #f8f8f2;
            padding: 15px;
            border-radius: 5px;
            overflow-x: auto;
            margin: 10px 0;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>Emscripten</h1>
        
        <h2>安装Emscripten</h2>
        
        <div class="emscripten-demo">
            <h3>安装步骤</h3>
            <div class="code-block">
                <pre>
# 使用emsdk安装
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk

# 安装最新版本
./emsdk install latest

# 激活最新版本
./emsdk activate latest

# 配置环境变量
source ./emsdk_env.sh

# 验证安装
emcc --version
                </pre>
            </div>
        </div>
        
        <h2>编译C代码</h2>
        
        <div class="emscripten-demo">
            <h3>简单示例</h3>
            <div class="code-block">
                <pre>
// hello.c
#include &lt;stdio.h&gt;
#include &lt;emscripten.h&gt;

int main() {
    printf("Hello, WebAssembly!\n");
    return 0;
}

// 导出函数供JavaScript调用
EMSCRIPTEN_KEEPALIVE
int add(int a, int b) {
    return a + b;
}

EMSCRIPTEN_KEEPALIVE
int factorial(int n) {
    if (n &lt;= 1) return 1;
    return n * factorial(n - 1);
}
                </pre>
            </div>
            
            <div class="code-block">
                <pre>
# 编译为WebAssembly
emcc hello.c -o hello.html

# 或编译为wasm和js文件
emcc hello.c -o hello.js

# 常用编译选项
emcc hello.c \
    -o hello.html \
    -s WASM=1 \              # 生成WebAssembly
    -s EXPORTED_FUNCTIONS="['_add', '_factorial']" \  # 导出函数
    -s EXPORTED_RUNTIME_METHODS="['ccall', 'cwrap']" \  # 导出运行时方法
    -s MODULARIZE=1 \        # 模块化输出
    -s EXPORT_NAME="createModule" \  # 模块名称
    -O3                      # 优化级别
                </pre>
            </div>
        </div>
        
        <h2>在JavaScript中调用</h2>
        
        <div class="emscripten-demo">
            <h3>调用导出函数</h3>
            <div class="code-block">
                <pre>
// 加载模块
Module.onRuntimeInitialized = () =&gt; {
    // 使用ccall调用
    const result = Module.ccall(
        'add',        // 函数名
        'number',     // 返回类型
        ['number', 'number'],  // 参数类型
        [10, 20]      // 参数值
    );
    console.log('10 + 20 =', result); // 30
    
    // 使用cwrap包装函数
    const add = Module.cwrap('add', 'number', ['number', 'number']);
    console.log('5 + 3 =', add(5, 3)); // 8
    
    const factorial = Module.cwrap('factorial', 'number', ['number']);
    console.log('5! =', factorial(5)); // 120
    
    // 直接调用(需要下划线前缀)
    console.log('7 + 8 =', Module._add(7, 8)); // 15
};
                </pre>
            </div>
        </div>
        
        <h2>处理字符串</h2>
        
        <div class="emscripten-demo">
            <h3>字符串传递</h3>
            <div class="code-block">
                <pre>
// string.c
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;emscripten.h&gt;

EMSCRIPTEN_KEEPALIVE
const char* greet(const char* name) {
    static char buffer[256];
    sprintf(buffer, "Hello, %s!", name);
    return buffer;
}

EMSCRIPTEN_KEEPALIVE
int stringLength(const char* str) {
    return strlen(str);
}
                </pre>
            </div>
            
            <div class="code-block">
                <pre>
// JavaScript调用
const greet = Module.cwrap('greet', 'string', ['string']);
const message = greet('WebAssembly');
console.log(message); // "Hello, WebAssembly!"

const stringLength = Module.cwrap('stringLength', 'number', ['string']);
console.log(stringLength('Hello')); // 5

// 手动处理字符串
function passString(str) {
    // 分配内存
    const ptr = Module.allocate(
        Module.intArrayFromString(str),
        Module.ALLOC_NORMAL
    );
    
    // 调用函数
    const resultPtr = Module._greet(ptr);
    
    // 读取返回的字符串
    const result = Module.UTF8ToString(resultPtr);
    
    // 释放内存
    Module._free(ptr);
    
    return result;
}
                </pre>
            </div>
        </div>
        
        <h2>处理数组</h2>
        
        <div class="emscripten-demo">
            <h3>数组传递</h3>
            <div class="code-block">
                <pre>
// array.c
#include &lt;emscripten.h&gt;

EMSCRIPTEN_KEEPALIVE
int sumArray(int* arr, int size) {
    int sum = 0;
    for (int i = 0; i &lt; size; i++) {
        sum += arr[i];
    }
    return sum;
}

EMSCRIPTEN_KEEPALIVE
void doubleArray(int* arr, int size) {
    for (int i = 0; i &lt; size; i++) {
        arr[i] *= 2;
    }
}
                </pre>
            </div>
            
            <div class="code-block">
                <pre>
// JavaScript调用
const sumArray = Module.cwrap('sumArray', 'number', ['number', 'number']);
const doubleArray = Module.cwrap('doubleArray', null, ['number', 'number']);

// 传递数组
const arr = [1, 2, 3, 4, 5];
const size = arr.length;

// 分配内存
const ptr = Module._malloc(size * 4); // int = 4 bytes

// 写入数组到内存
Module.HEAP32.set(arr, ptr / 4);

// 调用函数
const sum = sumArray(ptr, size);
console.log('Sum:', sum); // 15

// 修改数组
doubleArray(ptr, size);

// 读取修改后的数组
const doubled = Module.HEAP32.subarray(ptr / 4, ptr / 4 + size);
console.log('Doubled:', Array.from(doubled)); // [2, 4, 6, 8, 10]

// 释放内存
Module._free(ptr);
                </pre>
            </div>
        </div>
        
        <div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
            <strong>东巴文提示:</strong>Emscripten是将C/C++代码移植到Web的最成熟工具。掌握Emscripten的编译选项、函数导出、数据传递,能将现有的C/C++库高效地移植到Web平台。
        </div>
    </div>
</body>
</html>

wasm模块加载

WebAssembly模块可以通过多种方式加载和实例化。

加载方式

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>wasm模块加载 - 东巴文</title>
    
    <style>
        body {
            font-family: 'Segoe UI', sans-serif;
            padding: 20px;
            background: #f5f5f5;
        }
        
        .container {
            max-width: 800px;
            margin: 0 auto;
            background: white;
            padding: 30px;
            border-radius: 10px;
        }
        
        h1 {
            color: #667eea;
            margin-bottom: 20px;
        }
        
        h2 {
            color: #764ba2;
            margin: 30px 0 15px;
            border-left: 4px solid #764ba2;
            padding-left: 15px;
        }
        
        .loading-demo {
            background: #f8f9fa;
            padding: 20px;
            border: 2px solid #ddd;
            margin: 15px 0;
            border-radius: 10px;
        }
        
        .loading-demo h3 {
            color: #667eea;
            margin-bottom: 10px;
        }
        
        .code-block {
            background: #2d2d2d;
            color: #f8f8f2;
            padding: 15px;
            border-radius: 5px;
            overflow-x: auto;
            margin: 10px 0;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>wasm模块加载</h1>
        
        <h2>加载方式</h2>
        
        <div class="loading-demo">
            <h3>1. instantiateStreaming</h3>
            <div class="code-block">
                <pre>
// 最推荐的加载方式
WebAssembly.instantiateStreaming(fetch('module.wasm'))
    .then(results =&gt; {
        const instance = results.instance;
        const exports = instance.exports;
        
        // 调用导出的函数
        console.log(exports.add(10, 20));
    })
    .catch(error =&gt; {
        console.error('加载失败:', error);
    });

// 带导入对象的加载
const importObject = {
    env: {
        memory: new WebAssembly.Memory({ initial: 256 }),
        table: new WebAssembly.Table({ initial: 0, element: 'anyfunc' })
    },
    imports: {
        imported_func: arg =&gt; console.log('Imported:', arg)
    }
};

WebAssembly.instantiateStreaming(fetch('module.wasm'), importObject)
    .then(results =&gt; {
        const instance = results.instance;
        // 使用实例
    });
                </pre>
            </div>
        </div>
        
        <div class="loading-demo">
            <h3>2. 使用ArrayBuffer</h3>
            <div class="code-block">
                <pre>
// 兼容性更好的方式
fetch('module.wasm')
    .then(response =&gt; response.arrayBuffer())
    .then(bytes =&gt; WebAssembly.instantiate(bytes, importObject))
    .then(results =&gt; {
        const instance = results.instance;
        const module = results.module;
        
        // 使用实例
        console.log(instance.exports.add(5, 3));
    });

// 分步加载
fetch('module.wasm')
    .then(response =&gt; response.arrayBuffer())
    .then(bytes =&gt; WebAssembly.compile(bytes))
    .then(module =&gt; {
        // 可以多次实例化
        const instance1 = new WebAssembly.Instance(module, importObject);
        const instance2 = new WebAssembly.Instance(module, importObject);
        
        return { module, instance: instance1 };
    });
                </pre>
            </div>
        </div>
        
        <div class="loading-demo">
            <h3>3. 动态导入</h3>
            <div class="code-block">
                <pre>
// ES模块方式(实验性)
const module = await import('./module.wasm');
console.log(module.add(10, 20));

// 或使用script标签
&lt;script type="module"&gt;
    import init, { add, subtract } from './pkg/my_module.js';
    
    async function run() {
        // 初始化模块
        const module = await init();
        
        // 调用函数
        console.log(add(10, 5));      // 15
        console.log(subtract(10, 5)); // 5
    }
    
    run();
&lt;/script&gt;
                </pre>
            </div>
        </div>
        
        <h2>WebAssembly JavaScript API</h2>
        
        <div class="loading-demo">
            <h3>核心对象</h3>
            <div class="code-block">
                <pre>
// 1. WebAssembly.Module
// 编译后的WebAssembly模块
const module = await WebAssembly.compile(bytes);

// 检查模块
console.log(WebAssembly.Module.customSections(module, 'name'));
console.log(WebAssembly.Module.exports(module));
console.log(WebAssembly.Module.imports(module));

// 2. WebAssembly.Instance
// 模块的实例
const instance = new WebAssembly.Instance(module, importObject);

// 访问导出
const exports = instance.exports;
console.log(exports.add);      // 函数
console.log(exports.memory);   // 内存
console.log(exports.table);    // 表

// 3. WebAssembly.Memory
// 线性内存
const memory = new WebAssembly.Memory({ 
    initial: 256,  // 初始页数(每页64KB)
    maximum: 1024  // 最大页数
});

// 访问内存
const buffer = memory.buffer;
const view = new Int32Array(buffer);

// 4. WebAssembly.Table
// 函数表
const table = new WebAssembly.Table({ 
    initial: 2, 
    element: 'anyfunc' 
});

// 设置函数
table.set(0, exports.func1);
table.set(1, exports.func2);

// 调用
table.get(0)();

// 5. WebAssembly.Global
// 全局变量
const global = new WebAssembly.Global({ value: 'i32', mutable: true }, 0);

console.log(global.value); // 0
global.value = 10;
console.log(global.value); // 10
                </pre>
            </div>
        </div>
        
        <h2>错误处理</h2>
        
        <div class="loading-demo">
            <h3>捕获错误</h3>
            <div class="code-block">
                <pre>
// WebAssembly错误类型
try {
    const result = WebAssembly.compile(invalidBytes);
} catch (e) {
    if (e instanceof WebAssembly.CompileError) {
        console.error('编译错误:', e.message);
    } else if (e instanceof WebAssembly.LinkError) {
        console.error('链接错误:', e.message);
    } else if (e instanceof WebAssembly.RuntimeError) {
        console.error('运行时错误:', e.message);
    }
}

// 完整的错误处理
async function loadWasm(url, importObject) {
    try {
        const response = await fetch(url);
        
        if (!response.ok) {
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        
        const instance = await WebAssembly.instantiateStreaming(
            response, 
            importObject
        );
        
        return instance.instance.exports;
    } catch (error) {
        console.error('加载WebAssembly失败:', error);
        
        // 降级处理
        return fallbackImplementation();
    }
}

function fallbackImplementation() {
    // JavaScript降级实现
    return {
        add: (a, b) =&gt; a + b,
        subtract: (a, b) =&gt; a - b
    };
}
                </pre>
            </div>
        </div>
        
        <div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
            <strong>东巴文提示:</strong>掌握WebAssembly的加载方式和JavaScript API,能灵活地在Web应用中集成WebAssembly模块。注意错误处理和降级方案,确保应用的健壮性。
        </div>
    </div>
</body>
</html>

JavaScript与wasm交互

JavaScript和WebAssembly可以相互调用,共享内存。

交互方式

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript与wasm交互 - 东巴文</title>
    
    <style>
        body {
            font-family: 'Segoe UI', sans-serif;
            padding: 20px;
            background: #f5f5f5;
        }
        
        .container {
            max-width: 800px;
            margin: 0 auto;
            background: white;
            padding: 30px;
            border-radius: 10px;
        }
        
        h1 {
            color: #667eea;
            margin-bottom: 20px;
        }
        
        h2 {
            color: #764ba2;
            margin: 30px 0 15px;
            border-left: 4px solid #764ba2;
            padding-left: 15px;
        }
        
        .interaction-demo {
            background: #f8f9fa;
            padding: 20px;
            border: 2px solid #ddd;
            margin: 15px 0;
            border-radius: 10px;
        }
        
        .interaction-demo h3 {
            color: #667eea;
            margin-bottom: 10px;
        }
        
        .code-block {
            background: #2d2d2d;
            color: #f8f8f2;
            padding: 15px;
            border-radius: 5px;
            overflow-x: auto;
            margin: 10px 0;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>JavaScript与wasm交互</h1>
        
        <h2>JavaScript调用wasm</h2>
        
        <div class="interaction-demo">
            <h3>基本调用</h3>
            <div class="code-block">
                <pre>
// C代码
int add(int a, int b) {
    return a + b;
}

// JavaScript调用
const result = instance.exports.add(10, 20);
console.log(result); // 30

// 复杂类型
// C代码
void processArray(int* data, int length) {
    for (int i = 0; i &lt; length; i++) {
        data[i] *= 2;
    }
}

// JavaScript调用
const memory = instance.exports.memory;
const processArray = instance.exports.processArray;

// 创建数组
const data = new Int32Array([1, 2, 3, 4, 5]);
const length = data.length;

// 在wasm内存中分配空间
const ptr = instance.exports.alloc(length * 4);

// 复制数据到wasm内存
const wasmArray = new Int32Array(memory.buffer, ptr, length);
wasmArray.set(data);

// 调用wasm函数
processArray(ptr, length);

// 读取结果
console.log(Array.from(wasmArray)); // [2, 4, 6, 8, 10]

// 释放内存
instance.exports.dealloc(ptr, length * 4);
                </pre>
            </div>
        </div>
        
        <h2>wasm调用JavaScript</h2>
        
        <div class="interaction-demo">
            <h3>导入JavaScript函数</h3>
            <div class="code-block">
                <pre>
// 导入对象
const importObject = {
    env: {
        // 导入console.log
        js_console_log: (ptr, length) =&gt; {
            const memory = instance.exports.memory;
            const buffer = new Uint8Array(memory.buffer, ptr, length);
            const str = new TextDecoder().decode(buffer);
            console.log(str);
        },
        
        // 导入数学函数
        js_random: () =&gt; Math.random(),
        
        // 导入DOM操作
        js_set_title: (ptr, length) =&gt; {
            const memory = instance.exports.memory;
            const buffer = new Uint8Array(memory.buffer, ptr, length);
            const title = new TextDecoder().decode(buffer);
            document.title = title;
        },
        
        // 导入回调
        js_callback: (data) =&gt; {
            console.log('Callback from wasm:', data);
        }
    }
};

// 加载wasm
const instance = await WebAssembly.instantiateStreaming(
    fetch('module.wasm'),
    importObject
).then(results =&gt; results.instance);

// C代码中使用
/*
#include &lt;emscripten.h&gt;

extern void js_console_log(const char* str, int length);
extern double js_random();
extern void js_set_title(const char* title, int length);

void log_message() {
    const char* msg = "Hello from WebAssembly!";
    js_console_log(msg, strlen(msg));
}

double get_random() {
    return js_random();
}

void change_title() {
    const char* title = "New Title";
    js_set_title(title, strlen(title));
}
*/
                </pre>
            </div>
        </div>
        
        <h2>共享内存</h2>
        
        <div class="interaction-demo">
            <h3>内存共享</h3>
            <div class="code-block">
                <pre>
// 创建共享内存
const memory = new WebAssembly.Memory({ 
    initial: 256,
    maximum: 1024,
    shared: true  // SharedArrayBuffer
});

const importObject = {
    env: { memory }
};

// 加载wasm
const instance = await WebAssembly.instantiateStreaming(
    fetch('module.wasm'),
    importObject
).then(results =&gt; results.instance);

// JavaScript和wasm共享内存
const buffer = memory.buffer;
const view = new Int32Array(buffer);

// JavaScript写入
view[0] = 100;
view[1] = 200;

// wasm读取和修改
instance.exports.process_shared_memory();

// JavaScript读取结果
console.log(view[0], view[1]);

// 多线程共享(需要SharedArrayBuffer)
if (typeof SharedArrayBuffer !== 'undefined') {
    const sharedMemory = new WebAssembly.Memory({
        initial: 256,
        maximum: 1024,
        shared: true
    });
    
    // 可以在多个Worker中共享
    const worker = new Worker('worker.js');
    worker.postMessage({ memory: sharedMemory });
}
                </pre>
            </div>
        </div>
        
        <h2>函数表</h2>
        
        <div class="interaction-demo">
            <h3>间接调用</h3>
            <div class="code-block">
                <pre>
// 创建函数表
const table = new WebAssembly.Table({
    initial: 10,
    element: 'anyfunc'
});

const importObject = {
    env: {
        table,
        memory: new WebAssembly.Memory({ initial: 256 })
    }
};

// 加载wasm
const instance = await WebAssembly.instantiateStreaming(
    fetch('module.wasm'),
    importObject
).then(results =&gt; results.instance);

// wasm填充函数表
instance.exports.fill_table();

// JavaScript调用函数表中的函数
const func0 = table.get(0);
const func1 = table.get(1);

console.log(func0(10, 5)); // 调用第一个函数
console.log(func1(10, 5)); // 调用第二个函数

// 动态添加JavaScript函数到表
table.set(2, (a, b) =&gt; a * b);

// wasm可以调用这个JavaScript函数
instance.exports.call_table_function(2, 10, 5); // 50
                </pre>
            </div>
        </div>
        
        <h2>性能优化</h2>
        
        <div class="interaction-demo">
            <h3>减少交互开销</h3>
            <div class="code-block">
                <pre>
// ❌ 频繁调用,性能差
for (let i = 0; i &lt; 1000000; i++) {
    instance.exports.process_single(data[i]);
}

// ✅ 批量处理,性能好
const dataArray = new Float32Array(1000000);
// ... 填充数据
const ptr = instance.exports.alloc(1000000 * 4);
const wasmArray = new Float32Array(memory.buffer, ptr, 1000000);
wasmArray.set(dataArray);
instance.exports.process_batch(ptr, 1000000);

// ❌ 频繁字符串传递
for (let i = 0; i &lt; 1000; i++) {
    const str = `Item ${i}`;
    const ptr = allocateString(str);
    instance.exports.process_string(ptr);
    deallocateString(ptr);
}

// ✅ 复用内存
const maxLen = 100;
const ptr = instance.exports.alloc(maxLen);
const buffer = new Uint8Array(memory.buffer, ptr, maxLen);
const encoder = new TextEncoder();

for (let i = 0; i &lt; 1000; i++) {
    const str = `Item ${i}`;
    const bytes = encoder.encode(str);
    buffer.set(bytes);
    instance.exports.process_string(ptr, bytes.length);
}

instance.exports.dealloc(ptr, maxLen);
                </pre>
            </div>
        </div>
        
        <div style="background: #fff3cd; padding: 15px; border-radius: 5px; margin-top: 20px;">
            <strong>东巴文提示:</strong>JavaScript与WebAssembly的交互需要理解内存布局、函数调用约定。减少跨边界调用、批量处理数据、复用内存,能显著提升性能。
        </div>
    </div>
</body>
</html>

学习检验

完成本章学习后,请尝试回答以下问题:

  1. 选择题: WebAssembly的主要优势是什么?

    • A. 更好的DOM操作能力
    • B. 接近原生的执行性能
    • C. 更小的文件体积
    • D. 更简单的语法
  2. 填空题: Emscripten是将____代码编译为WebAssembly的工具链。

  3. 简答题: WebAssembly适合哪些应用场景?为什么?

  4. 实践题: 使用Emscripten编译一个简单的C函数(如计算斐波那契数列),并在JavaScript中调用。

  5. 应用题: 分析一个使用WebAssembly的实际项目(如Figma、Google Earth),总结其WebAssembly应用方式。