当NativeAOT遇到Garnet

时间:08/31/2024 17:33:36   作者:ChenReal    阅读:88

前言

也许大伙还有印象吧。前几个月,我曾经大张旗鼓地介绍了Garnet。《Garnet开发实战:准备好跟Redis说拜拜了吗?》

如果不记得,或者没看过的话,建议先回顾一下。因为很多概念和知识点,我都不会在这里“炒冷饭”。

开讲正题之前,我还是忍不住插播一则消息:我公司的项目已经成功把缓存中间键,从Redis和Memecached迁移到Garnet了!迁移的过程非常顺利,并且项目版本上线运行超过1个月相当稳定!我也算是业内比较敢于“吃螃蟹”的人了。

如果有时间,我会另外写一篇文章,来总结一下这个迁移的过程。但今天我准备探讨的是另外一个话题:假如将Garnet用NativeAOT来发布,能成功吗?

正题

首先我问了一下,搜索引擎。发现早在4月的时候,有人在Github上讨论过,甚至还有人实践过了,并没得到让我欣喜的答案!

最终,我决定亲自尝试一下,看看几个月过去了Garnet有没有悄悄地给我们惊喜。

1、升级Garnet

首先,将Garnet升级到最新版本(1.0.19)。

<PackageReference Include="Microsoft.Garnet" Version="1.0.19" />

1.png

2、项目启用NativeAOT

修改一下原来的工程配置文件(*.csproj),增加PublishAot配置节点。参考如下:

<PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <PublishAot>true</PublishAot>
</PropertyGroup>

3、编译发布

执行发布命令:

dotnet publish GarnetServer.csproj -o $PWD/build -c Release -r osx-x64

4、执行

编译发布后,得到一个大小30M左右的可执行文件。 2.png

迫不及待,执行一下。

./GarnetServer

3.png

结果,奇迹并未出现。报错了,而且还是一个非常经典报错提示: Object reference not set to an instance of an object

仔细看编译发布的log,从一堆warning消息,可以初步判断,似乎是Garnet以及其所依赖的库并不支持NativeAOT的编译裁剪,导致生成的执行文件运行报错。

总结

我暂时没有解决问题的思路和线索,只能到此为止。直接宣布:当NativeAOT遇到Garnet,得到的结果会是“Object reference not set to an instance of an object”。

NativeAOT对编译代码是有要求的,在JIT上能够变异运行的代码不能保证100%能AOT化。其中一个很大的限制来源于:.NET 的动态功能不可用(例如,动态实例化类型、使用 C# dynamic 关键字、或动态加载代码等)而动态化是当今C#主流写法,最大的矛盾点在此。

不像golang或Rust,它们本就是面向静态编译而生的,因此编译成Native应用易如反掌。

希望微软继续努力,如果把Garnet的NativeAOT补上,那就真的非常完美了!同样,这也是一件任重道远的事情。

 

评论
0/200