第三章:探索WebAssembly模块

【WebAssembly】WebAssembly概念介绍和在js中使用 记录下WebAssembly的概念和在JavaScript中的使用方法。 阅读详情

WebAssembly是一种低级别的类汇编代码,设计用于高效执行和紧凑表示。WebAssembly在所有JavaScript引擎中(包括现代桌面和移动浏览器以及Node.js)都能以接近原生的速度运行。二进制的紧凑表示使得生成的二进制尽可能小。

注意

WebAssembly的主要目标是使高性能应用程序成为可能。

每个WebAssembly文件都是一个高效、优化且自足的模块,称为WebAssembly模块(WASM)。WASM是安全的,即二进制文件在一个内存安全和沙盒化的环境中运行。WASM没有权限访问沙盒之外的任何内容。WASM是语言无关、硬件无关和平台无关的。

WebAssembly是一个虚拟指令集架构(ISA)。WebAssembly规范定义了以下内容:

  • 指令集
  • 二进制编码
  • 验证
  • 执行语义

WebAssembly规范还定义了WebAssembly二进制的文本表示。

在本章中,我们将探索WASM以及JavaScript引擎如何执行WASM。然后我们探索WebAssembly文本格式及其有用之处。理解WASM执行和WebAssembly文本格式将使我们能够轻松理解模块并在JavaScript引擎中调试它。我们将在本章中覆盖以下主要主题:

  • 理解WebAssembly如何工作
  • 探索WebAssembly文本格式

理解WebAssembly如何工作

首先,让我们探索JavaScript和WebAssembly如何在JavaScript引擎内部执行。

理解JavaScript引擎内部的JavaScript执行

JavaScript引擎首先获取完整的JavaScript文件(注意,引擎必须等到整个文件被下载/加载完毕)。

注意

JavaScript文件越大,加载所需时间就越长。不管你的JavaScript引擎有多快或你的代码有多高效。如果你的JavaScript文件很大(即,大于170KB),那么你的应用程序在加载时间上会很慢。

Figure 3.1 – JavaScript execution inside the JavaScript engine

图3.1 - JavaScript引擎内的JavaScript执行

一旦加载完成,JavaScript被解析成抽象语法树(ASTs)。这个阶段称为解析。由于JavaScript既是解释型语言也是编译型语言,JavaScript引擎在解析后开始执行。解释器执行代码更快,但它每次都要编译代码。这个阶段称为解释。

JavaScript引擎有观察者(在某些浏览器中称为分析器)。观察者跟踪代码执行情况。如果某个特定的代码块频繁执行,观察者就会将其标记为热点代码。引擎使用即时(JIT)编译器编译这部分代码。引擎花费一些时间进行编译,比如纳秒级别。在这里花费的时间是值得的,因为下次调用该函数时,执行会更快,因为编译后的版本总是比解释版的快。这个阶段称为优化。

JavaScript引擎增加了一层(或两层)更多的优化。观察者继续监控代码执行。然后,观察者将更频繁调用的代码称为非常热的代码。引擎进一步优化这部分代码。这种优化需要较长时间(考虑类似于-O3级别的优化)。这个阶段产生的代码是高度优化的,运行速度非常快。这段代码比之前的优化代码和解释版的运行速度都要快。显然,引擎在这个阶段花费的时间更多,比如毫秒级别。但这通过代码性能和执行频率得到了补偿。

JavaScript是一种动态类型语言,引擎能做的所有优化都基于类型的假设。如果这个假设被打破,那么代码将被解释和执行,并且优化的代码会被移除,而不是抛出运行时异常。JavaScript引擎实现了必要的类型检查,并在假定的类型发生变化时放弃优化代码。但在优化阶段花费的时间就白费了。

我们可以通过使用类似TypeScript的东西来预防这些类型相关的问题。TypeScript是JavaScript的超集。使用TypeScript,我们可以防止多态代码(接受不同类型的代码)。在JavaScript引擎中,单态代码(只接受一种类型的代码)总是比其多态对应物运行得更快。

