真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

不安裝運(yùn)行時(shí)運(yùn)行 .NET 程序

大家好,先祝大家國慶快樂。不過大家看到這篇文章的時(shí)候估計(jì)已經(jīng)過完國慶了 ????。
上一篇我們寫了如何通過 SelfContained 模式發(fā)布程序(不安裝運(yùn)行時(shí)運(yùn)行.NET程序)達(dá)到不需要在目標(biāo)機(jī)器上安裝 runtime 就可以運(yùn)行 .NET 程序的目標(biāo)。其實(shí)除了標(biāo)準(zhǔn)的 self-contained 微軟還給我們帶來了 Native AOT 發(fā)布模式。是的你沒看錯(cuò),通過該技術(shù)我們的 .NET 程序會(huì)直接編譯為 Native 代碼而不再是 IL ,程序運(yùn)行的時(shí)候直接就是機(jī)器碼,不再需要 JIT 編譯。通過 AOT 技術(shù),我們的程序啟動(dòng)會(huì)變的非??觳⑶沂褂酶俚膬?nèi)存,并且運(yùn)行的時(shí)候不需要在機(jī)器上安裝任何運(yùn)行時(shí)。
前階段 .NET7 發(fā)布了第一個(gè) RC 版本,標(biāo)志著正式版的 AOT 馬上會(huì)隨 .NET7 發(fā)布而到來。所以趁著國慶趕緊體驗(yàn)一把。

創(chuàng)新互聯(lián)公司主要從事做網(wǎng)站、成都做網(wǎng)站、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)渾江,十多年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):13518219792

環(huán)境與工具

現(xiàn)階段 .NET7 還在RC,所以我們選擇安裝 SDK 7.0.100-rc.1.22431.12 ,操作系統(tǒng)是 WIN10 64位,開發(fā)工具是 VS2022 17.4.0 Preview 2.1 。正式版的 VS2022 是沒辦法選擇目標(biāo)框架 .NET7 的,但是其實(shí)可以手動(dòng)改 csproj 文件,所以 VS2022 Preview 不是必須的。

Console App

我們新建一個(gè)控制臺(tái)程序,目標(biāo)框架選擇 NET7 (如果使用正式版的 VS2022 沒有辦法選擇 net7 ,可以直接編輯 csproj 文件),右鍵項(xiàng)目選擇“編輯項(xiàng)目文件”,在 PropertyGroup 節(jié)點(diǎn)下添加 PublishAot :



    
        Exe
        net7.0
        enable
        enable
		
        true
		
    



修改 main 方法:

Console.WriteLine("Hello, AOT!");

Console.Read();

使用 dotnet 命令進(jìn)行發(fā)布:

dotnet publish -r win-x64 -c Release


AOT 發(fā)布相比正常發(fā)布會(huì)慢一點(diǎn),等待發(fā)布成功后,我們可以到以下目錄查看 bin\Release\net7.0\win-x64\publish :

我們可以看到生成的 exe 文件只有 3.48MB ,相比普通單文件發(fā)布加裁剪過后的程序小了不少。

我們把這個(gè) exe 程序復(fù)制到一臺(tái)沒有安裝 .net 環(huán)境的服務(wù)器上,順利運(yùn)行起來了。

ASP.NET CORE

上面我們測(cè)試了一下控制臺(tái)程序的 AOT 發(fā)布,相對(duì)比較簡單沒有什么問題。下面讓我們?cè)囋噾?yīng)用范圍最為廣泛的 ASP.NET CORE 項(xiàng)目 AOT 發(fā)布行不行。
新建一個(gè) ASP.NET CORE WebApi 項(xiàng)目,目標(biāo)框架選擇 NET7 。同樣的操作編輯 csproj 文件,添加 PublishAot 屬性:



  
    net7.0
    enable
    enable

    true
  



同樣使用 dotnet cli 命令進(jìn)行發(fā)布:

dotnet publish -r win-x64 -c Release

不同于上面控制臺(tái)項(xiàng)目的發(fā)布,ASP.NET CORE 項(xiàng)目的 AOT 發(fā)布會(huì)出現(xiàn)很多警告信息,暫且忽略。

