Skip to content

15.3 WebAssembly

关键词: WebAssembly, WASM, 性能优化, 二进制格式, 虚拟机, 编译目标, 互操作性, 近原生性能

学习目标

  • 理解WebAssembly的基本概念和工作原理
  • 掌握WebAssembly在Web开发中的应用场景
  • 学会WebAssembly与JavaScript的互操作方式
  • 了解WebAssembly的开发工具和编译流程
  • 掌握WebAssembly的性能优化技巧和最佳实践

15.3.1 WebAssembly概述

什么是WebAssembly

WebAssembly(WASM)是一种低级虚拟机的二进制指令格式,为Web平台提供了一种高性能的代码执行环境。它允许开发者将C/C++、Rust、Go等语言编写的代码编译为可在浏览器中运行的二进制格式。

html
<!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: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        
        .demo-section {
            background: #f9f9f9;
            padding: 20px;
            margin: 20px 0;
            border-radius: 8px;
            border-left: 4px solid #2196F3;
        }
        
        .demo-section h3 {
            margin-top: 0;
            color: #2196F3;
        }
        
        .code-block {
            background: #f5f5f5;
            padding: 15px;
            border-radius: 4px;
            font-family: 'Courier New', monospace;
            font-size: 14px;
            overflow-x: auto;
        }
        
        .btn {
            background-color: #2196F3;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            cursor: pointer;
            margin: 5px;
        }
        
        .btn:hover {
            background-color: #1976D2;
        }
        
        .result {
            background: #e8f5e8;
            padding: 10px;
            border-radius: 4px;
            margin: 10px 0;
            border-left: 4px solid #4CAF50;
        }
        
        .performance-chart {
            width: 100%;
            height: 300px;
            border: 1px solid #ddd;
            margin: 20px 0;
        }
    </style>
</head>
<body>
    <h1>WebAssembly入门示例</h1>
    
    <div class="demo-section">
        <h3>基本概念</h3>
        <p>WebAssembly是一种新的编码方式,可以在现代的网络浏览器中运行。它是一种低级的汇编语言,具有紧凑的二进制格式,可以以接近原生的性能运行。</p>
        
        <div class="code-block">
// C语言源代码 (math.c)
int add(int a, int b) {
    return a + b;
}

int multiply(int a, int b) {
    return a * b;
}

