日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

高性能动态编译库Natasha发布1.0版本!

發布時間:2023/12/4 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 高性能动态编译库Natasha发布1.0版本! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、 前言


????????對于開源貢獻者,Emit和表達式樹不是陌生的字眼,IL的動態特性為封裝工作帶來了極大的方便,會Emit的開發者可以說駕馭了大部分的高性能、高動態的編程技巧。縱觀ef、dapper、json.net等第三方常用庫,哪個能脫離emit而獨善其身,也正因如此,幸福了一批批懶癌患者,包括我這個懶癌中晚期患者(這里給各位病友問好),與此同時本人對封裝有著莫名其妙的執念,就在兩支怪力的驅使下走上了對emit的不歸路.


舊版Natasha始于2016年,當時是對Emit進行的封裝,中途經有檸檬的提醒完善了UT和兼容性等工作,后由Victor.X.Qu補充了文檔,后經ORM實戰。


二、Emit非銀彈


????????經歷過重重思考和實踐,Emit不是動態的最佳實踐,簡單的從以下幾個角度來講:


  • 調優:


  • dup : emit中的dup指令優化在是由開發者控制的,在熟悉指令操作的同時又給開發者帶來了額外的優化工作。


  • if/while/for :不得不說IL可以透過代碼看本質,指令就是這樣的,在條件分支上,標簽跳轉的形式使得邏輯執行靈活多變。這樣除了棧的操作之外,還要關注標簽的位置和跳轉語句的優化,另外還要清晰的記得你的各個分支。


  • 并發字典與算法優化 :這一點是出自我的極端,在對象成員的賦值/加載等操作面前,并發字典像是一場災難,賣盡氣力優化的動態執行,卻被某些數據結構所糟蹋。至于算法與動態編譯結合起來,應該沒幾個病友做過,各位如果有興趣的話可以慢慢體會。



  • 兼容性:


  • 結構體 : 類與結構體在操作指令上有著諸多的不同,開發者不僅僅要熟悉對類的操作指令,還要對結構體做出兼容,諸如ldflda、 ldloca、Constrained等指令,對于開發者來說并不是一件省心的事。


  • 類型轉換 : .NET中的類型轉換不僅僅有指令級的轉換,standard還提供了諸多方法支持不同類型之間的轉換,因此你還需要花一些功夫去處理這些。


  • 語法糖 : 一切語法糖在emit面前都要還原,比如可空類型語法糖,對象比較語法糖,類型比較語法糖等等,無疑會大大增加兼容工作的負擔(core3.0的可空引用我還沒有做測試)。



  • 構建難度:


  • 深度克隆 : 深度克隆是動態編程的一個典型實戰,如果各位病友堅持用EMIT挑戰的話,可以沒病走兩步,走兩步。


  • 深度構建 :一旦遇到了動態構建動態場景,那么這個復雜度難以想象。


  • 猜錯誤 : Emit并沒有很好的友情提示,沒有語法檢查,而被程序鍛煉成老獵手一定要付出很多代價。



  • 維護升級:


  • 后續開發 :接手emit代碼是一件令人糾結的事,當量變引起質變的時候,從興奮到苦不堪言這種事情并不是沒有發生過,尤其是現在.NET開源工作者都比較獨立,沒有凝聚力和氛圍,人的生命以及精力是有限的。


  • 傳承 ?:由上面諸多信息也可見,在新技術的沖擊下,在令人不安的環境下,在孤獨的夜里,傳承也是個問題。




盡管表達式樹已經幫我們做了一些工作,但復雜場景和使用習慣仍然封印著開發者的大腦。


三、狙擊暴君


??????? Roslyn到如今已經耳熟能詳了,編譯被當作成服務對外開放,讓不少開發者從中受益,但由于文檔不全,實例不充分,從開始一直到2018年期間,對于懶癌開發者來說,基于Roslyn開發都是一件憋手的事情(例如一些必備操作文檔,在2019年今年5月份才提上日程)。Natasha使用Roslyn做為編譯引擎,不僅僅在動態構建上進行了人性化升級,還在功能上進行了簡化。您不僅可以使用Natasha輕松的構建類、結構體、方法、接口、抽象類,還可以輕松的繼承類、重載方法、實現接口、抽象類等等,技術較新,僅支持.standard2.0。


????????項 目 地 址:https://github.com/dotnetcore/Natasha

??????? Nuget索引:DotNetCore.Natasha ?(正式版1.0.0.0)


(娜塔莎)(原型蘇聯紅軍第25步兵師的中尉柳德米拉·帕夫利琴科,一名出色的女狙擊手)


