试试将.NET7编译为WASM并在Docker上运行
之前有听到说Docker支持Wasmtime了,刚好.NET7也支持WASM,就带大家来了解一下这个东西,顺便试试它怎么样。
因为WASM(WebAssembly) 一开始是一个给浏览器的技术,比起JS解释执行,WASM能用于提升浏览器的用户体验,因为在一些场景中它有着比JS更好的性能。
大家可以将WASM理解为C#的MSIL或者Java的字节码,它并不是二进制代码,还是会由JIT编译执行,JIT有很多优化,另外大多数场景也只会JIT一次,加上省略了JS加载,语法分析各种的过程,才会有着比JS更好的性能。
另外因为WASM是中间码的格式,所以理论上任何语言C#、RUST、Java、Go都可以将代码编译为WASM,然后放到浏览器中执行。比如C#火热的Blazor项目,就是将C#编译为WASM,然后使C#代码能在浏览器中运行。
另外聊一聊WASI(WebAssembly System Interface),我们知道WASM有着不错的可移植性和安全性(目前浏览器运行都是沙箱运行,对于权限管控很严格),那么就有一群大佬就说,我们是不是能脱离浏览器单独运行WASM程序呢?于是就产生了一个标准的系统接口,大家都按照这样的方式来生成WASM,调用系统API,然后我们开发一个Runtime,让大家的WASM程序都能在这上面运行。
举个不严谨的例子说明一下WASI就是比如:
- C# => MSIL => CLR(Mono、CoreCLR)
- Java => 字节码 => JVM(HotSpot VM、ZingVM)
而现在我们可以: - C# => WASM => WASI(wasmtime、wasmedge)。
各位应该就明白了,WASI其实就是个运行时的规范,大家编译成WASM放上去就能跑。
所以现在对于它的观点就是,觉得它在Server后端领域目前来说不是一个很价值的东西,因为可移植性好的语言比比皆是,比如C#、Java、Go等等。
拿性能来说,对于这样的中间语言性能无关就是JIT和GC,WASI的JIT和GC能做的像C#、Java这样的JIT、GC性能那么好吗?这个目前来说是存在疑问的,至少在短时间内很难追平其它平台十多年的优化。
再说WASM的另一个优点,就是体积小和启动快,现在C#支持NativeAOT、Java有GraalVM、Go和Rust之类的本身就是编译型语言,启动速度和体积都很不错,WASM在这个方面其实不占优势。
.NET编译为WASM
好了,言归正传,我们来试试.NET7上面的WASM。.NET7目前已经发布,我们需要使用最新的版本,如下图所示:
然后我们创建一个简单的控制台项目,用于输出斐波那契数列和执行耗时,代码如下所示 (这并不性能最优的实现,只是这样子实现简单):
using System.Diagnostics;
namespace PublishDotNetToWASM;
public static class Program
{
public static void Main()
{
// warm
ulong sum = 0;
foreach (var i in Fibonacci().Take(1000))
{
sum += i;
}
// run
sum = 0;
var sw = Stopwatch.StartNew();
foreach (var i in Fibonacci().Take(100000))
{
sum += i;
}
sw.Stop();
Console.WriteLine($"Result:{sum}, Timespan:{sw.ElapsedTicks} Ticks");
}
private static IEnumerable<ulong> Fibonacci()
{
ulong current = 1, next = 1;
while (true)
{
yield return current;
next = current + (current = next);
}
}
}
接下来为了将.NET程序发布成WASM,我们需要安装Wasi.Sdk
预览包,这个预览包是Steve Sanderson
大佬做的支持,可以将.NET程序编译为WASM,截止至目前版本信息如下所示:
<PackageReference Include="Wasi.Sdk" Version="0.1.2-preview.10061" />
运行dotnet publish -c Release
命令,将我们的应用程序发布为WASM格式,在发布过程中,需要下载MinGW
作为编译器,网络环境不好的同学,需要使用proxy,稍微等待一会就顺利的发布成功了:
运行WASM程序
此时我们可以安装一下Wasmtime
来执行我们的程序,通过https://wasmtime.dev/
下载安装:
然后就可以直接使用wasmtime
命令运行我们的程序,我分别使用wasmtime
和dotnet
运行了我们的程序:
可见目前来说WASM的性能还是惨不忍睹的,等一等后续的优化吧。
将.NET发布到Docker WASI
再来看看我们的Docker,对于Docker支持WASI我感到并不意外,因为Docker的容器化对于直接执行的WASM来说还是比较重,支持它是一个拓宽影响力的好事。具体的执行模型如下所示,对于WASM应用有着不同的执行方式。不再使用runc
而是wasmedge
。
wasmedge
也是一个实现了WASI标准的WASM运行时,和上文提到的wasmtime一样。
要实现在Docker上运行WASM程序需要安装Docker的预览版,链接https://docs.docker.com/desktop/wasm/
。
然后我们整一个Dockerfile,我们直接依赖scratch镜像即可,因为它不需要其它的基础镜像(暂时我没有使用.NET7的多段构建镜像,听大佬说目前貌似有问题)。
FROM scratch
COPY ./bin/Release/net7.0/PublishDotNetToWASM.wasm /PublishDotNetToWASM.wasm
ENTRYPOINT [ "PublishDotNetToWASM.wasm" ]
再使用下面的命令构建Docker镜像,由于是wasm镜像,所以需要带额外的参数。
docker buildx build --platform wasi/wasm32 -t publishdotnettowasm .
可以看到打包出来的镜像是非常小的,只有3.68MB。
运行的话也很简单,用下方的命令即可,需要指定runtime为io.containerd.wasmedge.v1
,另外也需要指定paltform。
docker run --rm --name=publishdotnettowasm --runtime=io.containerd.wasmedge.v1 --platform=wasi/wasm32 publishdotnettowasm
我把dotnet原生运行、wasmtime运行、docker WASI运行都跑了一下,可以发现目前来说性能是惨不忍睹。
总结
以上就是如何将.NET7程序发布到WASM,然后在Docker最新的WASI中运行的样例,目前来看基本的运行都已经OK,不过正如前面提到的,现在性能还是太受影响了。
这不仅仅是在.NET平台上,其它语言Rust、C、C++编译为WASM上都有明显的性能下降。
思来想去可能在一些插件化和不需要性能很好的场景WASI会比较用。不过这些都需要时间慢慢见证,毕竟存在即合理,像JS这样的语言不一样好好的?
我们可以拭目以待,看看WASM/WASI会不会给我们带来其它惊喜,期待后续Steve Sanderson大佬和WASM社区的相关优化。
源码链接
https://github.com/InCerryGit/PublishDotNetToWASM
参考文献
https://www.docker.com/blog/docker-wasm-technical-preview/
https://www.zhihu.com/question/304577684/answer/1961085507
https://arghya.xyz/articles/webassembly-wasm-wasi/
https://laurentkempe.com/2022/10/31/experimenting-with-dotnet-7-wasm-and-wasi-on-docker/
试试将.NET7编译为WASM并在Docker上运行的更多相关文章
- VS2015在win10上编译的程序不能在Win7上运行的原因
研究了下,搞懂原理了.是VS 2015 编译的问题,因为我是Win 10 ,所以会用到win 10 的SDK ,这个SDK 依赖了Universal C Runtime ,就是API-MS-CRT-X ...
- framework中编译anroid工程并在模拟器上运行
1.在eclipse下创建android工程Hello并拷贝到“源码目录/packages/experimental”下面 2.在Hello工程目录下面创建Android.mk文件,内容如下: L ...
- FixFFmpeg 修改官方编译的ffmpeg能在 XP 上运行的工具
把 fixff.cmd 和 FixFFmpeg.exe 拷贝到 ffmpeg 所在的目录 运行 fixff.cmd 自动修复; fixffmpeg-20160924.7z
- 使用Apache TVM将机器学习编译为WASM和WebGPU
使用Apache TVM将机器学习编译为WASM和WebGPU TLDR 在Apache TVM深度学习编译器中引入了对WASM和WebGPU的支持.实验表明,在将模型部署到Web时,TVM的WebG ...
- WebAssembly,可以作为任何编程语言的编译目标,使应用程序可以运行在浏览器或其它代理中——浏览器里运行其他语言的程序?
Mozilla.谷歌.微软和苹果已经决定开发一种面向Web的二进制格式.该格式名为WebAssembly,可以作为任何编程语言的编译目标,使应用程序可以运行在浏览器或其它代理中. 几年前,我们在Inf ...
- 在kubernetes上运行WASM负载
在kubernetes上运行WASM负载 WASM一般用在前端业务中,但目前有扩展到后端服务的趋势.本文使用Krustlet 将WASM服务部署到kubernetes. 简介 Krustlet 是一个 ...
- Spark源码编译并在YARN上运行WordCount实例
在学习一门新语言时,想必我们都是"Hello World"程序开始,类似地,分布式计算框架的一个典型实例就是WordCount程序,接触过Hadoop的人肯定都知道用MapRedu ...
- 编译可在Nexus5上运行的CyanogenMod13.0 ROM(基于Android6.0)
编译可在Nexus5上运行的CyanogenMod13.0 ROM (基于Android6.0) 作者:寻禹@阿里聚安全 前言 下文中无特殊说明时CM代表CyanogenMod的缩写. 下文中说的“设 ...
- 编译可在Android上运行的qemu user mode
前言 本文在Ubuntu 64位系统上对qemu项目进行交叉编译,并且只编译与qemu user mode有关的代码. 下文中的”NDK”若无特殊说明均指”Android NDK”. 下文中”$NDK ...
随机推荐
- 3-14 Python处理XML文件
xml文件处理 什么是xml文件? xml即可扩展标记语言,它可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. 从结构上,很像HTML超文本标记语言.但他们被设计的目的 ...
- 可别小看了XSS漏洞
可别小看了XSS漏洞 对于初了解xss漏洞的人来说,XSS漏洞的危害就是获取受害者的cookie,来进行 'cookie劫持'. 今天就总结一下XSS漏洞的危害性,望安全人员不要轻视,开发人员 ...
- Docker 入门指南
Docker 入门指南 目录 基础概念 安装教程 基本操作 常用安装 构建操作 容器编排 壹.基础概念 什么是Docker? Docker是基于Go开发的应用容器引擎,属于 Linux 容器的一种封装 ...
- LFS(Linux From Scratch)构建过程全记录(四):最后的准备
写在前面 本章将进行一系列的环境配置 目录创建 在LFS中创建文件目录 我们可以用以下的指令来创建一些基础的目录,并进行连接 mkdir -pv $LFS/{etc,var} $LFS/usr/{bi ...
- 【HMS Core】集成地图服务不显示地图问题
[问题描述] 关于华为HMS-地图服务不显示地图的问题. 背景:集成华为地图服务运行后页面不显示地图,运行app后不展示地图报错MapsInitializer is not initialized. ...
- 《Java Web程序设计——开发环境搭建》
Java Web程序设计--开发环境搭建 一.JDK下载.安装以及环境变量的配置: 官网:https://www.oracle.com/java/technologies/download ...
- 通俗易懂理解 MySQL B+树、数据存储、索引等知识
文章转载自:https://mp.weixin.qq.com/s?__biz=MzI1MDgwNzQ1MQ==&mid=2247485630&idx=1&sn=681c9c0d ...
- MySQL 自增字段取值
1 前言 本文来自回答思否网友的一个问题,这个网友新建了一张表,auto_increment_increment设为10,AUTO_INCREMENT主键起始值设为9, 当他插入数据的时候,发现主键值 ...
- Winsw将jar包部署为windows服务
1. 下载Winsw https://github.com/winsw/winsw/releases 下载winsw官网上的xml文件和.exe文件 2. 编辑配置文件 创建一个文件夹demo,将所需 ...
- 代码随想录第二天| 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
2022/09/22 第二天 第一题 这题我就直接平方后排序了,很无脑但很快乐啊(官方题解是双指针 第二题 滑动窗口的问题,本来我也是直接暴力求解发现在leetCode上超时,看了官方题解,也是第一次 ...