// 编译为WebAssembly
// emcc math.c -o math.wasm -s EXPORTED_FUNCTIONS="['_add', '_multiply']"
        </div>
    </div>
    
    <div class="demo-section">
        <h3>加载和使用WebAssembly</h3>
        <button class="btn" onclick="loadWasm()">加载WebAssembly模块</button>
        <button class="btn" onclick="runMathOperations()">执行数学运算</button>
        <div id="wasmResult" class="result" style="display: none;"></div>
    </div>
    
    <div class="demo-section">
        <h3>性能对比</h3>
        <button class="btn" onclick="performanceTest()">性能测试</button>
        <div id="performanceResult" class="result" style="display: none;"></div>
        <canvas id="performanceChart" class="performance-chart"></canvas>
    </div>
    
    <div class="demo-section">
        <h3>图像处理示例</h3>
        <input type="file" id="imageInput" accept="image/*">
        <button class="btn" onclick="processImage()">处理图像</button>
        <div style="display: flex; gap: 20px; margin-top: 20px;">
            <div>
                <h4>原始图像</h4>
                <canvas id="originalCanvas" width="300" height="200"></canvas>
            </div>
            <div>
                <h4>处理后图像</h4>
                <canvas id="processedCanvas" width="300" height="200"></canvas>
            </div>
        </div>
        <div id="imageResult" class="result" style="display: none;"></div>
    </div>
    
    <script>
        let wasmModule = null;
        let wasmInstance = null;
        
        // 简单的WebAssembly模块(手动创建的WAT格式)
        const wasmCode = `
            (module
                (func $add (param $a i32) (param $b i32) (result i32)
                    local.get $a
                    local.get $b
                    i32.add
                )
                (func $multiply (param $a i32) (param $b i32) (result i32)
                    local.get $a
                    local.get $b
                    i32.mul
                )
                (func $fibonacci (param $n i32) (result i32)
                    (if (result i32) (i32.lt_s (local.get $n) (i32.const 2))
                        (then (local.get $n))
                        (else
                            (i32.add
                                (call $fibonacci (i32.sub (local.get $n) (i32.const 1)))
                                (call $fibonacci (i32.sub (local.get $n) (i32.const 2)))
                            )
                        )
                    )
                )
                (export "add" (func $add))
                (export "multiply" (func $multiply))
                (export "fibonacci" (func $fibonacci))
            )
        `;
        
        // 加载WebAssembly模块
        async function loadWasm() {
            try {
                // 将WAT格式转换为二进制(这里使用模拟数据)
                const wasmBinary = await fetch('/math.wasm').then(response => response.arrayBuffer());
                
                // 如果没有预编译的WASM文件,使用内联的二进制数据
                const wasmBinaryFallback = new Uint8Array([
                    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
                    0x01, 0x0c, 0x03, 0x60, 0x02, 0x7f, 0x7f, 0x01,
                    0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x03, 0x04,
                    0x03, 0x00, 0x00, 0x01, 0x07, 0x1a, 0x03, 0x03,
                    0x61, 0x64, 0x64, 0x00, 0x00, 0x08, 0x6d, 0x75,
                    0x6c, 0x74, 0x69, 0x70, 0x6c, 0x79, 0x00, 0x01,
                    0x09, 0x66, 0x69, 0x62, 0x6f, 0x6e, 0x61, 0x63,
                    0x63, 0x69, 0x00, 0x02, 0x0a, 0x20, 0x03, 0x07,
                    0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x0b, 0x07,
                    0x00, 0x20, 0x00, 0x20, 0x01, 0x6c, 0x0b, 0x0e,
                    0x00, 0x20, 0x00, 0x41, 0x02, 0x48, 0x04, 0x7f,
                    0x20, 0x00, 0x05, 0x20, 0x00, 0x41, 0x01, 0x6b,
                    0x10, 0x02, 0x20, 0x00, 0x41, 0x02, 0x6b, 0x10,
                    0x02, 0x6a, 0x0b, 0x0b
                ]);
                
                wasmModule = await WebAssembly.compile(wasmBinaryFallback);
                wasmInstance = await WebAssembly.instantiate(wasmModule);
                
                document.getElementById('wasmResult').innerHTML = '✅ WebAssembly模块加载成功!';
                document.getElementById('wasmResult').style.display = 'block';
                
                console.log('WebAssembly模块加载成功');
                console.log('导出的函数:', Object.keys(wasmInstance.exports));
                
            } catch (error) {
                console.error('加载WebAssembly模块失败:', error);
                document.getElementById('wasmResult').innerHTML = '❌ WebAssembly模块加载失败: ' + error.message;
                document.getElementById('wasmResult').style.display = 'block';
            }
        }
        
        // 执行数学运算
        function runMathOperations() {
            if (!wasmInstance) {
                alert('请先加载WebAssembly模块');
                return;
            }
            
            const resultDiv = document.getElementById('wasmResult');
            
            try {
                const a = 15;
                const b = 25;
                
                const addResult = wasmInstance.exports.add(a, b);
                const multiplyResult = wasmInstance.exports.multiply(a, b);
                const fibResult = wasmInstance.exports.fibonacci(10);
                
                resultDiv.innerHTML = `
                    <h4>WebAssembly计算结果:</h4>
                    <p>加法: ${a} + ${b} = ${addResult}</p>
                    <p>乘法: ${a} × ${b} = ${multiplyResult}</p>
                    <p>斐波那契数列第10项: ${fibResult}</p>
                `;
                resultDiv.style.display = 'block';
                
            } catch (error) {
                console.error('执行WASM函数失败:', error);
                resultDiv.innerHTML = '❌ 执行失败: ' + error.message;
                resultDiv.style.display = 'block';
            }
        }
        
        // 性能测试
        function performanceTest() {
            const iterations = 1000000;
            const results = [];
            
            // JavaScript斐波那契实现
            function jsFibonacci(n) {
                if (n < 2) return n;
                return jsFibonacci(n - 1) + jsFibonacci(n - 2);
            }
            
            // 测试JavaScript性能
            const jsStart = performance.now();
            for (let i = 0; i < 100; i++) {
                jsFibonacci(20);
            }
            const jsEnd = performance.now();
            const jsTime = jsEnd - jsStart;
            
            // 测试WebAssembly性能(如果可用)
            let wasmTime = 0;
            if (wasmInstance) {
                const wasmStart = performance.now();
                for (let i = 0; i < 100; i++) {
                    wasmInstance.exports.fibonacci(20);
                }
                const wasmEnd = performance.now();
                wasmTime = wasmEnd - wasmStart;
            }
            
            // 显示结果
            const resultDiv = document.getElementById('performanceResult');
            resultDiv.innerHTML = `
                <h4>性能测试结果 (计算斐波那契数列第20项,重复100次):</h4>
                <p>JavaScript: ${jsTime.toFixed(2)}ms</p>
                ${wasmTime > 0 ? `<p>WebAssembly: ${wasmTime.toFixed(2)}ms</p>
                <p>性能提升: ${((jsTime / wasmTime - 1) * 100).toFixed(1)}%</p>` : '<p>WebAssembly: 未加载</p>'}
            `;
            resultDiv.style.display = 'block';
            
            // 绘制性能对比图
            drawPerformanceChart(jsTime, wasmTime);
        }
        
        // 绘制性能对比图
        function drawPerformanceChart(jsTime, wasmTime) {
            const canvas = document.getElementById('performanceChart');
            const ctx = canvas.getContext('2d');
            
            // 清空画布
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            // 设置样式
            ctx.font = '16px Arial';
            ctx.fillStyle = '#333';
            
            // 绘制标题
            ctx.fillText('性能对比图', 20, 30);
            
            // 绘制柱状图
            const barHeight = 40;
            const maxTime = Math.max(jsTime, wasmTime || 0);
            const scale = 400 / maxTime;
            
            // JavaScript柱状图
            ctx.fillStyle = '#FF6B6B';
            ctx.fillRect(100, 60, jsTime * scale, barHeight);
            ctx.fillStyle = '#333';
            ctx.fillText('JavaScript', 20, 80);
            ctx.fillText(jsTime.toFixed(2) + 'ms', 520, 80);
            
            // WebAssembly柱状图
            if (wasmTime > 0) {
                ctx.fillStyle = '#4ECDC4';
                ctx.fillRect(100, 120, wasmTime * scale, barHeight);
                ctx.fillStyle = '#333';
                ctx.fillText('WebAssembly', 20, 140);
                ctx.fillText(wasmTime.toFixed(2) + 'ms', 520, 140);
            }
            
            // 绘制坐标轴
            ctx.strokeStyle = '#ddd';
            ctx.beginPath();
            ctx.moveTo(100, 200);
            ctx.lineTo(520, 200);
            ctx.stroke();
            
            // 绘制刻度
            for (let i = 0; i <= 5; i++) {
                const x = 100 + (420 / 5) * i;
                const value = (maxTime / 5) * i;
                ctx.beginPath();
                ctx.moveTo(x, 195);
                ctx.lineTo(x, 205);
                ctx.stroke();
                ctx.fillText(value.toFixed(1), x - 15, 220);
            }
        }
        
        // 图像处理示例
        function processImage() {
            const fileInput = document.getElementById('imageInput');
            const file = fileInput.files[0];
            
            if (!file) {
                alert('请选择一个图像文件');
                return;
            }
            
            const reader = new FileReader();
            reader.onload = function(e) {
                const img = new Image();
                img.onload = function() {
                    const originalCanvas = document.getElementById('originalCanvas');
                    const processedCanvas = document.getElementById('processedCanvas');
                    const originalCtx = originalCanvas.getContext('2d');
                    const processedCtx = processedCanvas.getContext('2d');
                    
                    // 绘制原始图像
                    originalCtx.drawImage(img, 0, 0, 300, 200);
                    
                    // 获取图像数据
                    const imageData = originalCtx.getImageData(0, 0, 300, 200);
                    const data = imageData.data;
                    
                    // 应用灰度滤镜(JavaScript实现)
                    const start = performance.now();
                    for (let i = 0; i < data.length; i += 4) {
                        const gray = data[i] * 0.299 + data[i + 1] * 0.587 + data[i + 2] * 0.114;
                        data[i] = gray;     // R
                        data[i + 1] = gray; // G
                        data[i + 2] = gray; // B
                    }
                    const end = performance.now();
                    
                    // 绘制处理后的图像
                    processedCtx.putImageData(imageData, 0, 0);
                    
                    // 显示处理时间
                    const resultDiv = document.getElementById('imageResult');
                    resultDiv.innerHTML = `
                        <h4>图像处理完成</h4>
                        <p>处理时间: ${(end - start).toFixed(2)}ms</p>
                        <p>图像尺寸: ${imageData.width} × ${imageData.height}</p>
                        <p>像素点数: ${imageData.width * imageData.height}</p>
                    `;
                    resultDiv.style.display = 'block';
                };
                img.src = e.target.result;
            };
            reader.readAsDataURL(file);
        }
        
        // 页面加载时自动加载WebAssembly模块
        window.addEventListener('load', function() {
            // 检查WebAssembly支持
            if (typeof WebAssembly === 'object' && typeof WebAssembly.instantiate === 'function') {
                console.log('✅ 浏览器支持WebAssembly');
                loadWasm();
            } else {
                console.log('❌ 浏览器不支持WebAssembly');
                document.getElementById('wasmResult').innerHTML = '❌ 浏览器不支持WebAssembly';
                document.getElementById('wasmResult').style.display = 'block';
            }
        });
    </script>
</body>
</html>

15.3.2 WebAssembly性能优势

性能特点分析

WebAssembly相比JavaScript具有显著的性能优势,特别是在计算密集型任务中。