等到發(fā)布完成后,我們看到生成了一個(gè) 27MB 大小的 exe 文件。雙擊運(yùn)行起來,不得不提一句,這個(gè)啟動(dòng)速度真的是肉眼可見的快,雙擊之后瞬間就啟動(dòng)了。這個(gè)就是 AOT 發(fā)布最大的優(yōu)勢(shì)了。

訪問一下默認(rèn)生成的那個(gè) Action 方法:http://localhost:5000/WeatherForecast/ 成功的輸出了天氣信息。

序列化的問題

以上通過簡單的測(cè)試,ASP.NET CORE WebApi 項(xiàng)目順利的跑起來了, 當(dāng)然他只是一個(gè)簡單的示例項(xiàng)目,我們生產(chǎn)的項(xiàng)目相比這些要復(fù)雜多了。經(jīng)過更深入的測(cè)試,發(fā)現(xiàn)現(xiàn)階段 ASP.NET CORE 進(jìn)行 AOT 發(fā)布后有一個(gè)比較麻煩的問題,那就是 JSON 序列化。
以下代碼是默認(rèn)生成的 WeatherForecastController 的 GET 方法,這個(gè)方法是個(gè)標(biāo)準(zhǔn)的同步方法,進(jìn)行 AOT 發(fā)布后序列化沒有任何問題。

   [HttpGet]
        public WeatherForecast[] Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }

但是如果把代碼改成異步,或者說的更直白一點(diǎn)的話,返回值是 Task<T> 類型就會(huì)出現(xiàn)問題。比如把上面的代碼使用 Task.FromResult 改造一下,使返回值變成 Task

       [HttpGet]
        public async Task Get()
        {
            var arr = Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();

            var result = await Task.FromResult(arr);

            return result;
        }

改造的程序進(jìn)行 AOT 發(fā)布后運(yùn)行,訪問對(duì)應(yīng)的接口程序不會(huì)有任何報(bào)錯(cuò),但是返回值是個(gè)空對(duì)象的json:

{}

嘗試修復(fù)該問題,并沒有特別的好辦法,目前能夠勉強(qiáng)使用的辦法是使用 System.Text.Json source generator 模式進(jìn)行序列化:
首先編寫一個(gè) WeatherForecastContext 類繼承 JsonSerializerContext,并且標(biāo)記為 partial。為啥要標(biāo)記為 partial ?因?yàn)轭惖牧硗獠糠质?source generator 自動(dòng)生成的。

   [JsonSerializable(typeof(Task))]
    internal partial class WeatherForecastContext : JsonSerializerContext
    {
    }

第二步,在配置 services 的時(shí)候順便把 WeatherForecastContext 配置進(jìn)去。

builder.Services.AddControllers()
    .AddJsonOptions(options => options.JsonSerializerOptions.AddContext()); 

通過以上操作,再次 AOT 發(fā)布后運(yùn)行程序,訪問接口,數(shù)據(jù)是能正確的返回了。但是有一點(diǎn)小瑕疵是Task對(duì)象自身的屬性也被序列化出來了。

{
    "result": [
        {
            "date": "2022-10-08T19:14:26.1801524+08:00",
            "temperatureC": 6,
            "temperatureF": 42,
            "summary": "Warm"
        },
        {
            "date": "2022-10-09T19:14:26.1816645+08:00",
            "temperatureC": -9,
            "temperatureF": 16,
            "summary": "Bracing"
        },
        {
            "date": "2022-10-10T19:14:26.1816648+08:00",
            "temperatureC": -1,
            "temperatureF": 31,
            "summary": "Sweltering"
        },
        {
            "date": "2022-10-11T19:14:26.181665+08:00",
            "temperatureC": -17,
            "temperatureF": 2,
            "summary": "Balmy"
        },
        {
            "date": "2022-10-12T19:14:26.1816651+08:00",
            "temperatureC": -16,
            "temperatureF": 4,
            "summary": "Freezing"
        }
    ],
    "asyncState": null,
    "creationOptions": 0,
    "exception": null,
    "id": 1,
    "isCanceled": false,
    "isCompleted": true,
    "isCompletedSuccessfully": true,
    "isFaulted": false,
    "status": 5
}

桌面程序