使用Natasha你需要關注:


  • 在您的工程文件里添加這個節點:<PreserveCompilationContext>true</PreserveCompilationContext>


  • 了解wiki中反解器的概念及使用。? ??


  • 注意命名空間,自動補充命名空間目前尚未支持,需要您手動操作,使用using方法添加。


  • 想盡一切辦法拼接字符串,目前符合CSharp7.3或以下C#版本的都行。


  • 編譯模式有區分:StreamComplier內存流編譯/FileComplier文件流編譯, 文件流編譯的內容,可以被動態調用。當你想動態編譯類B的時候使用類A,那類A就需要使用文件流編譯,相當于dll動態加載到運行時。


  • 使用Natasha中的Operator來構建你的動態內容。

  • 四、性能


    ????????這幾年隨著.NET架構引擎的不斷升級,dynamic、emit執行性能已經得到了大幅度提升,roslyn也不例外,之前官方給過性能測試截圖,上面顯示是比emit快一點,個人的基準測試要等下一個benchmark版本,從耗時的角度來說roslyn <= emit (roslyn有指定release模式編譯),所以大家根本不用關心性能問題。


    五、使用案例


    ????????使用之前需要注意的是,方法操作都是基于內存流編譯,類和其他都基于文件流編譯。但有特殊情況,比如有些方法需要被復用,這時可以在編譯選項中如此操作:

    var tempBuilder = FastMethodOperator.New; tempBuilder.ComplierOption.UseFileComplie(); //可根據需求選擇編譯方式 var builder?=?new?ClassBuilder(); builder.ComplierOption.UseFileComplie(); builder.ComplierOption.UseMemoryComplie();


    • 實現抽象類與接口


    public abstract class TestAbstract { public int Name; public int Age; public abstract int GetAge(); public abstract string GetName(); } OopOperator<TestAbstract>?abstractBuilder?=?new?OopOperator<TestAbstract>(); abstractBuilder.ClassName("UTestClass"); abstractBuilder["GetName"]?=?"return?Name;"; abstractBuilder["GetAge"] = "return Age;"; abstractBuilder.Compile(); TestAbstract test = abstractBuilder.Create("UTestClass"); public interface ITest { int?MethodWidthReturnInt(); string?MethodWidthReturnString(); void?MethodWidthParamsRefInt(ref?int?i); string?MethodWidthParamsString(string?str); string?MethodWidthParams(int?a,string?str,int?b); } OopOperator<ITest>?interfaceBuilder?=?new?OopOperator<ITest>(); interfaceBuilder.ClassName("UTestClass"); interfaceBuilder["MethodWidthReturnInt"]?=?"return?123456;"; interfaceBuilder["MethodWidthReturnString"]?=?"return?\"test\";"; interfaceBuilder["MethodWidthParamsRefInt"]?=?"i+=10;"; interfaceBuilder["MethodWidthParamsString"]?=?"return?str+\"1\";"; interfaceBuilder["MethodWidthParams"]?=?"return?a.ToString()+str+b.ToString();"; interfaceBuilder.Compile(); ITest?test?=?interfaceBuilder.Create("UTestClass");



    • 快速編寫委托


    public delegate string GetterDelegate(int value); //方法一 var action = DelegateOperator<GetterDelegate>.Create("value += 101; return value.ToString();"); //action(1); result: "102" //方法二 var action = "value += 101; return value.ToString();".Create<GetterDelegate>(); //action(1); result: "102"



    • 定制方法


    var action = FastMethodOperator.New .Param<string>("str1") .Param(typeof(string),"str2") .MethodBody("return str1+str2;") .Return<string>() .Complie<Func<string,string,string>>(); string result = action("Hello ","World!"); //result: "Hello World!"



    • 偽造方法


    //這里只為演示,實際使用請用下面的靜態構造,拿到委托后可以直接運行。 public?class TestB { public?void?TestMethod(){} } var action = FakeMethodOperator.New .UseMethod<TestB>("TestMethod") .MethodContent($@"Console.WriteLine(""Hello World!"");") .Complie<Action>(); //The class script : // // using System; // public class N20d26dcba7e6451eaf4c4a6f4753e243 // { // public void TestMethod() //?????????{ // Console.WriteLine("Hello World!"); // } // } var action = FakeMethodOperator.New .UseMethod<TestB>("TestMethod") .StaticMethodContent($@"Console.WriteLine(""Hello World!"");") .Complie<Action>(); //The class script : // //????using?System; // public static class Neae0b5f6b8b94f4b9418ebc68813760b // { // public static void TestMethod() //???????? { // Console.WriteLine("Hello World!"); // } // }



    • 自定制一個類


    ClassBuilder builder = new ClassBuilder(); var script = builder .Namespace("TestNamespace") .ClassAccess(AccessTypes.Private) .ClassModifier(Modifiers.Abstract) .ClassName("TestUt2") .ClassBody(@"public static void Test(){}") .PublicStaticField<string>("Name") .PrivateStaticField<int>("_age") .Builder().Script; Assert.Equal( @"using System;namespace TestNamespace{private abstract class TestUt2{public static String Name;private static Int32 _age;public static void Test(){}}}" ,?script);


    • 自編譯一個類


    string text = @"using System; using System.Collections; using System.Linq; using System.Text; namespace HelloWorld { public class TestIndex1 { public string Name; public int Age{get;set;} } public class TestIndex2 { public string Name; public int Age{get;set;} } public class TestIndex3 { public string Name; public int Age{get;set;} } } namespace HelloWorld{ public struct TestStruct1{} public struct TestStruct2{} public class TestIndex4 { public string Name; public int Age{get;set;} } }"; //根據腳本創建動態類 //尋找第二個命名空間中的第一個類 Type type = RuntimeComplier.GetClassType(text, 1,2); Assert.Equal("TestIndex4", type.Name); //尋找第二個命名空間中的第二個結構體 type = RuntimeComplier.GetStructType(text, 2, 2); Assert.Equal("TestStruct2", type.Name);


    六、方便的擴展


    • 使用Natasha的類擴展:


    Example:?????????? typeof(Dictionary<string,List<int>>[]).GetDevelopName(); //result: "Dictionary<String,List<Int32>>[]" typeof(Dictionary<string,List<int>>[]).GetAvailableName(); //result: "Dictionary_String_List_Int32____" typeof(Dictionary<string,List<int>>).GetAllGenericTypes();? //result: [string,list<>,int] typeof(Dictionary<string,List<int>>).IsImplementFrom<IDictionary>(); //result: true typeof(Dictionary<string,List<int>>).IsOnceType(); //result: false typeof(List<>).With(typeof(int)); //result: List<int>


    • 使用Natasha的方法擴展:


    Example: Using : Natasha.Method; public delegate int AddOne(int value); var action = "return value + 1;".Create<AddOne>(); var result = action(9); //result : 10 var action = typeof(AddOne).Create("return value + 1;"); var result = action(9); //result : 10


    • 使用Natasha的克隆擴展:?


    Example: Using : Natasha.Clone; var instance = new ClassA(); var result = instance.Clone();


    • 使用Natasha的快照擴展:


    Example: Using : Natasha.Snapshot; var instance = new ClassA(); instance.MakeSnapshot(); // ******** // do sth //?******** var result = instance.Compare();



    七、實戰


    • 深度克隆:Natasha中提供了類遍歷器,結合多層動態編譯,可以支持復雜數據結構的克隆操作。


    • NCaller是Natasha的實戰項目,采用動態原生操作+動態優化查找算法,可以對動/靜態類初始化以及字段和屬性的常規操作,耗時僅為原生的2.5倍以下。


    八、調試


    ????????由于核心編譯引擎為Roslyn,因此語法檢查、詞法檢查、語義檢查等都支持,這樣可以很好的為開發者提供錯誤提示, Natasha為此增加日志模塊(NScriptLog), 在編譯流程中,捕獲編譯信息并記錄,另需注意的是,Natasha腳本的格式化操作與VS的格式化一樣,所以需要開發者在構建腳本的時候就要多多注意換行的問題。Natasha的編譯日志共有3個種類:成功日志、錯誤日志、警告日志。

    ??

    • 成功日志:

    • ?錯誤日志:

    • ?警告日志:



    九、寄語


    ???????隨著.NETCore的不斷升級,Natasha還有很多新的特性在等待開發,希望各位多多支持。https://github.com/night-moon-studio ?NMS是一個基于Natasha的開源項目“孵化”組,項目成熟且通過審核之后(或改名)推薦進入NCC,大家可以積極參與。


    ??????? Natasha如果說是一個庫不如說是一個時機,動態封裝已經不是學習成本高、開發效率低的工作了,希望各位能積極參與嘗試開源項目,共同打造.NET Core新生態。




    https://github.com/dotnetcore

    打賞一杯酒,削減三分愁。
    跟著我們走,脫發包你有。

    組織打賞賬戶為檸檬的賬戶,請標注「NCC」,并留下您的名字,以下地址可查看收支明細:https://github.com/dotnetcore/Home/blob/master/Statement-of-Income-and-Expense.mdOpenNCC,專注.NET技術的公眾號https://www.dotnetcore.xyz微信ID:OpenNCC長按左側二維碼關注


    歡迎打賞組織

    給予我們更多的支持


    總結

    以上是生活随笔為你收集整理的高性能动态编译库Natasha发布1.0版本!的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。