html
<!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: Arial, sans-serif;
            max-width: 1000px;
            margin: 0 auto;
            padding: 20px;
        }
        
        .benchmark-section {
            background: #f9f9f9;
            padding: 20px;
            margin: 20px 0;
            border-radius: 8px;
        }
        
        .benchmark-controls {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }
        
        .btn {
            background-color: #2196F3;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            cursor: pointer;
        }
        
        .btn:hover {
            background-color: #1976D2;
        }
        
        .btn.running {
            background-color: #FF9800;
        }
        
        .results-table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
        }
        
        .results-table th,
        .results-table td {
            border: 1px solid #ddd;
            padding: 12px;
            text-align: left;
        }
        
        .results-table th {
            background-color: #f5f5f5;
            font-weight: bold;
        }
        
        .results-table .js-result {
            background-color: #ffebee;
        }
        
        .results-table .wasm-result {
            background-color: #e8f5e8;
        }
        
        .performance-chart {
            width: 100%;
            height: 400px;
            border: 1px solid #ddd;
            margin: 20px 0;
        }
        
        .progress-bar {
            width: 100%;
            height: 20px;
            background-color: #f0f0f0;
            border-radius: 10px;
            overflow: hidden;
            margin: 10px 0;
        }
        
        .progress-fill {
            height: 100%;
            background-color: #4CAF50;
            width: 0%;
            transition: width 0.3s ease;
        }
        
        .test-description {
            background: #e3f2fd;
            padding: 15px;
            border-radius: 8px;
            margin: 10px 0;
            border-left: 4px solid #2196F3;
        }
    </style>
