知乎问题之:.NET AOT编译后能替代C++吗?
标题上的Native库是指:Native分为静态库(
作者:nscript
链接:https://www.zhihu.com/question/536903224/answer/2522626086
(1)开发 NDK 库有人进行尝试:NativeAOT-AndroidHelloJniLib (https://github.com/josephmoresena/NativeAOT-AndroidHelloJniLib) 通过修改 .Net Runtime 来生成 Android 下的 NDK Native 库。希望后续官方能直接支持。
(2)Remobjects Elements (https://www.remobjects.com/elements/) 收费工具。可以采用 C# 语言开发 NDK Native 库,限制是不能自由使用 Core CLR,而是使用 Remobjects 的平台相关库 island 和跨平台库 RTL,RTL 库和 Core CLR 的相关类型接口相似。
Remobjects Elements 也可以用 C# 开发 wasm 模块,试用了下,满小巧的,gzip 下可以做到低于 1M,性能测试大约是 .net 6 的1/4-1/5。同上面一样,库这块会受到限制。
Remobjects Elements 的思路蛮有意思的,可以用 C#[或 Oxygene(Object Pascal), Swift, Java, Go or Mercury (VB)] 来写各种库或应用程序。Swift 语言的免费,其他的收费。可以用这些语言写native 程序、 .net 程序、 jvm 程序 ……
----
补充一下,这是个很值得探讨的问题,我一直在尝试用 csharp 代替 cpp。很多地方可以直接替代掉,但也遇到了一些问题:
(1)写底层算法或库的话,而调用者各种语言都有,csharp的,vb的,java 的,delphi 的都碰到过。那时的工作流程是,csharp 写算法,验证之后,再根据对方需求,改成 cpp。有 AOT 之后,这种情况可以避免掉。
(2)移动开发:安卓开发底层的库,参考资料太少。比如,开发个 sdk,给 java 调用,xamarin 资料太少,解决方案也不通用。
AOT 工具链完善后,对我来说,可以解决很多问题:
(1)写底层库:可以完全放心大胆的用 csharp 写底层库了,jit 模式下快速开发,aot 模式发布。csharp 的生产力比 cpp 高太多,构建系统也比 cmake 好使的多。我现在正在尝试优化 csharp 脚本开发 aot dll 的开发流程,目前还没完全完成,但也挺舒服的,以一个最简单的例子来说明,
lib.csx:
using System.Runtime.InteropServices;
[UnmanagedCallersOnly(EntryPoint = "add")]
public static int Add(int a, int b)
{
return a + b;
}
[DllImport("pack/out/lib.dll")]
private static extern int add(int a, int b);
int result = add(2,4);
Console.WriteLine(result);
一行命令就编译成 dll 了,win10下是964 k。
nscript pack --aot --lib lib.csx
再用下面指令调用脚本:
nscript .\lib.csx
输出:
6
这种开发模式可比写 cpp 舒服太多了。目前 aot 工具链还不够完善,但是开发起来难度不大,就是工作量的问题。比如,根据代码,直接生成各个语言的调用封装,生成文档 ......
这样一来,就可以用 csharp 快速开发出底层库,生成动态链接库、静态链接库给桌面用,给服务器用,给移动设备用。底层库一般不牵扯到ui,其通用性极强。做 android 的 ndk 开发太折腾,cpp 开发,jni 调用,调试麻烦得很。
这也可以解决 csharp 这块防止反编译的问题,发布时也可以 UI 层用 jit 跑,底层用 aot 跑来保护代码。
(2)开发小工具
我造过一个轮子,把 avalonia 的控件库的核心给拆出来,用 direct2d 来绘制,弄了一些基本的控件,写简单的桌面程序,aot 之后尺寸可以控制在 4M,如果写一些小工具还是可以的。
再比如说,如果想发布一些 server 端小工具,以 http 方式提供服务,jit 模式下,用 asp.net 来做,单个文件发布压缩之后可以做到20-30M, 用 EmbedIO 来写的话,单个文件发布,win下11M,linux 下 13M。EmbedIO用了反射,aot 我没配好,没跑出来,根据经验的话,aot 应该可以做到 2-4 M。不过,11M 也够用了,来看看用脚本写的代码:
#r "nuget: EmbedIO, 3.4.3"
using EmbedIO;
using EmbedIO.WebApi;
using EmbedIO.Actions;
using EmbedIO.Files;
WebServer CreateWebServer(string url)
{
var server = new WebServer(o => o
.WithUrlPrefix(url)
.WithMode(HttpListenerMode.EmbedIO))
.WithLocalSessionManager()
.WithStaticFolder("/static/", "./webroot", true, m => m.WithContentCaching(true)) // Add static files after other modules to avoid conflicts
.WithModule(new ActionModule("/api", HttpVerbs.Get, HandleApi))
.WithModule(new ActionModule("/", HttpVerbs.Any, ctx => ctx.SendDataAsync(new { Message = "Hello!" })))
;
return server;
}
Task HandleApi(IHttpContext ctx)
{
return ctx.SendDataAsync("api");
}
//@main
var url = "http://*:5000/";
var server = CreateWebServer(url);
server.RunAsync();
Console.ReadKey();
所以,工具链完善后,用 csharp 写东西很爽的:
(1)写完之后,AOT一下,给各个语言用 <--> 对标 cpp;
(2)写完之后,打包个几M 的小东西,扔服务器跑 <--> 是不是很像 golang?
(3)不建项目,像我上面那样用脚本写 <--> python;
(4)正常使用 <--> java;
(5)上 blazor <--> js。
除此之外,还有很新东西可以玩的 ......
----
一些场景替代不了:
(1)带 gc 的 .net aot,最小尺寸差不多1M,对于有的场景这个尺寸过大。比如说,对于插件系统,每个插件1M,100个就100M,过大,并且全部加载的话,有100个gc在跑,浪费。不知有没技术让100个插件共享一个 gc。虽然可以不开gc,但这样,就只是个大号的C了。
(2)对实时性要求高的场景,因为有gc存在会受到限制。
其他场景可以当有 gc 的 cpp 用,应该可以达到 cpp 80%+的性能。
其实现在jit,aot以及源生cpp性能都差不了太多,我做过密集计算的测试,细节忘记了,只记得是个 float 密集计算,java 的性能大于csharp和cpp。后来分析,jvm 做了向量化并行处理,csharp和cpp没有做。改csharp代码手动用simd,最后性能略高于Java。
aot的除了启动快,还有其他好处:(1)代码很难反编译;(2)尺寸小。
假设你要写个东西,给java调用或python调用,用 jit 的话,得几十M,aot 的话,可以做到 1M。这样的话,很多用cpp写的sdk,可以用csharp来写,aot编译成动态链接库,提供给上层用。
而不开gc的话,你可以就当他是个C语言的方言。
Windows以lib后缀名,Linux以a后缀 名)和动态库(Windows以dll为后缀名,Linux以so后缀名。 本文顺序先从生成Native程序.然后是动态库,最后是静态库。
知乎问题之:.NET AOT编译后能替代C++吗?的更多相关文章
- JIT和AOT编译详解
JIT和AOT编译介绍 JIT - Just-In-Time 实时编译,即时编译 通常所说的JIT的优势是Profile-Based Optimization,也就是边跑边优化 ...
- Java编译后产生class文件的命名规则
今天刚好有同学问了下Java编译后产生的.class文件名的问题,虽然一直都在使用Java做开发,但是之前对编译后产生的.class文件名的规范也基本没做了解过,也真的是忏愧啊!今天无论如何都要总结下 ...
- Idea中包内中的置文件如何发布到编译后的目录中去
1.问题引入: 运行一个maven+springmvc+hibernate的项目的时候出现了下边的错误: Caused by: java.io.FileNotFoundException: class ...
- 查看eclipse web项目中jsp编译后的servlet源文件【转】【JSP】
eclipse中,jsp编译后 servlet源文件的位置为: F:\workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wor ...
- Intellij如何设置编译后自动重新加载class文件?
前段时间突然发现Intellij不能自动重新加载类了,每次编译后都要重新启动项目,才能显示更新效果,后来网上查询Intellij下如何配置热部署,都说是要配置构件,然后在web容器的编辑页面选择upd ...
- Android APP使用NDK编译后的ffmpeg库出现undefined reference to 'posix_memalign'错误
在android程序中使用NDK编译后的ffmpeg库的时候出现了如下错误: jni/libs/libavutil.a(mem.o): in function av_malloc:libavutil/ ...
- java编译后字节码解析
java编译后字节码解析 参考网摘: https://my.oschina.net/indestiny/blog/194260
- VS 设置编译后的程序可以以管理员身份运行
1.首先,创建一个文件命名为 XXX.exe.manifest, 并将以下内容复制到文件 <?xml version="1.0" encoding="UTF-8&q ...
- c#:Reflector+Reflexil 修改编译后的dll/exe文件
不知道大家有没有这样的经历:现场实施时测试出一个bug,明明知道某个dll/exe文件只要修改一二行代码即可,但手头没有开发环境,紧急情况下,可以用reflector + reflexil 临时直接修 ...
随机推荐
- 【Nginx】Windows平台下配置Nginx服务实现负载均衡
前言:废话不多说了,直接上步骤. 系统环境:win10 测试用的开发环境和服务类型:VS2022 + DotNet 6 + WebApi 1.本地先创建一个webapi项目,用于测试使用. 2.新建一 ...
- ssm框架layui分页下标中文乱码,或者请选择中文乱码,提示乱码等
开始我以为是layui的bug 后来发现不是 用过的方法: 1.修改layui的js文件 将其中的中文变为encdoe 代码 比如laypage.js下的中文 2.添加web.xml的过滤器 该代码 ...
- VisionPro · C# · 实时取像
VisionPro 在C#项目程序中实现实时取像方式,有两种: 1.采用界面控件 CogAcqFifoTool 进行操作,与在VisionPro软件中操作一致: 2.采用界面控件 CogRecord ...
- 【python基础】第08回 流程控制 for循环
本章内容概要 1.循环结构之 for 循环 本章内容详解 1.循环结构之for循环 1.1 语法结构 for 变量名 in 可迭代对象: #字符串 列表 字典 元组 for 循环的循环体代码 针对变量 ...
- 基于Svelte3.x桌面端UI组件库Svelte UI
Svelte-UI,一套基于svelte.js开发的桌面pc端ui组件库 最近一直忙于写svelte-ui,一套svelte3开发的桌面端ui组件库.在设计及功能上借鉴了element-ui组件库.所 ...
- 漫谈客户端存储技术之Cookie篇
Cookie 说到Cookie,不管作为前端开发人员还是后端开发人员并不陌生,作为一种最古老.最稳定的客户端存储形式,即便是在当下各种新的客户端存储技术层出不穷的时代,它仍旧有其一席之位.Cookie ...
- RT-Thread 组件 FinSH 使用时遇到的问题
一.FinSH 的移植与使用问题 FinSH组件输入无反应的问题 现象:当打开 finsh 组件后,控制台会打相应的信息,如下图说是: \ | / - RT - Thread Operating Sy ...
- Mybatis整合第三方缓存
1) 为了提高扩展性.MyBatis定义了缓存接口Cache.我们可以通过实现Cache接口来自定义二级缓存 2) EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点. 3) 整合 ...
- C#《原CSharp》第三回 万文疑谋生思绪 璃月港口见清玉
第三回 万文疑谋生思绪 璃月港口见清玉 ===================================================================== 云溪愣了下,在他的认 ...
- 彻底理解DDS(信号发生器)的fpga实现(verilog设计代码)
DDS(Direct Digital Synthesis)是一种把一系列数字信号通过D/A转换器转换成模拟信号的数字合成技术. 它有查表法和计算法两种基本合成方法.在这里主要记录DDS查表法的fpga ...