如果JavaScript文件体积巨大,那么拥有高度优化的单态JavaScript代码也没有用。JavaScript引擎必须等到整个文件下载完成。在网络连接差的情况下,这几乎永远不会发生。

注意

将JavaScript包分割成更小的块很重要。异步包含JavaScript(换句话说,懒加载)可以提升应用程序的性能。我们需要找到正确的平衡,知道哪个JavaScript模块/文件要加载、缓存然后重新验证。较大的文件大小(有效载荷)将极大地降低应用程序的性能。

最后一个步骤是垃圾收集,所有内存中的活动对象都被移除。JavaScript引擎中的垃圾收集是基于引用的。在垃圾收集周期中,JavaScript引擎从根对象(如Node.js中的global)开始。它找到从根对象引用的所有对象,并将它们标记为可达对象。它将剩余的对象标记为不可达对象。最后,它清除不可达对象。由于这是由JavaScript引擎自动完成的,垃圾收集过程效率不高,而且速度要慢得多。

理解JavaScript引擎内的WebAssembly执行

WASM是二进制格式,已经编译和优化。JavaScript引擎获取WASM,然后解码WASM并将其转换为模块的内部表示(即AST)。这个阶段称为解码。解码阶段比JavaScript的解析阶段快得多。

Figure 3.2 – WebAssembly execution inside the JavaScript engine
图3.2 - JavaScript引擎内的WebAssembly执行

接下来,解码后的WASM进入编译阶段。在这个阶段,模块进行验证,验证过程中会检查某些条件以保证模块是安全的,没有任何有害的代码。函数、指令序列和堆栈的使用在验证过程中进行类型检查。然后将已验证的代码编译为机器可执行代码。由于WASM已经被编译和优化,所以这个编译阶段更快。在这个阶段,WASM被转换为机器代码。

编译后的代码随后进入执行阶段。在执行阶段,模块被实例化和调用。在实例化过程中,引擎实例化状态和执行栈(存储与程序相关的所有信息的内存),然后执行模块。

WebAssembly的另一个优势是,模块从第一个字节开始就已准备好编译和实例化。因此,JavaScript引擎不必等到整个模块下载完毕。这进一步提高了WebAssembly的性能。WebAssembly之所以快,是因为它的执行步骤比JavaScript执行少,所以二进制文件已经被优化和编译,且可以进行流式编译。

注意

WASM并不总是提供高性能。在某些情况下,JavaScript表现更佳。因此,了解这一点并在使用WebAssembly之前思考是必要的。

了解更多关于JavaScript性能及其加载时间的影响,请访问 https://medium.com/@addyosmani/the-cost-of-javascript-in-2018-7d8950fbb5d4。

了解更多关于webpack中的分块和代码分割,请访问 https://webpack.js.org/guides/code-splitting/。

我们已经了解了WebAssembly在浏览器内的工作原理;现在,让我们探索WebAssembly文本格式。

探索WebAssembly文本格式

机器理解一串1和0。我们优化二进制文件以使其运行得更快、更高效。指令越简洁和优化,机器的效率和性能就越高。但对人来说,理解和分析一大堆1和0是很困难的。这正是我们开始抽象并创建高级编程语言的原因。

在WebAssembly世界中,我们将人类可读的编程语言(如Rust、Go和C/C++)转换为二进制代码。这些二进制文件是一堆带有操作码和操作数的指令。这些指令使机器高效运行,但从上下文角度让我们难以理解。

为什么我们应该担心生成的二进制文件的可读性?因为它有助于我们理解代码,有助于调试代码。

WebAssembly提供了WebAssembly文本格式,WAST或WAT。WAST是WebAssembly二进制的人类可读格式。JavaScript引擎(无论是在浏览器还是Node.js中),在加载WebAssembly文件时,可以将二进制文件转换为WebAssembly文本格式。这有助于理解代码内容并进行调试。文本编辑器可以以WebAssembly文本格式显示二进制文件,这比其二进制对应物更易于阅读。

基本的WASM二进制格式如下:

00 61 73 6d 01 00 00 00

这段内容翻译成中文如下:

 00 61 73 6d 01 00 00 00