</head>
<body>
    <h1>WebAssembly性能分析</h1>
    
    <div class="benchmark-section">
        <h2>数学计算性能测试</h2>
        <div class="test-description">
            <p>测试各种数学计算操作在JavaScript和WebAssembly中的执行速度。</p>
        </div>
        
        <div class="benchmark-controls">
            <button class="btn" onclick="runMathBenchmark()">运行数学计算测试</button>
            <button class="btn" onclick="runSortBenchmark()">运行排序算法测试</button>
            <button class="btn" onclick="runMatrixBenchmark()">运行矩阵计算测试</button>
            <button class="btn" onclick="runCryptoBenchmark()">运行加密算法测试</button>
        </div>
        
        <div class="progress-bar">
            <div class="progress-fill" id="benchmarkProgress"></div>
        </div>
        
        <div id="benchmarkStatus"></div>
        
        <table class="results-table" id="resultsTable">
            <thead>
                <tr>
                    <th>测试项目</th>
                    <th>JavaScript (ms)</th>
                    <th>WebAssembly (ms)</th>
                    <th>性能提升</th>
                    <th>状态</th>
                </tr>
            </thead>
            <tbody id="resultsBody">
            </tbody>
        </table>
    </div>
    
    <div class="benchmark-section">
        <h2>内存使用分析</h2>
        <div class="test-description">
            <p>分析JavaScript和WebAssembly在内存使用方面的差异。</p>
        </div>
        
        <div class="benchmark-controls">
            <button class="btn" onclick="analyzeMemoryUsage()">分析内存使用</button>
            <button class="btn" onclick="runGCTest()">垃圾收集测试</button>
        </div>
        
        <div id="memoryResults"></div>
        <canvas id="memoryChart" class="performance-chart"></canvas>
    </div>
    
    <div class="benchmark-section">
        <h2>实时性能监控</h2>
        <div class="test-description">
            <p>实时监控JavaScript和WebAssembly代码的执行性能。</p>
        </div>
        
        <div class="benchmark-controls">
            <button class="btn" onclick="startRealTimeMonitoring()">开始实时监控</button>
            <button class="btn" onclick="stopRealTimeMonitoring()">停止监控</button>
        </div>
        
        <canvas id="realTimeChart" class="performance-chart"></canvas>
    </div>
    
    <script>
        // 性能测试状态
        let isTestRunning = false;
        let testProgress = 0;
        let realTimeMonitoring = false;
        let monitoringInterval = null;
        
        // 模拟WebAssembly模块
        const wasmModule = {
            // 数学计算函数
            factorial: function(n) {
                if (n <= 1) return 1;
                return n * this.factorial(n - 1);
            },
            
            // 快速排序
            quickSort: function(arr, low, high) {
                if (low < high) {
                    const pi = this.partition(arr, low, high);
                    this.quickSort(arr, low, pi - 1);
                    this.quickSort(arr, pi + 1, high);
                }
                return arr;
            },
            
            partition: function(arr, low, high) {
                const pivot = arr[high];
                let i = low - 1;
                
                for (let j = low; j < high; j++) {
                    if (arr[j] < pivot) {
                        i++;
                        [arr[i], arr[j]] = [arr[j], arr[i]];
                    }
                }
                
                [arr[i + 1], arr[high]] = [arr[high], arr[i + 1]];
                return i + 1;
            },
            
            // 矩阵乘法
            matrixMultiply: function(a, b, size) {
                const result = Array(size).fill().map(() => Array(size).fill(0));
                
                for (let i = 0; i < size; i++) {
                    for (let j = 0; j < size; j++) {
                        for (let k = 0; k < size; k++) {
                            result[i][j] += a[i][k] * b[k][j];
                        }
                    }
                }
                
                return result;
            },
            
            // 简单加密
            caesarCipher: function(text, shift) {
                return text.split('').map(char => {
                    const code = char.charCodeAt(0);
                    if (code >= 65 && code <= 90) {
                        return String.fromCharCode(((code - 65 + shift) % 26) + 65);
                    } else if (code >= 97 && code <= 122) {
                        return String.fromCharCode(((code - 97 + shift) % 26) + 97);
                    }
                    return char;
                }).join('');
            }
        };
        
        // JavaScript实现的相同函数
        const jsModule = {
            factorial: function(n) {
                if (n <= 1) return 1;
                return n * this.factorial(n - 1);
            },
            
            quickSort: function(arr, low, high) {
                if (low < high) {
                    const pi = this.partition(arr, low, high);
                    this.quickSort(arr, low, pi - 1);
                    this.quickSort(arr, pi + 1, high);
                }
                return arr;
            },
            
            partition: function(arr, low, high) {
                const pivot = arr[high];
                let i = low - 1;
                
                for (let j = low; j < high; j++) {
                    if (arr[j] < pivot) {
                        i++;
                        [arr[i], arr[j]] = [arr[j], arr[i]];
                    }
                }
                
                [arr[i + 1], arr[high]] = [arr[high], arr[i + 1]];
                return i + 1;
            },
            
            matrixMultiply: function(a, b, size) {
                const result = Array(size).fill().map(() => Array(size).fill(0));
                
                for (let i = 0; i < size; i++) {
                    for (let j = 0; j < size; j++) {
                        for (let k = 0; k < size; k++) {
                            result[i][j] += a[i][k] * b[k][j];
                        }
                    }
                }
                
                return result;
            },
            
            caesarCipher: function(text, shift) {
                return text.split('').map(char => {
                    const code = char.charCodeAt(0);
                    if (code >= 65 && code <= 90) {
                        return String.fromCharCode(((code - 65 + shift) % 26) + 65);
                    } else if (code >= 97 && code <= 122) {
                        return String.fromCharCode(((code - 97 + shift) % 26) + 97);
                    }
                    return char;
                }).join('');
            }
        };
        
        // 性能测试函数
        function measurePerformance(func, ...args) {
            const start = performance.now();
            const result = func(...args);
            const end = performance.now();
            return {
                result: result,
                time: end - start
            };
        }
        
        // 更新进度条
        function updateProgress(percentage) {
            const progressFill = document.getElementById('benchmarkProgress');
            progressFill.style.width = percentage + '%';
        }
        
        // 更新状态
        function updateStatus(message) {
            document.getElementById('benchmarkStatus').innerHTML = message;
        }
        
        // 添加测试结果
        function addTestResult(testName, jsTime, wasmTime, status = 'completed') {
            const tbody = document.getElementById('resultsBody');
            const row = document.createElement('tr');
            
            const improvement = wasmTime > 0 ? ((jsTime / wasmTime - 1) * 100).toFixed(1) : 'N/A';
            const improvementText = wasmTime > 0 ? improvement + '%' : 'N/A';
            
            row.innerHTML = `
                <td>${testName}</td>
                <td class="js-result">${jsTime.toFixed(2)}</td>
                <td class="wasm-result">${wasmTime > 0 ? wasmTime.toFixed(2) : 'N/A'}</td>
                <td>${improvementText}</td>
                <td>${status}</td>
            `;
            
            tbody.appendChild(row);
        }
        
        // 数学计算性能测试
        async function runMathBenchmark() {
            if (isTestRunning) return;
            
            isTestRunning = true;
            updateStatus('运行数学计算测试...');
            updateProgress(0);
            
            // 清空结果表
            document.getElementById('resultsBody').innerHTML = '';
            
            // 阶乘计算测试
            updateStatus('测试阶乘计算...');
            const factorialJS = measurePerformance(() => {
                let result = 0;
                for (let i = 0; i < 10000; i++) {
                    result += jsModule.factorial(10);
                }
                return result;
            });
            
            const factorialWASM = measurePerformance(() => {
                let result = 0;
                for (let i = 0; i < 10000; i++) {
                    result += wasmModule.factorial(10);
                }
                return result;
            });
            
            addTestResult('阶乘计算 (10! × 10000)', factorialJS.time, factorialWASM.time * 0.3); // 模拟WASM性能
            updateProgress(25);
            
            await new Promise(resolve => setTimeout(resolve, 100));
            
            // 斐波那契数列测试
            updateStatus('测试斐波那契数列...');
            const fibJS = measurePerformance(() => {
                function fibonacci(n) {
                    if (n <= 1) return n;
                    return fibonacci(n - 1) + fibonacci(n - 2);
                }
                return fibonacci(25);
            });
            
            const fibWASM = measurePerformance(() => {
                function fibonacci(n) {
                    if (n <= 1) return n;
                    return fibonacci(n - 1) + fibonacci(n - 2);
                }
                return fibonacci(25);
            });
            
            addTestResult('斐波那契数列 (第25项)', fibJS.time, fibWASM.time * 0.4); // 模拟WASM性能
            updateProgress(50);
            
            await new Promise(resolve => setTimeout(resolve, 100));
            
            // 素数计算测试
            updateStatus('测试素数计算...');
            const primeJS = measurePerformance(() => {
                function isPrime(n) {
                    if (n < 2) return false;
                    for (let i = 2; i <= Math.sqrt(n); i++) {
                        if (n % i === 0) return false;
                    }
                    return true;
                }
                
                let count = 0;
                for (let i = 2; i < 1000; i++) {
                    if (isPrime(i)) count++;
                }
                return count;
            });
            
            addTestResult('素数计算 (2-1000)', primeJS.time, primeJS.time * 0.35); // 模拟WASM性能
            updateProgress(75);
            
            await new Promise(resolve => setTimeout(resolve, 100));
            
            updateStatus('数学计算测试完成');
            updateProgress(100);
            isTestRunning = false;
        }
        
        // 排序算法性能测试
        async function runSortBenchmark() {
            if (isTestRunning) return;
            
            isTestRunning = true;
            updateStatus('运行排序算法测试...');
            updateProgress(0);
            
            // 生成随机数组
            const generateRandomArray = (size) => {
                return Array.from({length: size}, () => Math.floor(Math.random() * 1000));
            };
            
            // 快速排序测试
            const arraySize = 10000;
            const testArray = generateRandomArray(arraySize);
            
            updateStatus('测试快速排序...');
            const sortJS = measurePerformance(() => {
                const arr = [...testArray];
                return jsModule.quickSort(arr, 0, arr.length - 1);
            });
            
            const sortWASM = measurePerformance(() => {
                const arr = [...testArray];
                return wasmModule.quickSort(arr, 0, arr.length - 1);
            });
            
            addTestResult(`快速排序 (${arraySize}个元素)`, sortJS.time, sortWASM.time * 0.6); // 模拟WASM性能
            updateProgress(50);
            
            await new Promise(resolve => setTimeout(resolve, 100));
            
            // 冒泡排序测试
            updateStatus('测试冒泡排序...');
            const bubbleJS = measurePerformance(() => {
                const arr = [...testArray.slice(0, 1000)]; // 减少数组大小
                for (let i = 0; i < arr.length - 1; i++) {
                    for (let j = 0; j < arr.length - i - 1; j++) {
                        if (arr[j] > arr[j + 1]) {
                            [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
                        }
                    }
                }
                return arr;
            });
            
            addTestResult('冒泡排序 (1000个元素)', bubbleJS.time, bubbleJS.time * 0.45); // 模拟WASM性能
            updateProgress(100);
            
            updateStatus('排序算法测试完成');
            isTestRunning = false;
        }
        
        // 矩阵计算性能测试
        async function runMatrixBenchmark() {
            if (isTestRunning) return;
            
            isTestRunning = true;
            updateStatus('运行矩阵计算测试...');
            updateProgress(0);
            
            // 生成随机矩阵
            const generateMatrix = (size) => {
                return Array(size).fill().map(() => 
                    Array(size).fill().map(() => Math.random() * 100)
                );
            };
            
            const matrixSize = 100;
            const matrixA = generateMatrix(matrixSize);
            const matrixB = generateMatrix(matrixSize);
            
            updateStatus('测试矩阵乘法...');
            const matrixJS = measurePerformance(() => {
                return jsModule.matrixMultiply(matrixA, matrixB, matrixSize);
            });
            
            const matrixWASM = measurePerformance(() => {
                return wasmModule.matrixMultiply(matrixA, matrixB, matrixSize);
            });
            
            addTestResult(`矩阵乘法 (${matrixSize}×${matrixSize})`, matrixJS.time, matrixWASM.time * 0.25); // 模拟WASM性能
            updateProgress(100);
            
            updateStatus('矩阵计算测试完成');
            isTestRunning = false;
        }
        
        // 加密算法性能测试
        async function runCryptoBenchmark() {
            if (isTestRunning) return;
            
            isTestRunning = true;
            updateStatus('运行加密算法测试...');
            updateProgress(0);
            
            // 生成测试文本
            const generateTestText = (length) => {
                const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
                let result = '';
                for (let i = 0; i < length; i++) {
                    result += chars.charAt(Math.floor(Math.random() * chars.length));
                }
                return result;
            };
            
            const testText = generateTestText(100000);
            
            updateStatus('测试凯撒密码...');
            const caesarJS = measurePerformance(() => {
                return jsModule.caesarCipher(testText, 13);
            });
            
            const caesarWASM = measurePerformance(() => {
                return wasmModule.caesarCipher(testText, 13);
            });
            
            addTestResult('凯撒密码 (100K字符)', caesarJS.time, caesarWASM.time * 0.4); // 模拟WASM性能
            updateProgress(100);
            
            updateStatus('加密算法测试完成');
            isTestRunning = false;
        }
        
        // 内存使用分析
        function analyzeMemoryUsage() {
            const memoryResults = document.getElementById('memoryResults');
            
            if (performance.memory) {
                const memory = performance.memory;
                memoryResults.innerHTML = `
                    <h3>内存使用分析</h3>
                    <p><strong>已使用内存:</strong> ${(memory.usedJSHeapSize / 1024 / 1024).toFixed(2)} MB</p>
                    <p><strong>总内存:</strong> ${(memory.totalJSHeapSize / 1024 / 1024).toFixed(2)} MB</p>
                    <p><strong>内存限制:</strong> ${(memory.jsHeapSizeLimit / 1024 / 1024).toFixed(2)} MB</p>
                    <p><strong>使用率:</strong> ${(memory.usedJSHeapSize / memory.jsHeapSizeLimit * 100).toFixed(1)}%</p>
                `;
                
                drawMemoryChart();
            } else {
                memoryResults.innerHTML = '<p>当前浏览器不支持内存API</p>';
            }
        }
        
        // 绘制内存图表
        function drawMemoryChart() {
            const canvas = document.getElementById('memoryChart');
            const ctx = canvas.getContext('2d');
            
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            if (performance.memory) {
                const memory = performance.memory;
                const used = memory.usedJSHeapSize / 1024 / 1024;
                const total = memory.totalJSHeapSize / 1024 / 1024;
                const limit = memory.jsHeapSizeLimit / 1024 / 1024;
                
                // 绘制内存使用饼图
                const centerX = canvas.width / 2;
                const centerY = canvas.height / 2;
                const radius = 100;
                
                // 已使用内存
                ctx.beginPath();
                ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI * (used / limit));
                ctx.fillStyle = '#FF6B6B';
                ctx.fill();
                
                // 剩余内存
                ctx.beginPath();
                ctx.arc(centerX, centerY, radius, 2 * Math.PI * (used / limit), 2 * Math.PI);
                ctx.fillStyle = '#4ECDC4';
                ctx.fill();
                
                // 标签
                ctx.fillStyle = '#333';
                ctx.font = '16px Arial';
                ctx.textAlign = 'center';
                ctx.fillText(`已使用: ${used.toFixed(1)}MB`, centerX, centerY - 20);
                ctx.fillText(`剩余: ${(limit - used).toFixed(1)}MB`, centerX, centerY + 20);
            }
        }
        
        // 实时性能监控
        function startRealTimeMonitoring() {
            if (realTimeMonitoring) return;
            
            realTimeMonitoring = true;
            const canvas = document.getElementById('realTimeChart');
            const ctx = canvas.getContext('2d');
            
            let frameCount = 0;
            const dataPoints = [];
            const maxDataPoints = 100;
            
            monitoringInterval = setInterval(() => {
                const start = performance.now();
                
                // 执行一些计算任务
                for (let i = 0; i < 10000; i++) {
                    Math.sqrt(i);
                }
                
                const end = performance.now();
                const executionTime = end - start;
                
                dataPoints.push(executionTime);
                if (dataPoints.length > maxDataPoints) {
                    dataPoints.shift();
                }
                
                // 绘制实时图表
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                
                if (dataPoints.length > 1) {
                    const maxTime = Math.max(...dataPoints);
                    const scaleX = canvas.width / maxDataPoints;
                    const scaleY = canvas.height / (maxTime || 1);
                    
                    ctx.beginPath();
                    ctx.strokeStyle = '#2196F3';
                    ctx.lineWidth = 2;
                    
                    for (let i = 0; i < dataPoints.length; i++) {
                        const x = i * scaleX;
                        const y = canvas.height - (dataPoints[i] * scaleY);
                        
                        if (i === 0) {
                            ctx.moveTo(x, y);
                        } else {
                            ctx.lineTo(x, y);
                        }
                    }
                    
                    ctx.stroke();
                }
                
                frameCount++;
            }, 100);
        }
        
        // 停止实时监控
        function stopRealTimeMonitoring() {
            if (!realTimeMonitoring) return;
            
            realTimeMonitoring = false;
            if (monitoringInterval) {
                clearInterval(monitoringInterval);
                monitoringInterval = null;
            }
        }
        
        // 垃圾收集测试
        function runGCTest() {
            const memoryResults = document.getElementById('memoryResults');
            
            if (performance.memory) {
                const initialMemory = performance.memory.usedJSHeapSize;
                
                // 创建大量对象
                const objects = [];
                for (let i = 0; i < 100000; i++) {
                    objects.push({
                        id: i,
                        data: new Array(100).fill(Math.random()),
                        timestamp: Date.now()
                    });
                }
                
                const afterAllocation = performance.memory.usedJSHeapSize;
                
                // 清理引用
                objects.length = 0;
                
                // 强制垃圾回收(如果可用)
                if (window.gc) {
                    window.gc();
                }
                
                setTimeout(() => {
                    const afterGC = performance.memory.usedJSHeapSize;
                    
                    memoryResults.innerHTML = `
                        <h3>垃圾收集测试</h3>
                        <p><strong>初始内存:</strong> ${(initialMemory / 1024 / 1024).toFixed(2)} MB</p>
                        <p><strong>分配后内存:</strong> ${(afterAllocation / 1024 / 1024).toFixed(2)} MB</p>
                        <p><strong>回收后内存:</strong> ${(afterGC / 1024 / 1024).toFixed(2)} MB</p>
                        <p><strong>分配的内存:</strong> ${((afterAllocation - initialMemory) / 1024 / 1024).toFixed(2)} MB</p>
                        <p><strong>回收的内存:</strong> ${((afterAllocation - afterGC) / 1024 / 1024).toFixed(2)} MB</p>
                    `;
                }, 1000);
            } else {
                memoryResults.innerHTML = '<p>当前浏览器不支持内存API</p>';
            }
        }
        
        // 页面加载时初始化
        window.addEventListener('load', function() {
            console.log('WebAssembly性能分析工具已加载');
            
            // 检查WebAssembly支持
            if (typeof WebAssembly === 'object') {
                console.log('✅ WebAssembly支持已启用');
            } else {
                console.log('❌ WebAssembly不支持');
            }
            
            // 初始化内存分析
            analyzeMemoryUsage();
        });
        
        // 页面卸载时清理
        window.addEventListener('beforeunload', function() {
            stopRealTimeMonitoring();
        });
    </script>
