asm.js:面向未来的开发

WebAssembly编译之(1)-asm.js及WebAssembly原理介绍(wasm) asm.js及WebAssembly原理介绍 阅读详情

这是一个可深可浅的话题,会先简单介绍一下什么是asm.js,看看它长什么样子,再来聊聊asm.js为什么能带来高性能,会有一些简单的对比,然后再从工程的角度讲讲兼容性,如何打包使用等等。水平有限,肯定讲不透,就当是抛装引玉吧。

What’s asm.js

还记得前段时间的“围棋杀手”AlphaGo吧,设想一下,如果两台AlphaGo相遇,会擦出些什么火花?同样的算法,在同样的机器上跑,会是什么样的结果?两只“阿尔法狗”我是抓不到了,倒是可以看看微软写的两个AI棋手对战DEMO:Asm.js Chess Battle。

游戏说明:

On this page, we match two chess engines against one another. They are identical in nearly every detail, including source code! The only difference is that one has a flag set to be interpreted as asm.js, a specialized and strict JavaScript subset that allows JavaScript engines to employ specialized compilation to dramatically speed up execution.
Each turn is limited to 200ms – because the asm.js-optimized engine has a significant performance advantage, it can evaluate more moves per turn and has a substantially higher likelihood of victory. You can adjust the turn length and other variables in the demo to see how they affect the outcome of the game.

在这个页面中,我们设置两个象棋引擎进行对战。 这两个引擎在各个细节上几乎一样,包括源代码! 唯一的区别是,其中一个引擎设置了标志,让浏览器按照asm.js规范(一个特定、严格、允许JavaScript引擎使用专门的编译来显着加快执行的JavaScript子集)来解释。
每回合“思考”时间为0.2s - 因为源码被浏览器解析为asm.js的象棋引擎具有显着的性能优势,所以它在每回合可以进行更多评估,因此具有更高的获胜可能性。

微软-asm.js演示

正所谓天下武功,唯快不破。运行得更快,在每一回合评估的可能越多,越容易取胜。

值得注意的是:仅在对asm.js规范做了优化的浏览器上运行才能看到上面的结果,如果你是Safari,那么抱歉,遵循asm.js规范的代码说不定会更慢。关于兼容性下面马上会提到。

主角登场

由上面那个象棋对战的演示可以看到,即使在web上,我们仍有许多场景(例如web游戏等)对运行性能有着极高的要求。对于这种极高的要求,这里介绍一种解法:asm.js

asm.js不是一门新的语言,而是JavaScript的一个子集。由Mozilla于2013年提出,主要为了提升JS引擎执行代码的速度。通俗来说,同样是js代码,符合asm.js规范的代码对JS引擎更加友好,JS引擎在解释执行这些代码更加省心(例如不用进行变量类型推断了),也就更加快。

asm.js介绍

an extraordinarily optimizable, low-level subset of JavaScript
一个极度可优化的,面向底层的JavaScript子集。

如果上面的描述你还看得一头雾水的话,说不定你在下面官方的常见问题中能找到一些答案。

如果你想深入了解asm.js的规范或者说草案标准,推荐看官方草案。

asm.js、js、C++

下面我们来看一下同一个算法(参考网上),三种不同的“语言”(其实只有C++和js)实现。

① C++

// For x = 1 to infinity: 
// if x not divisible by any member of an initially empty list of primes, 
// add x to the list until we have 25,000
// 
// x从1递增到无穷,如果x不能整除list里的所有数,
// 那么将x添加到list,直到list中有25,000个数
#include <stdio.h>

class Primes {
 public:
  int getPrimeCount() const { return prime_count; }
  int getPrime(int i) const { return primes[i]; }
  void addPrime(int i) { primes[prime_count++] = i; }

  bool isDivisibe(int i, int by) { return (i % by) == 0; }

  bool isPrimeDivisible(int candidate) {
    for (int i = 1; i < prime_count; ++i) {
      if (isDivisibe(candidate, primes[i])) return true;
    }
    return false;
  }

 private:
  volatile int prime_count;
  volatile int primes[25000];
};

int main() {
  Primes p;
  int c = 1;
  while (p.getPrimeCount() < 25000) {
    if (!p.isPrimeDivisible(c)) {
      p.addPrime(c);
    }
    c++;
  }
  printf("%d\n", p.getPrime(p.getPrimeCount()-1));
}