以上對(duì)控制臺(tái)程序,web 程序進(jìn)行了測(cè)試,接下來順便對(duì)桌面 GUI 程序測(cè)試一下吧。

很遺憾,不管是 WINFROM 還是 WPF 程序,進(jìn)行 AOT 發(fā)布的時(shí)候直接都會(huì)報(bào)錯(cuò),提示不支持。

一些其他限制

AOT 發(fā)布的程序會(huì)有一些限制,我們編寫的時(shí)候需要注意:

  1. No dynamic loading (for example, Assembly.LoadFile)
  2. No runtime code generation (for example, System.Reflection.Emit)
  3. No C++/CLI
  4. No built-in COM (only applies to Windows)
  5. Requires trimming, which has limitations
  6. Implies compilation into a single file, which has known incompatibilities
  7. Apps include required runtime libraries (just like self-contained apps, increasing their size, as compared to framework-dependent apps)

以上是直接復(fù)制的英文文檔(原文地址在文末),因?yàn)橛⑽牟皇呛芎茫贿M(jìn)行翻譯了,怕誤導(dǎo)大家。主要需要注意的就是 1,2 兩點(diǎn) ,關(guān)于動(dòng)態(tài)加載類庫跟動(dòng)態(tài)生成代碼的問題。我想序列化的問題大概也就是出在這里,因?yàn)閭鹘y(tǒng)的序列化需要大量的使用動(dòng)態(tài)生成代碼技術(shù)。

總結(jié)

通過以上我們對(duì) .NET 上最常用的幾種程序進(jìn)行了 Native AOT 發(fā)布的測(cè)試??傮w來說控制臺(tái)跟ASP.NET CORE 項(xiàng)目能用,WINFROM 跟 WPF 不能用。比較遺憾的有兩個(gè)點(diǎn):

  1. ASP.NET COER 在序列化方面貌似還有點(diǎn)小問題。不知道是不是我環(huán)境的問題,如果有知道的大神請(qǐng)指點(diǎn)指點(diǎn)
  2. 不支持桌面 GUI 程序。其實(shí)從個(gè)人的經(jīng)驗(yàn)來說,桌面端可能對(duì)啟動(dòng)速度更加敏感一點(diǎn),因?yàn)閏/s程序經(jīng)常性的打開關(guān)閉、打開關(guān)閉,如果啟動(dòng)慢用戶是很容易察覺的。如果桌面程序能支持 AOT ,那么能大大改進(jìn)現(xiàn)在 .NET 程序的啟動(dòng)速度,這對(duì)用戶體驗(yàn)的提升是非常大的。服務(wù)端的話本身啟動(dòng)一次后就長期運(yùn)行,用戶不會(huì)時(shí)時(shí)刻刻感受到啟動(dòng)速度帶來的影響。另外現(xiàn)在 .NET 程序啟動(dòng)本身就不慢,況且還有 R2R 可以選,正常在100-200ms之間的啟動(dòng)速度已經(jīng)對(duì)用戶體驗(yàn)影響不大了。所以 AOT 之后的啟動(dòng)速度的優(yōu)勢(shì)不是很大。

另外來說說性能,有同學(xué)可能覺得 Native AOT 之后性能會(huì)有很大的提升,畢竟大家都迷信 Native 速度快嘛。但是經(jīng)過大佬們的測(cè)試事實(shí)上 AOT 之后跟沒有 AOT 的代碼性能基本在伯仲之間,有些地方甚至不如非 Native 的代碼。為什么?因?yàn)榉?Native 代碼可以進(jìn)行運(yùn)行時(shí) JIT 啊,可以在運(yùn)行時(shí)分析代碼對(duì)熱點(diǎn)代碼進(jìn)行二次 JIT 來提升性能,而 Native AOT 之后的代碼做不到這點(diǎn)。

參考

Native AOT Deployment
Try the new System.Text.Json source generator
AOT和單文件發(fā)布對(duì)程序性能的影響

關(guān)注我的公眾號(hào)一起玩轉(zhuǎn)技術(shù)


網(wǎng)站名稱:不安裝運(yùn)行時(shí)運(yùn)行 .NET 程序
地址分享:http://weahome.cn/article/dsoidjo.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部