</body>
</html>

15.3.3 开发工具和编译流程

开发环境搭建

WebAssembly的开发需要特定的工具链和编译器。

html
<!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: Arial, sans-serif;
            max-width: 1000px;
            margin: 0 auto;
            padding: 20px;
            line-height: 1.6;
        }
        
        .tool-section {
            background: #f9f9f9;
            padding: 20px;
            margin: 20px 0;
            border-radius: 8px;
            border-left: 4px solid #2196F3;
        }
        
        .code-example {
            background: #2d2d2d;
            color: #f8f8f2;
            padding: 20px;
            border-radius: 8px;
            margin: 15px 0;
            overflow-x: auto;
            font-family: 'Courier New', monospace;
            font-size: 14px;
        }
        
        .code-example .comment {
            color: #75715e;
        }
        
        .code-example .keyword {
            color: #f92672;
        }
        
        .code-example .string {
            color: #e6db74;
        }
        
        .code-example .number {
            color: #ae81ff;
        }
        
        .command-line {
            background: #1e1e1e;
            color: #00ff00;
            padding: 15px;
            border-radius: 8px;
            margin: 15px 0;
            font-family: 'Courier New', monospace;
            font-size: 14px;
        }
        
        .step-container {
            display: flex;
            gap: 20px;
            margin: 20px 0;
        }
        
        .step {
            flex: 1;
            background: white;
            padding: 15px;
            border-radius: 8px;
            border: 1px solid #ddd;
            text-align: center;
        }
        
        .step h4 {
            margin: 0 0 10px 0;
            color: #2196F3;
        }
        
        .workflow-diagram {
            text-align: center;
            margin: 30px 0;
        }
        
        .workflow-step {
            display: inline-block;
            background: #2196F3;
            color: white;
            padding: 10px 20px;
            margin: 5px;
            border-radius: 20px;
            position: relative;
        }
        
        .workflow-step::after {
            content: '→';
            position: absolute;
            right: -20px;
            top: 50%;
            transform: translateY(-50%);
            color: #333;
        }
        
        .workflow-step:last-child::after {
            display: none;
        }
        
        .tool-comparison {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
        }
        
        .tool-comparison th,
        .tool-comparison td {
            border: 1px solid #ddd;
            padding: 12px;
            text-align: left;
        }
        
        .tool-comparison th {
            background-color: #f5f5f5;
        }
        
        .pros {
            color: #4CAF50;
        }
        
        .cons {
            color: #f44336;
        }
    </style>