② js

// For x = 1 to infinity: 
// if x not divisible by any member of an initially empty list of primes, 
// add x to the list until we have 25,000
// 
// x从1递增到无穷,如果x不能整除list里的所有数,
// 那么将x添加到list,直到list中有25,000个数

// 开始打点
// console.log("start");
var startTime = new Date();

function Primes() {
  this.prime_count = 0;
  this.primes = new Array(25000);
  this.getPrimeCount = function() { return this.prime_count; }
  this.getPrime = function(i) { return this.primes[i]; }
  this.addPrime = function(i) {
    this.primes[this.prime_count++] = i;
  }

  this.isPrimeDivisible = function(candidate) {
    for (var i = 1; i <= this.prime_count; ++i) {
      if ((candidate % this.primes[i]) == 0) return true;
    }
    return false;
  }
};

function main() {
  p = new Primes();
  var c = 1;
  while (p.getPrimeCount() < 25000) {
    if (!p.isPrimeDivisible(c)) {
      p.addPrime(c);
    }
    c++;
  }
  console.log(p.getPrime(p.getPrimeCount()-1));
}

main();

 // 结束打点
 // console.log("end");
 console.log("raw_js.js: ",(new Date() - startTime)/1000,"s");

③ asm.js规范(对,你没看错,下面就是js代码)