\0  a  s  m  1  0  0  0 (ascii value of the character)
|         |  |
---------  version
    |
Magic Header

这个基本模块有一个魔术头(\0asm),后跟WebAssembly的版本(01)。

文本格式采用S表达式格式编写。S表达式语法中的每个指令/表达式都应该在一对括号()内。S表达式通常用于定义嵌套列表或结构化树。许多关于基于树的数据结构的研究论文都使用这种表示法来展示他们的代码。S表达式从XML中去除了所有不必要的繁文缛节,提供了一种简洁的格式。

注意

这种表达式(在括号内定义一切)看起来熟悉吗?你有没有使用过LISP(或受LISP启发构建的语言)?

模块是WASM中的基本构建块。基本WASM的文本表示如下:

(module ) 

WASM由一个头部和零个或多个部分组成。头部以魔术头和WASM版本开始。在头部之后,WASM可能包含以下零个或多个部分:

  • 类型
  • 函数
  • 表
  • 内存
  • 全局变量
  • 元素
  • 数据
  • 起始函数
  • 导出
  • 导入

WASM中所有这些部分都是可选的。WASM的结构如下所示:

 module ::= {
    types vec<funcType>,
    funcs vec<func>,
    tables vec<table>,
    mems vec<mem>,
    globals vec<global>,
    elem vec<elem>,
    data vec<data>,
    start start,
    imports vec<import>,
    exports vec<export>
 }  

WASM内的每个部分都是一个向量(数组),包含零个或多个相应类型的值,除了start。我们将在书中后面探索start部分。现在,start保存一个索引,它引用funcs部分中的一个函数。

WASM中的每个部分都采用以下格式:

<section id><u32 section size><Actual content of the section> 

第一个字节指的是唯一的部分ID。每个部分都有一个唯一的部分ID。在唯一的部分ID旁边是一个无符号32位(u32)整数,定义了部分的大小(以字节为单位)。其余字节是部分内容。

注意

由于部分大小由u32整数定义,因此部分的最大大小限制为大约4.2GB的内存(即2^32 - 1)。

在WebAssembly文本格式中,我们使用部分的名称来表示部分中的每个段落。

例如,函数部分包含一系列函数。WebAssembly文本格式中的一个示例函数定义如下:

 (func <name>? <func_type> <local>* <inst>* )

与其他表达式一样,我们定义的所有内容都在括号()内。首先,我们用func关键字定义函数块。在func关键字之后,我们添加函数的名称。这里的函数名称是可选的,因为在二进制中,函数由函数部分内的函数块索引标识。

名称后面是func_type。func_type在规范中被称为type_use。这里的type_use指的是类型定义。func_type保存所有输入参数(及其类型)和函数的返回类型。因此,对于一个接受两个输入操作数并返回结果的add函数,func_type将如下所示:

(param $lhs i32) (param $rhs i32) (result i32) 

注意

类型可以是i32、i64、f32或f64(32位和64位整数或浮点数)。未来,当WebAssembly支持更多类型时,类型信息可能会发生变化。

param关键字表示定义的表达式持有一个参数。$lhs是变量名。注意,在WebAssembly文本格式中定义的所有变量都会以$为前缀。在此之后,我们有参数的类型,i32。同样,我们为第二个操作数$rhs定义了另一个表达式。最后,返回类型被标记为(result i32)。result关键字表示表达式是返回类型,后跟类型i32。

在func_type之后,我们定义函数内部将使用的任何局部变量。最后,我们有一个指令/操作列表。

让我们根据前面的代码片段定义一个add函数:

 (func $add (param $lhs i32) (param $rhs i32) (result i32)
    get_local $lhs
    get_local $rhs
    i32.add)  

整个块都包裹在括号内。函数块从func关键字开始。然后,我们有一个可选的函数名称($add)。WebAssembly二进制模块将使用函数部分内的函数索引来识别函数,而不是名称。然后,我们定义操作数和返回类型。

注意