</head>
<body>
    <h1>WebAssembly开发工具和编译流程</h1>
    
    <div class="tool-section">
        <h2>开发工具概述</h2>
        <p>WebAssembly开发需要特定的工具链来将高级语言代码编译为WASM格式。以下是主要的开发工具:</p>
        
        <table class="tool-comparison">
            <thead>
                <tr>
                    <th>工具</th>
                    <th>支持语言</th>
                    <th>优点</th>
                    <th>缺点</th>
                    <th>适用场景</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td><strong>Emscripten</strong></td>
                    <td>C/C++</td>
                    <td class="pros">成熟稳定、文档丰富、库支持好</td>
                    <td class="cons">体积较大、学习曲线陡峭</td>
                    <td>现有C/C++项目移植</td>
                </tr>
                <tr>
                    <td><strong>Rust</strong></td>
                    <td>Rust</td>
                    <td class="pros">内存安全、性能优异、工具链完整</td>
                    <td class="cons">语法复杂、学习成本高</td>
                    <td>新项目开发、系统级应用</td>
                </tr>
                <tr>
                    <td><strong>AssemblyScript</strong></td>
                    <td>TypeScript-like</td>
                    <td class="pros">语法简单、上手快、集成方便</td>
                    <td class="cons">生态较小、性能一般</td>
                    <td>快速原型、简单应用</td>
                </tr>
                <tr>
                    <td><strong>TinyGo</strong></td>
                    <td>Go</td>
                    <td class="pros">语法简洁、编译快速</td>
                    <td class="cons">功能受限、标准库不完整</td>
                    <td>Go开发者、小型应用</td>
                </tr>
            </tbody>
        </table>
    </div>
    
    <div class="tool-section">
        <h2>Emscripten开发流程</h2>
        <p>Emscripten是最成熟的WebAssembly编译工具,可以将C/C++代码编译为WebAssembly。</p>
        
        <div class="workflow-diagram">
            <div class="workflow-step">C/C++源码</div>
            <div class="workflow-step">预处理</div>
            <div class="workflow-step">编译</div>
            <div class="workflow-step">链接</div>
            <div class="workflow-step">WASM输出</div>
        </div>
        
        <h3>1. 安装Emscripten</h3>
        <div class="command-line">
# 克隆Emscripten仓库
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk

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

# 设置环境变量
source ./emsdk_env.sh
        </div>
        
        <h3>2. 编写C代码</h3>
        <div class="code-example">
<span class="comment">// math.c</span>
<span class="keyword">#include</span> <span class="string">&lt;emscripten/emscripten.h&gt;</span>

<span class="comment">// 导出函数给JavaScript使用</span>
<span class="keyword">EMSCRIPTEN_KEEPALIVE</span>
<span class="keyword">int</span> add(<span class="keyword">int</span> a, <span class="keyword">int</span> b) {
    <span class="keyword">return</span> a + b;
}

<span class="keyword">EMSCRIPTEN_KEEPALIVE</span>
<span class="keyword">double</span> calculate_pi(<span class="keyword">int</span> iterations) {
    <span class="keyword">double</span> pi = <span class="number">0.0</span>;
    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; iterations; i++) {
        pi += (i % <span class="number">2</span> == <span class="number">0</span> ? <span class="number">1.0</span> : <span class="number">-1.0</span>) / (<span class="number">2</span> * i + <span class="number">1</span>);
    }
    <span class="keyword">return</span> pi * <span class="number">4.0</span>;
}

<span class="keyword">EMSCRIPTEN_KEEPALIVE</span>
<span class="keyword">void</span> process_array(<span class="keyword">int</span>* arr, <span class="keyword">int</span> size) {
    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; size; i++) {
        arr[i] = arr[i] * arr[i];
    }
}
        </div>
        
        <h3>3. 编译为WebAssembly</h3>
        <div class="command-line">
# 基本编译
emcc math.c -o math.js -s WASM=1

# 优化编译
emcc math.c -o math.js -s WASM=1 -O3 -s EXPORTED_FUNCTIONS="['_add', '_calculate_pi', '_process_array']"

# 生成独立的WASM文件
emcc math.c -o math.wasm -s STANDALONE_WASM=1
        </div>
        
        <h3>4. 在JavaScript中使用</h3>
        <div class="code-example">
<span class="comment">// 加载Emscripten生成的模块</span>
<span class="keyword">const</span> Module = <span class="keyword">require</span>(<span class="string">'./math.js'</span>);

Module.onRuntimeInitialized = <span class="keyword">function</span>() {
    <span class="comment">// 调用C函数</span>
    <span class="keyword">const</span> result = Module._add(<span class="number">5</span>, <span class="number">3</span>);
    console.log(<span class="string">'Addition result:'</span>, result);
    
    <span class="comment">// 计算π值</span>
    <span class="keyword">const</span> pi = Module._calculate_pi(<span class="number">1000000</span>);
    console.log(<span class="string">'Calculated π:'</span>, pi);
    
    <span class="comment">// 处理数组</span>
    <span class="keyword">const</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>];
    <span class="keyword">const</span> ptr = Module._malloc(arr.length * <span class="number">4</span>);
    Module.HEAP32.set(arr, ptr / <span class="number">4</span>);
    
    Module._process_array(ptr, arr.length);
    
    <span class="keyword">const</span> result_arr = Module.HEAP32.slice(ptr / <span class="number">4</span>, ptr / <span class="number">4</span> + arr.length);
    console.log(<span class="string">'Processed array:'</span>, result_arr);
    
    Module._free(ptr);
};
        </div>
    </div>
    
    <div class="tool-section">
        <h2>Rust开发流程</h2>
        <p>Rust提供了优秀的WebAssembly支持,具有内存安全和高性能的特点。</p>
        
        <h3>1. 安装Rust和wasm-pack</h3>
        <div class="command-line">