function _main() {
 var $0 = 0, $1 = 0, $10 = 0, $11 = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, $c = 0, $p = 0, $vararg_buffer = 0, label = 0, sp = 0;
 sp = STACKTOP;
 STACKTOP = STACKTOP + 100016|0; if ((STACKTOP|0) >= (STACK_MAX|0)) abort();
 $vararg_buffer = sp;
 $p = sp + 8|0;
 $0 = 0;
 $c = 1;
 while(1) {
  $1 = (__ZNK6Primes13getPrimeCountEv($p)|0);
  $2 = ($1|0)<(25000);
  if (!($2)) {
   break;
  }
  $3 = $c;
  $4 = (__ZN6Primes16isPrimeDivisibleEi($p,$3)|0);
  if (!($4)) {
   $5 = $c;
   __ZN6Primes8addPrimeEi($p,$5);
  }
  $6 = $c;
  $7 = (($6) + 1)|0;
  $c = $7;
 }
 $8 = (__ZNK6Primes13getPrimeCountEv($p)|0);
 $9 = (($8) - 1)|0;
 $10 = (__ZNK6Primes8getPrimeEi($p,$9)|0);
 HEAP32[$vararg_buffer>>2] = $10;

 // 结束打点
 // console.log("end");
 console.log("asm.js: ",(new Date() - startTime)/1000, "s");

 (_printf(672,$vararg_buffer)|0);
 $11 = $0;
 STACKTOP = sp;return ($11|0);
}
function __ZNK6Primes13getPrimeCountEv($this) {
 $this = $this|0;
 var $0 = 0, $1 = 0, $2 = 0, label = 0, sp = 0;
 sp = STACKTOP;
 STACKTOP = STACKTOP + 16|0; if ((STACKTOP|0) >= (STACK_MAX|0)) abort();
 $0 = $this;
 $1 = $0;
 $2 = HEAP32[$1>>2]|0;
 STACKTOP = sp;return ($2|0);
}
function __ZN6Primes16isPrimeDivisibleEi($this,$candidate) {
 $this = $this|0;
 $candidate = $candidate|0;
 var $$expand_i1_val = 0, $$expand_i1_val2 = 0, $$pre_trunc = 0, $0 = 0, $1 = 0, $10 = 0, $11 = 0, $12 = 0, $13 = 0, $14 = 0, $15 = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0, $8 = 0, $9 = 0, $i = 0;
 var label = 0, sp = 0;
 sp = STACKTOP;
 STACKTOP = STACKTOP + 16|0; if ((STACKTOP|0) >= (STACK_MAX|0)) abort();
 $0 = sp + 12|0;
 $1 = $this;
 $2 = $candidate;
 $3 = $1;
 $i = 1;
 while(1) {
  $4 = $i;
  $5 = HEAP32[$3>>2]|0;
  $6 = ($4|0)<($5|0);
  if (!($6)) {
   label = 6;
   break;
  }
  $7 = $2;
  $8 = $i;
  $9 = ((($3)) + 4|0);
  $10 = (($9) + ($8<<2)|0);
  $11 = HEAP32[$10>>2]|0;
  $12 = (__ZN6Primes10isDivisibeEii($3,$7,$11)|0);
  if ($12) {
   label = 4;
   break;
  }
  $13 = $i;
  $14 = (($13) + 1)|0;
  $i = $14;
 }
 if ((label|0) == 4) {
  $$expand_i1_val = 1;
  HEAP8[$0>>0] = $$expand_i1_val;
  $$pre_trunc = HEAP8[$0>>0]|0;
  $15 = $$pre_trunc&1;
  STACKTOP = sp;return ($15|0);
 }
 else if ((label|0) == 6) {
  $$expand_i1_val2 = 0;
  HEAP8[$0>>0] = $$expand_i1_val2;
  $$pre_trunc = HEAP8[$0>>0]|0;
  $15 = $$pre_trunc&1;
  STACKTOP = sp;return ($15|0);
 }
 return (0)|0;
}
function __ZN6Primes8addPrimeEi($this,$i) {
 $this = $this|0;
 $i = $i|0;
 var $0 = 0, $1 = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, $7 = 0, label = 0, sp = 0;
 sp = STACKTOP;
 STACKTOP = STACKTOP + 16|0; if ((STACKTOP|0) >= (STACK_MAX|0)) abort();
 $0 = $this;
 $1 = $i;
 $2 = $0;
 $3 = $1;
 $4 = HEAP32[$2>>2]|0;
 $5 = (($4) + 1)|0;
 HEAP32[$2>>2] = $5;
 $6 = ((($2)) + 4|0);
 $7 = (($6) + ($4<<2)|0);
 HEAP32[$7>>2] = $3;
 STACKTOP = sp;return;
}
function __ZNK6Primes8getPrimeEi($this,$i) {
 $this = $this|0;
 $i = $i|0;
 var $0 = 0, $1 = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, label = 0, sp = 0;
 sp = STACKTOP;
 STACKTOP = STACKTOP + 16|0; if ((STACKTOP|0) >= (STACK_MAX|0)) abort();
 $0 = $this;
 $1 = $i;
 $2 = $0;
 $3 = $1;
 $4 = ((($2)) + 4|0);
 $5 = (($4) + ($3<<2)|0);
 $6 = HEAP32[$5>>2]|0;
 STACKTOP = sp;return ($6|0);
}
function __ZN6Primes10isDivisibeEii($this,$i,$by) {
 $this = $this|0;
 $i = $i|0;
 $by = $by|0;
 var $0 = 0, $1 = 0, $2 = 0, $3 = 0, $4 = 0, $5 = 0, $6 = 0, label = 0, sp = 0;
 sp = STACKTOP;
 STACKTOP = STACKTOP + 16|0; if ((STACKTOP|0) >= (STACK_MAX|0)) abort();
 $0 = $this;
 $1 = $i;
 $2 = $by;
 $3 = $1;
 $4 = $2;
 $5 = (($3|0) % ($4|0))&-1;
 $6 = ($5|0)==(0);
 STACKTOP = sp;return ($6|0);
}

说实话,一开始看到上面asm.js的代码,也是懵的,这和以前上课学汇编好像呀,然后各种位运算,各种汇编运算,高位低位全部涌入脑海。

先告诉大家一个好消息压压惊,asm.js虽然是js的一个子集,但asm.js设计是面向js执行引擎的,而不是面向普通开发者的,也就是说,这货不是给我们手写,这货不是给我们手写,这货不是给我们手写……看看下面吧。

生成asm.js代码

既然手写是不太现实的,那代码是怎么生成的?又怎么实际用在项目里呢?下面给大家推荐一个生成asm.js代码的工具Emscripten。

Emscripten的作者之一kripken也是asm.js规范的草案起稿者之一。

emscripten

Emscripten是一个基于LLVM(Low Level Virtual Machine,编译器框架系统)的项目,它能将C和C++编译成浏览器高度可优化的asm.js代码。这使得我们能够在web环境中以接近原生的速度运行C和C++,且不需要额外的浏览器插件。