在二进制格式中,通过type部分定义参数和结果,因为这有助于优化生成的函数。但在文本格式中,为了简洁和易于理解,类型信息将在每个函数定义中显示。

然后,我们有一个指令列表。第一个指令get_local获取(来自堆的)$lhs的局部值。然后,我们获取$rhs的局部值。之后,我们使用i32.add指令将它们相加。最后,闭合括号结束了一切。

没有单独的return语句/表达式。那么,函数如何知道返回什么呢?

正如我们之前所见,WebAssembly是一个堆栈机。当调用一个函数时,它为该函数创建一个空堆栈。然后,函数使用这个堆栈来推送和弹出数据。因此,当执行get_local指令时,它会将值推送到堆栈中。在两次get_local调用之后,堆栈将有$lhs和$rhs。最后,i32.add会从堆栈中弹出两个值,执行add操作,并推送元素。当函数结束时,堆栈顶部的元素将被取出并提供给函数调用者。

如果我们想要将这个函数导出到外部世界,那么我们可以添加一个export块:

 (export <export_name> (func <function_reference>))

export块在()内定义。export块以export关键字开始。export关键字后跟函数的名称。在名称之后,我们引用函数。函数块由后面的func关键字组成。然后,我们有function_reference,它指的是模块内定义/导入的函数的名称。

为了导出add函数,我们定义如下:

 (export "add" (func $add)) 

"add"指的是函数在模块外部导出的名称,后跟(func $add),指的是函数。

函数和export部分都应该包裹在module部分内,以使其成为有效的WASM:

(module
    (func $add (param $lhs i32) (param $rhs i32) 
      (result i32)
        get_local $lhs
        get_local $rhs
        i32.add)
    (export "add" (func $add))
)  

这幅插图展示了WebAssembly代码的树形结构。在这个结构中,“module"作为根部,从中延伸出两个主要分支:“function"和"export”。在"function"分支下,有标有"param”、"result"和"local"的子分支。而在"export"分支下,则展示了一个标有"func reference"的子分支。这些分支相互连接,形成一个有机的整体,代表了WebAssembly文本格式的复杂结构。
在这里插入图片描述

在WebAssembly文本格式中构建函数

为此,我们将使用递归的斐波那契数列生成器。我们将编写的斐波那契函数将具有以下格式:

 # Sample code in C for reference
int fib(n) {
    if (n <= 1)
        return 1;
    else
        return fib(n-1)+ fib(n-2);
}  

首先,让我们使用WebAssembly文本格式定义给定fib函数的函数签名。类似于其C语言对应物,fib函数接受一个数字参数并返回一个数字。因此,函数定义在WebAssembly文本格式中遵循相同的签名:

 (func $fib (param $n i32) (result i32)
    ...
) 

我们在括号()内定义函数。函数以func关键字开始。在关键字之后,我们添加函数名称$fib。然后,我们为函数添加参数;在我们的案例中,函数只有一个参数n;我们将其定义为(param $n i32)。然后,函数返回一个数字,(result i32)。

WebAssembly没有内存来处理临时变量。为了拥有局部值,我们应该将值推入堆栈,然后检索它。因此,为了检查n<=1,我们必须首先创建一个局部变量并将1存储在其中,然后进行检查。要定义局部变量,我们使用local块。local块以local关键字开始。这个关键字后跟变量的名称。在变量名称之后,我们定义变量的类型:

 (local <name> <type>)

让我们创建一个名为$tmp的local变量:

 (local $tmp i32) 

注意

(local $tmp i32)不是指令。它是函数声明的一部分。记住,前面的函数语法包括local。

然后我们必须将$tmp的值设置为1。为了设置值,我们首先必须将值1推入堆栈,之后我们必须从堆栈中弹出该值并将其设置为$tmp:

i32.const 1
set_local $tmp  

i32.const创建一个i32常量值并将其推入堆栈。所以,这里我们创建一个值为1的常量并将其推入堆栈。

然后,我们使用set_local设置$tmp中的值。set_local从堆栈顶部取出值,在我们的案例中是1,并将$tmp的值设置为1。