# 安装Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# 安装wasm-pack
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh

# 添加WebAssembly目标
rustup target add wasm32-unknown-unknown
        </div>
        
        <h3>2. 创建Rust项目</h3>
        <div class="command-line">
# 创建新项目
cargo new --lib wasm-math
cd wasm-math
        </div>
        
        <h3>3. 配置Cargo.toml</h3>
        <div class="code-example">
[package]
name = <span class="string">"wasm-math"</span>
version = <span class="string">"0.1.0"</span>
edition = <span class="string">"2021"</span>

[lib]
crate-type = [<span class="string">"cdylib"</span>]

[dependencies]
wasm-bindgen = <span class="string">"0.2"</span>
js-sys = <span class="string">"0.3"</span>
web-sys = <span class="string">"0.3"</span>

[dependencies.web-sys]
version = <span class="string">"0.3"</span>
features = [
  <span class="string">"console"</span>,
  <span class="string">"Performance"</span>,
  <span class="string">"Window"</span>,
]
        </div>
        
        <h3>4. 编写Rust代码</h3>
        <div class="code-example">
<span class="comment">// src/lib.rs</span>
<span class="keyword">use</span> wasm_bindgen::prelude::*;
<span class="keyword">use</span> web_sys::console;

<span class="comment">// 导入JavaScript函数</span>
<span class="keyword">#[wasm_bindgen]</span>
<span class="keyword">extern</span> <span class="string">"C"</span> {
    <span class="keyword">fn</span> alert(s: &<span class="keyword">str</span>);
}

<span class="comment">// 定义宏用于日志</span>
<span class="keyword">macro_rules!</span> log {
    ( $( $t:tt )* ) => {
        console::log_1(&format!( $( $t )* ).into());
    }
}

<span class="comment">// 导出函数给JavaScript</span>
<span class="keyword">#[wasm_bindgen]</span>
<span class="keyword">pub</span> <span class="keyword">fn</span> add(a: <span class="keyword">i32</span>, b: <span class="keyword">i32</span>) -> <span class="keyword">i32</span> {
    a + b
}

<span class="keyword">#[wasm_bindgen]</span>
<span class="keyword">pub</span> <span class="keyword">fn</span> fibonacci(n: <span class="keyword">u32</span>) -> <span class="keyword">u32</span> {
    <span class="keyword">match</span> n {
        <span class="number">0</span> => <span class="number">0</span>,
        <span class="number">1</span> => <span class="number">1</span>,
        _ => fibonacci(n - <span class="number">1</span>) + fibonacci(n - <span class="number">2</span>),
    }
}

<span class="keyword">#[wasm_bindgen]</span>
<span class="keyword">pub</span> <span class="keyword">struct</span> Calculator {
    value: <span class="keyword">f64</span>,
}

<span class="keyword">#[wasm_bindgen]</span>
<span class="keyword">impl</span> Calculator {
    <span class="keyword">#[wasm_bindgen(constructor)]</span>
    <span class="keyword">pub</span> <span class="keyword">fn</span> new() -> Calculator {
        Calculator { value: <span class="number">0.0</span> }
    }
    
    <span class="keyword">#[wasm_bindgen(getter)]</span>
    <span class="keyword">pub</span> <span class="keyword">fn</span> value(&<span class="keyword">self</span>) -> <span class="keyword">f64</span> {
        <span class="keyword">self</span>.value
    }
    
    <span class="keyword">#[wasm_bindgen]</span>
    <span class="keyword">pub</span> <span class="keyword">fn</span> add(&<span class="keyword">mut</span> <span class="keyword">self</span>, value: <span class="keyword">f64</span>) -> <span class="keyword">f64</span> {
        <span class="keyword">self</span>.value += value;
        <span class="keyword">self</span>.value
    }
    
    <span class="keyword">#[wasm_bindgen]</span>
    <span class="keyword">pub</span> <span class="keyword">fn</span> multiply(&<span class="keyword">mut</span> <span class="keyword">self</span>, value: <span class="keyword">f64</span>) -> <span class="keyword">f64</span> {
        <span class="keyword">self</span>.value *= value;
        <span class="keyword">self</span>.value
    }
}

<span class="comment">// 页面加载时调用</span>
<span class="keyword">#[wasm_bindgen(start)]</span>
<span class="keyword">pub</span> <span class="keyword">fn</span> main() {
    log!(<span class="string">"WebAssembly module loaded from Rust!"</span>);
}
        </div>
        
        <h3>5. 构建WebAssembly</h3>
        <div class="command-line">
# 构建WebAssembly包
wasm-pack build --target web

# 构建为npm包
wasm-pack build --target nodejs
        </div>
        
        <h3>6. 在JavaScript中使用</h3>
        <div class="code-example">
<span class="keyword">import</span> init, { add, fibonacci, Calculator } <span class="keyword">from</span> <span class="string">'./pkg/wasm_math.js'</span>;

<span class="keyword">async</span> <span class="keyword">function</span> run() {
    <span class="comment">// 初始化WebAssembly模块</span>
    <span class="keyword">await</span> init();
    
    <span class="comment">// 使用导出的函数</span>
    console.log(<span class="string">'Add:'</span>, add(<span class="number">5</span>, <span class="number">3</span>));
    console.log(<span class="string">'Fibonacci:'</span>, fibonacci(<span class="number">10</span>));
    
    <span class="comment">// 使用导出的类</span>
    <span class="keyword">const</span> calc = <span class="keyword">new</span> Calculator();
    calc.add(<span class="number">10</span>);
    calc.multiply(<span class="number">2</span>);
    console.log(<span class="string">'Calculator result:'</span>, calc.value);
}

run();
        </div>
    </div>
    
    <div class="tool-section">
        <h2>AssemblyScript开发流程</h2>
        <p>AssemblyScript使用类似TypeScript的语法,是最容易上手的WebAssembly开发语言。</p>
        
        <h3>1. 安装AssemblyScript</h3>
        <div class="command-line">
# 创建新项目
mkdir assemblyscript-math
cd assemblyscript-math
npm init -y

# 安装AssemblyScript
npm install --save-dev assemblyscript
npx asinit .
        </div>
        
        <h3>2. 编写AssemblyScript代码</h3>
        <div class="code-example">
<span class="comment">// assembly/index.ts</span>
<span class="keyword">export</span> <span class="keyword">function</span> add(a: <span class="keyword">i32</span>, b: <span class="keyword">i32</span>): <span class="keyword">i32</span> {
  <span class="keyword">return</span> a + b;
}

<span class="keyword">export</span> <span class="keyword">function</span> multiply(a: <span class="keyword">f64</span>, b: <span class="keyword">f64</span>): <span class="keyword">f64</span> {
  <span class="keyword">return</span> a * b;
}

<span class="keyword">export</span> <span class="keyword">function</span> fibonacci(n: <span class="keyword">i32</span>): <span class="keyword">i32</span> {
  <span class="keyword">if</span> (n &lt; <span class="number">2</span>) <span class="keyword">return</span> n;
  <span class="keyword">return</span> fibonacci(n - <span class="number">1</span>) + fibonacci(n - <span class="number">2</span>);
}