简单来说,Emscripten能将C和C++代码编译成asm.js代码,得益于asm.js本身的可优化程度比较高及浏览器相应的优化,使得编译出来的asm.js代码在web中能以接近原生的速度运行。至于为什么是C和C++,为什么不直接对手写的JavaScript代码进行优化?这个问题我们后面再探索,下面先简单过一遍Emscripten的使用。

教程来自官方:

  1. 下载和安装
  2. 起步
  3. 优化选项

相信大家看完上面三个文档基本已经了解Emscripten的使用,至于Emscripten背后的原理,你可以理解为它就是一个编译器(感兴趣的可以了解一下,以前作业写过Pascal to C++的简单编译器,有些没弄懂的地方,但是相当有趣),将C、C++代码编译经过编译过程(分词,语法分析,语义分析,中间代码生成,代码优化,目标代码生成)编译成符合asm.js规范的JavaScript代码,并且生成的JavaScript能直接用于node和web环境。

性能

基于上面的算法,我们来对比一下上面三种写法的执行时间,再来聊聊为什么。

首先我将raw_c.cpp文件按照Emscripten的不同编译选项进行编译,编译命令如下:

    .././emcc raw_c.cpp -o asm.js
    .././emcc -O1 raw_c.cpp -o asm_O1.js
    .././emcc -O2 raw_c.cpp -o asm_O2.js
    .././emcc -O3 raw_c.cpp -o asm_O3.js
    .././emcc -Oz raw_c.cpp -o asm_Oz.js

对比

① node环境:

通过time命令得到代码执行的时间,结果(仅做了3,4次重复实验,结果不算绝对严谨,但能说明问题)如下。

asm.js性能对比

性能对比

性能对比

asm性能对比

② 浏览器环境(Chrome vs Safari):

下面只对比了raw.js和asm.js(不带优化选项的默认结果)。

asm性能对比

值得注意的是,我们在Safari中发现,经过优化的代码反而比原生的js代码还慢,这里就涉及到“兼容性”问题了,而这个兼容性特指运行速度的兼容性,因为asm.js规范只是JavaScript的一个子集,所以asm.js能在任何版本的浏览器中运行,但不是在任何浏览器上都跑得这么快。

为了让大家更好地理解兼容性这个问题,我们先探讨一下,为什么遵循asm.js规范的代码要比手写的js代码运行快?

为什么快

这大概是本文最核心的部分,也是没有信心说透的地方,暂且当做阶段性的学习总结。

实际上,由于JavaScript运行环境特性不一(除了node外还有各式各样的浏览器等),某一特性的表现与两方面有关,一是规范,二是实现。

可以这样理解,制定规范的“大哥们”说,

“来来来,兄弟们,今天我们来商量一件事,是这样的,昨晚我的Windows电脑坏了,手上的Mac又打不了《英雄联盟》 ,我想要是能在Web里打《英雄联盟》那多好,这样就不管什么Windows呀,Mac呀,Ubuntu…打开浏览器马上开撸,爽不爽?然后我昨晚就试着在web上写起了游戏来,结果一运行,我的天,这帧率怎么补刀,超神也别想了。于是苦闷得我整晚睡不着开始思考人生,首要问题还是,js在web上怎么运行这么慢呀?”

果然大哥就是大哥,熬了一晚之后的今天,大哥豁然开朗,

“我一想,王侯将相宁有种乎,凭啥C++写起游戏来这么快,我大JavaScript就玩不溜?于是ASM.js规范诞生了。兄弟们呀,你们按照这个规范做,保准跟着大哥在浏览器里面打撸把把超神呀!”

小弟们做着超神美梦纷纷点头支持,但人多想法也多嘛,有些小弟想,

“既然大哥都想好了,就按照asm.js这个规范做吧。”。

而有一些小弟比较有想法,

“其实大哥才不在意asm.js呢,大哥只是想在浏览器里面打撸而已嘛,我参考大哥的思路来提高JavaScript的运行速度就好啦。”

总之想法很多,反正经过努力,大家都愉快地在各家的浏览器打起了《英雄联盟》,而当初说的asm.js规范更像是一些建议,而不一定是最后的实现。“管他的,反正超神就好了……”

哈哈,大家看完理解了就行,里面说到的大哥小弟只是开个玩笑,没有半点调侃的意思,实际上规范的制定者和规范的实现者都是推动web前进的中流砥柱,我十分敬佩,而且制定者和实现者往往都是那么几个大神……