现在,我们必须检查给定的参数是否小于2。WebAssembly提供i32.<some_action>来对i32执行某些操作。例如,要添加两个数字,我们使用了i32.add。类似地,要检查它是否小于特定值,我们有i32.lt_s。_s表示我们正在检查有符号数字。

i32.lt_s需要两个操作数。对于第一个操作数(即$n),我们使用get_local表达式从$n中提取值并将其放在堆栈顶部。然后,我们使用i32.const 2创建一个2的常量并将2添加到堆栈。最后,我们使用i32.lt_s比较$n值和2:

get_local $n
i32.const 2
i32.lt_s 

但我们如何定义if条件?WebAssembly提供br_if和block。

在WebAssembly文本格式中,使用block关键字定义块,并跟随一个名称以标识该块。我们使用end结束块。块的格式如下:

block $block
... ; some code goes in here.
end 

我们将这个块提供给br_if。br_if在条件成功时调用该块:

get_local $n
i32.const 2
i32.lt_s
br_if $block ; calls the $block` only when the condition
  succeeds. 

到目前为止,WebAssembly文本格式将如下所示:

 (module
  (func $fib (param $n i32) (result i32) (local $tmp i32)
    i32.const 1
    set_local $tmp
    ; block
    block $block
      ; if condition
      get_local $n
      i32.const 2
      i32.lt_s
      br_if $block
    ... ; some code
    end
    ; return value
    get_local $tmp
  )
)  

一切都包裹在module内。在$block结束时,值将存储在$tmp中。我们使用get_local $tmp获取$tmp的值。唯一剩下要做的事情是创建循环。

循环时间

首先,我们将$tmp设置为1:

i32.const 1
set_local $tmp  

然后,我们将创建一个循环。在WebAssembly文本格式中,使用loop关键字来创建循环:

loop $loop
end  

loop关键字后跟循环的名称。循环以end关键字结束。loop是一个特殊的块,将一直运行,直到我们使用某些条件表达式(如br_if)退出:

get_local $n
i32.const -2
i32.add
call $fib
get_local $tmp
i32.add
set_local $tmp
get_local $n
i32.const -1
i32.add
tee_local $n
i32.const 1
i32.gt_s
br_if $loop 

我们获取$n并向其添加-2,然后调用fib函数。要调用函数,我们使用call关键字,后跟函数的名称。这里,call $fib返回值并将该值推入堆栈。

现在,使用get_local $tmp获取$tmp。这会将$tmp推入堆栈。然后,我们使用i32.add从堆栈中弹出两个值并将它们相加。最后,我们使用set_local $tmp设置$tmp。set_local $tmp从堆栈顶部取出值并将其赋给$tmp。我们获取$n并向其添加-1。

这里我们使用tee_local,因为tee_local类似于set_local,但它不是将值推入堆栈,而是返回值。最后,我们循环运行,直到$n大于1。如果它小于1,我们使用br_if $loop跳出循环。完整的WebAssembly文本格式将如下所示:

(module
  (func (export $fib (param $n i32) (result i32) 
    (local $tmp i32)
    i32.const 1
    set_local $tmp
    ; block
    block $block
      ; if condition
      get_local $n
      i32.const 2
      i32.lt_s
      br_if $block
      ; loop
      loop $loop
        get_local $n
        i32.const -2
        i32.add
        call $fib
        get_local $tmp
        i32.add
        set_local $tmp
        get_local $n
        i32.const -1
        i32.add
        tee_local $n
        i32.const 1
        i32.gt_s
        br_if $loop
      end
    end
    ; return value
    get_local $tmp
  )
)

在未来的章节中,我们将看到如何将这种WebAssembly文本格式转换为WASM并执行它。

如果您有兴趣了解更多关于S表达式的信息,请查看https://en.wikipedia.org/wiki/S-expression。

要了解更多关于WebAssembly文本格式设计的信息,请查看规范https://github.com/WebAssembly/design/blob/master/Semantics.md。

在https://webassembly.github.io/spec/core/text/instructions.html查看更多文本指令。

参考各种指令及其操作码https://webassembly.github.io/spec/core/binary/instructions.html。

了解更多关于二进制编码的信息https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md。

总结

在本章中,我们了解了WebAssembly在JavaScript引擎内部的执行方式,并探索了WebAssembly文本格式是什么以及如何使用WebAssembly文本格式定义WASM。在下一章中,我们将探索WebAssembly二进制工具包。

WebAssembly技术进阶之路(官方文档翻译) WebAssembly技术 ——从C/C++到Javascript之路 案例描述 随着对无插件预览性能要求的越来越高,原来的Emscripten asm.js技术已显不足,但目前一种新技术——WebAssembly正日趋成熟,WebAssembly可以将低级别编程语言(包括C和C++)编译成二进制字节码,可以较大的提升浏览器的性能。 案例分析和解决 WebAssembly作为一种新兴的Web... 阅读详情

相关推荐

WebAssembly 用在了哪里?18个激动人心的 Wasm 初创公司

WebAssembly 用在了哪里?18个激动人心的 Wasm 初创公司 本文作者:Renee Shah,Amplify Partner 原文链接:https://reneeshah.medium.com/how-webassembly-gets-used-the-18-most-exciting-startups-building-with-wasm-939474e951db 本文的翻译与传播已获得原作者 Renee 的授权。 每当我聊起我对 WebAssembly(简称 “Wasm”)感兴趣时,大

weixin_42376823的博客 4614

WebAssembly 基本了解

现代浏览器朝着第二操作系统一路狂奔,网页在线 PS、3D 地图、音视频编解码、游戏引擎等等应用,都在浏览器实现了,这都是基于 WebAssembly。WebAssem应不应该卷起来?

wade3po的博客 7358

WebAssembly相关技术介绍

本文将介绍Wasm的背景、工具栈、研发示例、工程应用以及未来发展。

leyang0910的博客 2152

什么是WebAssembly(Wasm)?

文章目录WebAssembly是什么?WebAssembly和JavaScript WebAssembly是什么? WASM是什么?带你了解WebAssembly的前世今生 参考URL: http://www.mabiji.com/webassembly/wasm.html WebAssembly是什么?WebAssembly即WASM, WebAssembly是一种新的编码格式并且可以在浏览器中运行,WASM可以与JavaScript并存,WASM更类似一种低级的汇编语言。 WebAssembly(又名w

西京刀客 4万+

c++实现异步线程池并详细分析线程池析构流程

多线程编程是提高程序性能和响应能力的关键技术之一,异步线程池作为多线程编程的一种有效实现方式,能够管理和复用线程资源,避免频繁创建和销毁线程带来的开销。在本文中,我们将深入探讨如何实现一个异步线程池。

2301_76564925的博客 1598

【AI深究】合成数据(Synthetic Data)深度解析:原理、算法与工程实践——全网最详细流程|核心原理、主流方法、数学表达、工程实践与细节、未来趋势|GAN、VAE、语言模型LLM合成如GPT

大家好,我是爱酱。本篇延续将会系统梳理合成数据(Synthetic Data)的核心原理、主流方法、数学表达、工程实践与未来趋势,结合数学公式,帮助你全面理解这一AI建模的关键技术。 注:本文章含大量数学算式、详细例子说明及大量代码演示,大量干货,建议先收藏再慢慢观看理解。新频道发展不易,你们的每个赞、收藏跟转发都是我继续分享的动力!

AI人工智能爱酱~你的AI学习好帮手~ 4913

印地语(hi)翻译指南解析:MCP Python SDK 多语言文档的语体、术语与排版规范

本文系统解析 MCP Python SDK 官方仓库 `i18n/hi/instructions.md` 中为印地语(Hindi, हिन्दी)翻译所制定的完整语言规范。这份指南不是一般意义上的"翻译要求",而是驱动整个多语言文档流水线的人工编写输入之一:它定义了天城体(Devanagari)印地语翻译必须遵循的敬称语体、句式结构、标点排版和术语策略,并配合同目录下的 [glossary.jso

gitblog_00635的博客 835

一种基于OpenPose和DNN的跌倒检测软件系统(中文&英文)

学习并实现一种跌倒检测模型,此模型基于OpenPose实现逐帧人体姿态检测,使用DNN识别人体动作。检测方式有在线与离线两种,本文主要测试了离线模式,测试效果较好。

Tongzhou_Li的博客 2643

Python 在 WebAssembly(WASM)中的探索

WebAssembly 是一种低级的、高效的虚拟机字节码格式,最初由 W3C 推出,旨在解决传统 JavaScript 在高性能计算任务上的局限性。通过将高级语言编译成 WASM 格式,开发者可以实现跨平台、跨语言的代码执行,而无需担心底层硬件差异。目前,主流浏览器如 Chrome、Firefox 和 Edge 都已经全面支持 WASM。随着 WebAssembly 技术的发展,越来越多的编程语言开始探索与其结合的可能性。

2501_91305464的博客 1644

Qt绘图库对决:QWT与QCustomPlot的实战选型指南

本文为Qt开发者提供了QWT与QCustomPlot两大绘图库的实战选型指南。文章从功能特性、性能资源、开发效率三大维度进行深度对比,并结合工业监控、科学计算、嵌入式设备等典型场景,给出了清晰的决策清单。对于需要专业科学图表(如极坐标、等高线图)的场景推荐QWT;对于追求高性能、实时性、快速开发及嵌入式部署的通用图表需求,QCustomPlot是更优选择。

alpha的博客 241

数字IC时序约束实战:深入解析clock_uncertainty的设置策略与后端影响

本文深入探讨数字IC设计中clock_uncertainty的设置策略及其对后端实现的影响。通过分析时钟不确定度的组成(包括clock_skew、clock_jitter和margin),并结合实际项目经验,详细介绍了在不同设计阶段(综合、布局布线、签核)的动态调整方法。文章还提供了工程化处理参数来源、跨时钟域特殊处理以及优化时序收敛的实用技巧,帮助工程师提升数字IC设计的可靠性和性能。

weixin_29284657的博客 227

探索WebAssembly的强大工具:wasm-util

探索WebAssembly的强大工具:wasm-util 项目介绍 wasm-util 是一个专为 TypeScript 和 JavaScript 开发者设计的 WebAssembly(WASM)工具库。它提供了丰富的功能,帮助开发者更轻松地构建和操作 WebAssembly 模块。无论你是初学者还是经验丰富的开发者,wasm-util 都能让你在处理 WebAssembly 时更加得心应手。 项...

gitblog_00407的博客 816

Cursor设置界面汉化保姆级教程:手把手教你修改JS文件实现中文界面(附避坑指南)

本文提供Cursor编辑器设置界面汉化的详细教程,从定位JS文件到安全修改实现中文界面,包含必备工具清单、文件路径指引和常见问题解决方案。通过手把手教学帮助用户轻松完成汉化,提升使用体验,特别适合不熟悉英文界面的开发者。

weixin_29007809的博客 1412

WebAssembly:wasm探索与TypeScript模块wasm应用

安装编译环境,Emscripten/bind实践,TypeScript模块WASM引用.

zouzouzou的博客 2767

UG\NX二次开发 获取对象的引用集

获取对象的引用集,一个对象可能有多个引用集,下面这个封装函数可以获取对象的所有引用集。

王牌飞行员_里海的博客 489

SAP Retail 补货里的 Requirement Groups,站点和商品太多时,主数据维护如何做减法

SAP Retail补货主数据设计中,Requirement Groups(需求组)是常被低估但至关重要的分类机制。它通过将具有相同补货需求的接收方(如门店)按商品分类(Merchandise Category)分组,大幅降低主数据维护量。在大型零售场景中(如800家门店、6万商品),直接维护每个门店和商品的组合参数会导致维护量失控。Requirement Groups允许企业按品类特性(如乳制品、饮料等)为不同门店组设置统一补货参数,并随业务变化灵活调整。该机制与商品分类紧密绑定,不同于MRP Group

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 67

探索未来计算的边界:Wasm3——超速的WebAssembly运行时

探索未来计算的边界:Wasm3——超速的WebAssembly运行时 wasm3???? A fast WebAssembly interpreter and the most universal WASM runtime项目地址:https://gitcode.com/gh_mirrors/wa/wasm3 WebAssembly(简称WASM)以其高性能和安全性在编程世界中迅速崭露头角。而作为这一...

gitblog_00095的博客 1508

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

N_m3u8DL-RE 流媒体下载器:从测试流到批量下载一次跑通

N_m3u8DL-RE 是一款跨平台流媒体下载器,把 MPD、m3u8、ISM 清单地址转成本地能直接播放的文件,点播和直播录制都覆盖。下面从判断它适不适合你开始,讲到装好、验证、五个常见场景实战,再到参数、排障和批量脚本,读完照着敲就能出片。 ## 先判断:这个流媒体下载器适不适合你? 先说结论:只要你手里是一个 MPD、m3u8 或 ISM 清单地址,它就能接手——解析轨道、多线程下载分片

gitblog_01170的博客 1036

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Python 社区对 WebAssembly(WASM)的探索:Python 会进入浏览器吗?

WebAssembly 是一种低级二进制格式,旨在为网页提供接近原生性能的计算能力。它最初由 Mozilla、Google、Microsoft 和 Apple 等多家公司联合开发,目前已成为 W3C 标准的一部分。与传统的 JavaScript 不同,WASM 提供了更高效的执行速度和更低的内存开销,尤其适合处理复杂的计算任务。尽管 WASM 最初设计用于浏览器环境,但它也逐渐被引入到其他领域,如边缘计算、物联网设备以及服务器端运行时。这种灵活性使得 WASM 成为连接不同平台的理想桥梁。

2501_91226552的博客 1635

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

探索WebAssembly的无限可能:Awesome Wasm项目推荐

在现代Web开发的世界中,WebAssembly(简称Wasm)已经成为一个革命性的技术。它允许开发者使用C、C++、Rust等语言编写的代码在浏览器中运行,极大地扩展了Web应用的功能和性能。**Awesome Wasm**项目是一个精心策划的资源集合,旨在为开发者提供关于WebAssembly生态系统的全面指南。无论你是WebAssembly的新手还是经验丰富的开发者,这个项目都能为你提供丰富...

gitblog_00073的博客 787

探索WebAssembly的Go语言门径 —— go-wasm项目推荐

探索WebAssembly的Go语言门径 —— go-wasm项目推荐 在这个前端技术日新月异的时代,WebAssembly(简称WASM)无疑为我们打开了全新的可能性。作为一种可以在现代浏览器中运行的低级虚拟机格式,它让C/C++等语言编写的代码得以在网页上高效执行。而今天,我们有幸向您介绍一款针对Go开发者特别友好的开源工具——go-wasm。 项目介绍 go-wasm 是一个用Go语言实现的...

gitblog_00208的博客 966

WASM Go Web "框架":探索Go与WebAssembly的无限可能

WASM Go Web "框架":探索Go与WebAssembly的无限可能 项目介绍 WASM Go Web "框架"是一个实验性项目,旨在探索如何将Go语言编译为WebAssembly(WASM)并在浏览器中直接操作DOM。尽管该项目目前还缺少许多框架应有的功能,但它为我们提供了一个独特的视角,展示了Go与WebAssembly结合的潜力。项目由Bria...

gitblog_00982的博客 1122

推荐文章:探索Elixir与WebAssembly的桥梁 - elixir-wasm

推荐文章:探索Elixir与WebAssembly的桥梁 - elixir-wasm 项目介绍 在WebAssembly日益成为跨平台运行高效代码的关键技术背景下,elixir-wasm应运而生。作为一个专注于编码WebAssembly的Elixir库,它打开了从函数式编程语言到现代浏览器和高性能计算环境的大门。尽管它的目标并非将Elixir直接编译成WebAssembly,而是通过一套精巧的元...

gitblog_00301的博客 665
上一篇: 第 6 章:并发系统编程与C++
下一篇: Rust循环和函数
段舸
博客等级 码龄3年 533粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值