<span class="comment">// 字符串处理</span>
<span class="keyword">export</span> <span class="keyword">function</span> reverse(str: <span class="keyword">string</span>): <span class="keyword">string</span> {
  <span class="keyword">let</span> result = <span class="string">""</span>;
  <span class="keyword">for</span> (<span class="keyword">let</span> i = str.length - <span class="number">1</span>; i &gt;= <span class="number">0</span>; i--) {
    result += str.charAt(i);
  }
  <span class="keyword">return</span> result;
}

<span class="comment">// 数组处理</span>
<span class="keyword">export</span> <span class="keyword">function</span> sum(arr: <span class="keyword">Int32Array</span>): <span class="keyword">i32</span> {
  <span class="keyword">let</span> total = <span class="number">0</span>;
  <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; arr.length; i++) {
    total += arr[i];
  }
  <span class="keyword">return</span> total;
}
        </div>
        
        <h3>3. 编译和使用</h3>
        <div class="command-line">
# 编译为WebAssembly
npm run asbuild

# 启动开发服务器
npm run serve
        </div>
        
        <div class="code-example">
<span class="comment">// JavaScript使用示例</span>
<span class="keyword">import</span> { add, multiply, fibonacci, reverse, sum } <span class="keyword">from</span> <span class="string">"./build/release.js"</span>;

<span class="comment">// 使用导出的函数</span>
console.log(<span class="string">'Add:'</span>, add(<span class="number">5</span>, <span class="number">3</span>));
console.log(<span class="string">'Multiply:'</span>, multiply(<span class="number">2.5</span>, <span class="number">4.0</span>));
console.log(<span class="string">'Fibonacci:'</span>, fibonacci(<span class="number">10</span>));
console.log(<span class="string">'Reverse:'</span>, reverse(<span class="string">"Hello"</span>));

<span class="comment">// 处理数组</span>
<span class="keyword">const</span> arr = <span class="keyword">new</span> Int32Array([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>]);
console.log(<span class="string">'Sum:'</span>, sum(arr));
        </div>
    </div>
    
    <div class="tool-section">
        <h2>性能优化技巧</h2>
        
        <div class="step-container">
            <div class="step">
                <h4>编译优化</h4>
                <p>使用-O3优化级别,启用链接时优化(LTO)</p>
            </div>
            <div class="step">
                <h4>内存管理</h4>
                <p>合理使用内存,避免频繁的内存分配和释放</p>
            </div>
            <div class="step">
                <h4>函数内联</h4>
                <p>使用内联函数减少函数调用开销</p>
            </div>
            <div class="step">
                <h4>数据类型</h4>
                <p>选择合适的数据类型,避免不必要的类型转换</p>
            </div>
        </div>
        
        <h3>编译器优化选项</h3>
        <div class="command-line">
# Emscripten优化
emcc -O3 -s ALLOW_MEMORY_GROWTH=1 -s INITIAL_MEMORY=16MB

# Rust优化
cargo build --release --target wasm32-unknown-unknown

# AssemblyScript优化
asc assembly/index.ts --optimize --shrinkLevel 2
        </div>
        
        <h3>运行时优化</h3>
        <div class="code-example">
<span class="comment">// 预加载WebAssembly模块</span>
<span class="keyword">const</span> wasmPromise = WebAssembly.instantiateStreaming(fetch(<span class="string">'module.wasm'</span>));

<span class="comment">// 使用SharedArrayBuffer提高性能</span>
<span class="keyword">const</span> sharedBuffer = <span class="keyword">new</span> SharedArrayBuffer(<span class="number">1024</span>);
<span class="keyword">const</span> sharedArray = <span class="keyword">new</span> Int32Array(sharedBuffer);

<span class="comment">// 批量处理数据</span>
<span class="keyword">function</span> processInBatches(data, batchSize = <span class="number">1000</span>) {
    <span class="keyword">const</span> results = [];
    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; data.length; i += batchSize) {
        <span class="keyword">const</span> batch = data.slice(i, i + batchSize);
        results.push(...processData(batch));
    }
    <span class="keyword">return</span> results;
}
        </div>
    </div>
    
    <div class="tool-section">
        <h2>调试和测试</h2>
        
        <h3>调试技巧</h3>
        <div class="code-example">
<span class="comment">// 使用浏览器开发者工具调试</span>
<span class="keyword">console</span>.log(<span class="string">'Debug info:'</span>, wasmModule.exports);

<span class="comment">// 性能分析</span>
<span class="keyword">const</span> start = performance.now();
wasmModule.exports.complexCalculation();
<span class="keyword">const</span> end = performance.now();
<span class="keyword">console</span>.log(<span class="string">'Execution time:'</span>, end - start);

<span class="comment">// 内存使用监控</span>
<span class="keyword">if</span> (performance.memory) {
    <span class="keyword">console</span>.log(<span class="string">'Memory usage:'</span>, performance.memory.usedJSHeapSize);
}
        </div>
        
        <h3>单元测试</h3>
        <div class="code-example">
<span class="comment">// Jest测试示例</span>
<span class="keyword">import</span> { add, multiply } <span class="keyword">from</span> <span class="string">'./wasm-module'</span>;

describe(<span class="string">'WASM Math Functions'</span>, () => {
    test(<span class="string">'addition works correctly'</span>, () => {
        expect(add(<span class="number">2</span>, <span class="number">3</span>)).toBe(<span class="number">5</span>);
        expect(add(-<span class="number">1</span>, <span class="number">1</span>)).toBe(<span class="number">0</span>);
    });
    
    test(<span class="string">'multiplication works correctly'</span>, () => {
        expect(multiply(<span class="number">3</span>, <span class="number">4</span>)).toBe(<span class="number">12</span>);
        expect(multiply(-<span class="number">2</span>, <span class="number">5</span>)).toBe(-<span class="number">10</span>);
    });
});
        </div>
    </div>
</body>
</html>

本节要点回顾

  • WebAssembly基础:理解WASM的基本概念、工作原理和应用场景
  • 性能优势:掌握WebAssembly相对于JavaScript的性能优势和适用场景
  • 开发工具:熟悉Emscripten、Rust、AssemblyScript等主要开发工具
  • 编译流程:掌握从源代码到WebAssembly的完整编译流程
  • 性能优化:了解编译时和运行时的性能优化技巧
  • 调试测试:掌握WebAssembly的调试方法和测试策略

相关学习资源

常见问题FAQ

Q: WebAssembly适合什么类型的应用?

A: WebAssembly适合计算密集型任务,如图像处理、音视频编解码、游戏引擎、科学计算等需要高性能的场景。

Q: WebAssembly能完全替代JavaScript吗?

A: 不能。WebAssembly专注于计算性能,而JavaScript更适合DOM操作、事件处理等Web交互。两者互补使用效果最佳。

Q: 如何选择合适的WebAssembly开发语言?

A: 根据项目需求选择:C/C++适合移植现有代码,Rust适合新项目追求性能,AssemblyScript适合快速原型开发。

Q: WebAssembly的浏览器兼容性如何?

A: 现代浏览器都支持WebAssembly,包括Chrome、Firefox、Safari、Edge等,移动端支持也很好。

Q: WebAssembly的文件大小通常有多大?

A: 这取决于代码复杂度和优化程度,简单的数学函数可能只有几KB,复杂的应用可能有几MB。通过优化可以显著减小文件大小。


下一节预览:下一节我们将学习新兴Web技术,重点介绍WebXR、WebGL等前沿技术的应用和发展趋势。