正经版概述:几个大神提出了asm.js规范,遵循该规范的代码性能更好,并且更容易被浏览器优化,从而性能更上一层楼。至于浏览器怎么优化,那就是各家的事情了。下面将从asm.js规范本身及主流浏览器的实现分别讲讲,为什么快?

规范or理论

从asm.js规范入手,快主要得益于以下几方面:

  • 数据类型确定 (使用位运算等限制数据类型)
  • “use asm”指示浏览器跳过数据类型等验证
  • 合法的asm.js代码能进行AOT提前编译处理(其中能实现复杂的性能优化)
  • 没有垃圾回收机制,内存的分配和回收时机都是手动确定的

补充:
AOT编译:在运行前预编译(对比JIT:在运行中编译)

实现上

1,FireFox与Microsoft Edge
遵循asm.js规范,能进行AOT处理。

2,Chrome
不支持AOT,但是对asm.js规范进行了优化。参考Chrome官方博客.

3,Safari
尚未对asm.js进行优化,根据官方消息:

There is no “use asm” mode in JavaScriptCore. Instead WebKit integrates ASM.js optimizations directly in the optimizer. As a result, it is possible to mix ASM-style typing with regular code and still get great performance and power efficiency.

JavaScriptCore(Safari使用的JavaScript引擎)中不支持“use asm”模式。然而,Webkit直接将asm.js的优化集成到优化器中,将来,有可能将asm.js代码与常规代码结合起来,以达到更好的性能同时更加节约能耗。

工程相关

兼容性

上面也说了,因为asm.js是JavaScript的一个子集,也就是asm.js能正确运行在支持JavaScript的浏览器上,所以这里探讨的兼容性问题是“所有浏览器能不能高速运行asm.js代码?”而不是“所有各个浏览器能不能正确运行asm.js代码?”

asm.js浏览器兼容性

Safari全系不支持对asm.js的优化。由之前的测试结果得出asm.js规范的代码在Safari上运行甚至有可能比原生js代码慢许多,Safari的缺席无疑在一定程度上扑灭了开发者的热情,这不得不令人想起Google强推的Service Worker同样在Safari中还没得到实现。

然而作为开发者对于技术的未来我们应该始终保持乐观,始终相信技术会朝着好的方向发展。现在可以看到的是由苹果公司主导的webkit项目对asm.js的优化支持已经处于开发阶段了。

webkit: asm.js is in development

打包

在工程上,除了兼容性之外,我们往往还会考虑引入asm.js除了带来高性能福利外,会不会有其他副作用。这里的副作用就是体积。
我们前面对将raw_c.cpp按照不同的编译选项编译成不同的asm_0*.js,包体积如下:

asm代码体积

注意:asm_Oz.js.mem文件的由来:
默认情况下,Emscripten将静态内存初始化代码打包到js文件里面,这会导致包体积过大。将这部分代码分离到以.mem结尾的二进制文件可以解决这个问题,asm_Oz.js执行的时候,会异步加载asm_Oz.js.mem,加载完成后再执行主函数。

可见,经过压缩优化后的asm_Oz.js大约有180k的额外负担,可以在服务器启动gzip压缩将负担降至最少,这部分主要是起始的代码,后面包体积只会随业务代码体积增大而增大,和以前一致。

总的来说,包体积带来的负担在产品环境还是能接受的,而且,一旦你的项目都要启用asm.js这种优化技术了,相信100k对你来说根本不是瓶颈。

C++与JS交互

由于博客已经写得过长了,这里就只给出官方文档,然后大致过一遍我认为不错的开发配置。

C++与JavaScript的交互

最最简单的使用是将js执行时间较长的代码用C++的方法实现一遍,可以在C++中暴露成为一个个方法,或者定义成为一个类,里面包含了一系列方法。至于怎么在JavaScript中调用C++编译后的asm.js代码中暴露出来的方法或类方法,相信上面的文档已经说得足够清楚了。

注意,在写C++代码的时候,除了可以使用一些标准库之外,不能使用任何DOM,BOM之类的API。

想象

不得不说,asm.js是给我无限想象的一个规范。

JavaScript之所以深得大家喜爱,是因为它能运行在所有浏览器上,而web形态是目前连接性,传递性最强的形态。而JavaScript能做什么也一定程度上决定了我们在web上能做什么。那么如果现在我们利用Emscripten能将其他语言编译成可高性能执行的JavaScript,会发生什么?例如,将C++编译器编译成asm运行在浏览器上,那么任何的C++程序是不是就能实时地在浏览器中编译运行?

任何东西都将有可能运行在web。

题外话:JavaScript与我都是95年来到这个世界的,21年来,JavaScript与我都在跌跌撞撞中成长起来了,然而作为一个青少年,未来依然是未知的,但我仍然保持一贯的乐观。

else

JavaScript的诞生和死亡

关于Asm.js的一些基本介绍和它的实现 Asm介绍asm是mozilla提出的一套基于JS的语法标准,由 Mozilla 的 Emscripten项目催生而来,主要为了解决js执行效率问题,尤其是通过Emscripten转换过来的js代码效率。那什么是Emscripten和asm,关于它的诞生,最主要的原因就是js执行效率低下。(目前asm已经由几家公司进行标准化,形成了WebAssembly,关于WebAssembly的内容,可以去看下 阅读详情

相关推荐

js 播放amr音频文件

js 播放amr音频文件,将amr文件转化成base64字符串,用js转换成音频播放

asm.js为什么快?小程序能否使用asm.js?

目录asm.js为什么快asm.js如何和外部js代码交互wasm & asm.js兼容性参考 本文探究 asm.js 为什么比普通js快,是否可以用在小程序上。 asm.js为什么快 asm的变量都是静态类型 并且只有两种类型: 32位有符号整数 int32 64位浮点数 float64 这两种类型都是占据固定长度内存,因此,可以将asm直接静态编译到字节码 var a =...

madlaxnoir的博客 2940

2018南京大学计算机夏令营机试

1. Count number of binary strings without consecutive 1’s Given a positive integer n(3≤n≤90), count all possible distinct binary strings of length n such that there are no consecutive 1's . Examples...

climber16的博客 1万+

asm.js简介

1.什么是asm.js 2.asm.js的原理 3.几个例子 4.可能的应用场景 5.参考来源和更多信息 1.什么是asm.js asm.js是由Mozilla提出的一个基于JS的语法标准,主要是为了解决JS引擎的执行效率问题,尤其是使用Emscripten从C/C++语言编译成JS的程序的效率,目前只有Mozilla的Firefox Nightly中支持。chro

jdk137的专栏 1987

人工智能(AI)简史:推动新时代的科技力量

人工智能(AI,Artificial Intelligence)是计算机科学的一个分支,旨在研究和开发可以模拟、扩展或增强人类智能的系统。它涉及多种技术和方法,包括机器学习、深度学习、自然语言处理(NLP)、计算机视觉、专家系统等。

qq_17153885的博客 1万+

Unified Access Control:从NAS到RRC的5G接入控制全流程解析

本文深入解析了5G统一接入控制(Unified Access Control)的全流程,从NAS到RRC的协同工作机制。通过身份核验、业务分类和动态决策三个核心步骤,UAC实现了智能调度和弹性决策,确保海量设备接入时的网络稳定性。文章详细介绍了USIM卡的身份凭证体系、NAS层的业务分类引擎以及RRC层的动态决策机制,并提供了实战案例和常见问题排查方法。

weixin_30855099的博客 588

为什么现如今asm.js鲜有耳闻?

WebAssembly(Wasm) 现在已经被广泛使用,并且在现代 Web 开发中占据了重要地位。它被设计为一种高效的字节码格式,能够在浏览器中接近原生性能地运行,适用于需要高性能计算的应用场景。自推出以来,WebAssembly 已逐渐超越 asm.js,成为 Web 上高性能计算的首选技术之一。

qq_55018264的博客 1014

【电路设计】带阻滤波器实战:从理论到Twin-T陷波电路实现

本文详细介绍了带阻滤波器的原理与Twin-T陷波电路的实战应用,从基础概念到工程实现全面解析。通过具体案例展示如何设计高Q值滤波器,解决电源噪声等实际问题,并分享PCB布局和元件选型的实用技巧,助力工程师提升电路设计能力。

gg901的博客 1011

Asm.js: Javascript的编译目标

正如许多开发者一样,我也为Asm.js的前景而感到兴奋不已。最近的新闻——Asm.js正 在被Firefox支持——引起了我的兴趣。同样感兴趣的还有Mozilla和Epic声明(mirror)他们已经为Asm.js而支持Unreal Engine 3——并且运行十分良好。 获得一个C++游戏引擎运行Javascript,并使用WebGL来渲染,这是一个重大的突破,这个突破很大程度上归功于Mo

renfengmei技术博客 1256

2025机械考研复试面试问题汇总篇(含13门科目),考研机械复试专业面试常见重点问题总结!考研机械复试专业面试准备看这一篇就够了!

(完整版内容:)1.汇集了本科各科的重点知识及多个机械名校800多个常见问题,共8.7万字185页,涵盖机械所以专业课的重点知识和常见问答。 2.涉及机械大类重点科目,包括:材料力学、控制工程、数控技术、机械制造技术基础、理论力学、液压传动、机械设计、机械原理、工程材料、互换性与技术测量、测试技术、汽车理论、程序设计与C语言等13门必修课。

weixin_56510835的博客 1861

Allegro如何用自带的功能将线段变成铜皮操作指导

在做PCB设计的时候,有时根据设计需要将线段变成铜皮,可以借助辅助工具来实现这一操作,但是Allegro自身也自带这个功能,如下图。勾选Delete original objects。如何用自带的功能将线段变成铜皮操作指导。勾选Convert to shape,需要把这段走线变成铜皮。

weixin_54787054的博客 2946

asm.js:高效JavaScript子集,开启Web性能新纪元

**许可证**:Apache 2.0

gitblog_00145的博客 788

库存管理系统项目部署方案(基于jdk17)

不需要安装到服务器,运维本地安装就行,主要是用来编译前端代码的。构建完成后将dist文件夹复制到服务器内。

程序员诚哥 6361

asmcrypto.js:高性能WebCrypto API的Asm.js实现完全指南

asmcrypto.js是一个专注于性能优化的JavaScript加密库,通过Asm.js技术实现了WebCrypto API的核心功能,为Web应用提供高效的密码学操作支持。无论是数据加密、哈希计算还是安全密钥生成,asmcrypto.js都能在浏览器环境中实现接近原生的执行效率,是前端安全开发的理想选择。 ## 🚀 核心功能与技术优势 ### 🔑 全面的加密算法支持 asmcrypto

gitblog_00013的博客 981

【YOLOv11】006、YOLOv11数据增强策略:Mosaic、MixUp等增强技术原理解析

摘要:YOLOv11在产线缺陷检测中遇到小尺寸瑕疵漏检问题,暴露了训练数据过于"干净"的缺陷。数据增强的核心是提升模型泛化能力,而非简单扩充数据。Mosaic增强通过多图拼接迫使模型处理多尺度目标,需注意边界框裁剪细节;MixUp通过线性插值使决策边界更平滑,但需避免类别冲突。自适应增强策略应随训练进度动态调整强度。实际应用中,需针对小目标、类别不平衡等场景调整增强参数,并确保验证与推理流程一致。数据增强应针对性解决具体问题,而非盲目尝试组合。

企鹅码农的专属播客,分享10多年的实战案例和经验解读,包含YOLO、RT-DETR、AI等各个工作领域。 365

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Asm.js- Javascript的编译目标

正如许多开发者一样,我也为Asm.js的前景而感到兴奋不已。最近的新闻——Asm.js正 在被Firefox支持——引起了我的兴趣。同样感兴趣的还有Mozilla和Epic声明(mirror)他们已经为Asm.js而支持Unreal  Engine 3——并且运行十分良好。 获得一个C++游戏引擎运行Javascript,并使用WebGL来渲染,这是一个重大的突破,这个突破很大程度上归功于Mozi...

qq_42483213的博客 385

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

SIMD.js与asm.js是什么?

它们共同的目标是:解决 JavaScript 在浏览器中执行计算密集型任务时性能不足的问题,让 Web 能够承载游戏、科学计算、多媒体处理等重型应用。在 asm.js 出现之前,人们认为用 JavaScript 写 3D 游戏、视频编码、CAD 软件等是天方夜谭。因为 JS 是动态类型、解释执行的语言,性能与 C/C++ 等编译型语言相差甚远。asm.js 的核心思想是: 通过一套严格的编写规则,让 JavaScript 代码的类型和行为在编译时(AOT) 就能被完全确定。这样 JS 引擎(如 Firefo

2301_82133855的博客 885

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

从Rust到远方:ASM.js星系

来源: https://mnt.io/2018/08/28/from-rust-to-beyond-the-asm-js-galaxy/这篇博客文章是这一系列解释如何将R...

Rust语言学习交流 647

asm.js与WebAssembly对比:为什么这个JavaScript子集至今仍不可替代?[特殊字符]

在前端性能优化的道路上,**asm.js验证器**一直扮演着关键角色。作为Mozilla Research推出的JavaScript严格子集,asm.js通过类型注释和静态验证为JavaScript带来了接近原生代码的性能表现。尽管WebAssembly(Wasm)已经成为现代Web应用的主流选择,但asm.js验证器仍然在某些场景中展现着不可替代的价值。 ## 📊 什么是asm.js验证器?

gitblog_02916的博客 544

asm.js 和 Emscripten 入门教程

作者:阮一峰 日期:2017年9月 7日 Web 技术突飞猛进,但是有一个领域一直无法突破 ---- 游戏。 游戏的性能要求非常高,一些大型游戏连 PC 跑起来都很吃力,更不要提在浏览器的沙盒模型里跑了!但是,尽管很困难,许多开发者始终没放弃,希望让浏览器运行 3D 游戏。 2012年,Mozilla 的工程师Alon Zakai在研究 LLVM 编译器时突发奇想:许多 3D 游戏都是用 C / C++ 语言写的,如果能将 C / C++ 语言编译成 JavaScript 代码,它们不就...

键盘的起始页 789

编写asm.js代码

asm.js代码的结构 这是一个简单的示例。 //(1)asm.js関数宣言 function asm(stdin, foreign, heap){//引数は最大3つ "use asm";//(2)use asm宣言 //(3)インポート宣言 var imul = stdin.Math.imul; var fround = stdin.Math.fround; var cal...

u014749668的博客 1129

asm.js验证器核心原理:10分钟理解JavaScript静态类型检查机制

想要让你的JavaScript代码运行速度提升数倍吗?asm.js验证器正是实现这一目标的关键工具!作为Mozilla Research推出的高性能JavaScript子集验证工具,asm.js验证器通过严格的静态类型检查机制,确保你的代码能够被JavaScript引擎进行极致优化。本文将用10分钟时间,带你深入理解asm.js验证器的核心工作原理,掌握JavaScript静态类型检查的奥秘。

gitblog_02560的博客 448

五分钟了解asm.js和WebAssembly

Asm.js是什么? 相信很多读者都或多或少地听说过Asm.js这个名词,但它究竟是什么意思呢? 先看一眼官方的定义: an extraordinarily optimizable, low-level subset of JavaScript 极度优化的、底层的javascript子集。 可以看到主要的三个关键词。 1、极度优化。asm.js是一种提升js执行效率的解决方案。 asm.js能带来非常高的效率提升。甚至能让浏览器运行3d游戏。 2、底层的。 底层到什么程度呢?就相当于

lengye7的博客 1713

asm.js 和 WebAssembly 有什么区别?

asm.js是具有“高度可优化”指令的 JS 子集。基本上你可以声明类型 (int, float) 和 js 引擎(在浏览器和 node.js 中)将更快地执行指令。如果您的应用程序与 WebGL 一起使用,它会进行大量计算或图形处理,这将带来好处。 web程序集是JS的二进制格式,所有的JS,不仅仅是asm.js。它不是字节码,而是解析器计算的 AST 的二进制编码。它有两大好处: JS引擎可以跳过解析步骤 它比 JS 原始源代码紧凑得多 我们已经可以为非 JS 的浏览器编写代码:EMSCri...

allway2的博客 1076

HTML5标准与性能之四:asm.js

之前的几篇文章分别介绍了WebWorkers、Typed Array和ParallelArray,最后,我们再来介绍一下与性能相关的标准:asm.js。 asm.js asm.js是由Mozilla提出的一个基于JS的语法标准,主要是为了解决JS引擎的执行效率问题,尤其是使用Emscripten从C/C++语言编译成JS的程序的效率,目前只有Mozilla的Firefox Night...

badao19931216的博客 187
上一篇: 前端开发中Cookie那些事儿
下一篇: 前端工程:apis接口封装实践
Sheldon_Law
博客等级 码龄11年 44粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值