《ASP.NET Core 高性能系列》致敬偉大的.NET鬥士甲骨文!

寫在開始

  三年前,曾寫過一篇文章:從.NET和Java之爭談IT這個行業,當時遭到某些自認爲懂得java就了不得的Javaer抨擊,html

如今能夠致敬偉大的.NET鬥士甲骨文了java

  (JDK8以上都須要收費,Android棄用java做爲第一語言,別高興:OpenJDK是甲骨文的).express

  《ASP.NET Core 高性能系列》是一套如何編寫高性能Web應用技術系列文章,緩存

咱們將從.NET 2開始全面升入.其中咱們會討論互聯網當今熱門的技術話題:容器、容器編排、服務治理、RPC等數據結構

此文是第一篇,用於此係列的開門篇,後面每週會持續發佈.架構

1、Core 2中須要知道的新鮮東西

Core系列有兩個主要產品:框架

第一個是.NET Core
異步

  它是一個低級別的提供基本庫的框架。 它能夠用來編寫控制檯應用程序,它也是async

更高級別的應用程序框架的基礎。 分佈式

第二個是ASP.NET Core

  它是一個用於構建Web的跨平臺框架

另外.NET Core中的更改也將適用於ASP.NET Core,由於這是基礎 

2、.NET Core 2的新東西

2.1 API範圍更加普遍

  .NET Core 2的主要焦點是API範圍的大幅增長,在1.*的基礎上增長了兩倍的API,

並且支持.net standard,您也能夠引用.NET Framework程序集而無需從新編譯,

只要程序集中的API已在.NET Core中實現就能夠正常工做。這意味着更多的Nuget包能夠在.NET Core中工做,

ASP.NET Core Library and Framework 支持狀況的一個統計站點:https://ANCLAFS.com(有點跟不上了)

2.2 性能的大幅度提高

.NET Core 2.0中一些更有趣的變化是在原始的.NET FrameworkAPI上性能改進

,已經對許多框架的實現進行了調整了數據結構。 

下面是一些已經看到快速改進的類和方法,已經內存開銷的減小包括:

List<T>
Queue<T>
SortedSet<T>
ConcurrentQueue<T>
Lazy<T>
Enumerable.Concat()
Enumerable.OrderBy()
Enumerable.ToList()
Enumerable.ToArray()
DeflateStream
SHA256
BigInteger
BinaryFormatter
Regex
WebUtility.UrlDecode()
Encoding.UTF8.GetBytes()
Enum.Parse()
DateTime.ToString()
String.IndexOf()
String.StartsWith()
FileStream
Socket
NetworkStream
SslStream
ThreadPool
SpinLock 

  另外,對於.NET Core 2RyuJIT Just In Time編譯器進行了改進。

僅做爲一個示例就能說明說明其優秀之處,finally塊如今幾乎與不使用異常同樣高效,

這在沒有拋出異常的正常狀況下是有益的。您如今沒有理由不使用tryusing{}塊,以及checked檢查

3、ASP.NET Core 2的新東西 

  ASP.NET Core 2利用了.NET Core 2的全部改進,不只經過即時編譯處理程序縮短了啓動時間,

涵蓋了增長了輸出緩存,本地及分佈式緩存(SQLSERVER,REDIS).

3.1 metapackage

  .NET Core包含了一個新metapackage,因此你只用引用一個NuGet項就能夠獲得全部的東西,metapackage仍然由單個獨立的包組成,

一個新的包修剪功能(new package-trimming)確保若是您不使用包,那麼它的二進制文件將不會包含在您的部署中,

即便您使用metapackage 來引用它。設置Web主機配置也有合理的默認設置。

您無需單獨添加logging, Kestrel, and IISlogging也變得更簡單,由於它是創建的在,你再也沒有任何藉口不一開始就使用它

3.2 Razor Pages

  無控制器Razor Pages。 這正是它聽起來的樣子,並且它容許您使用Razor模板編寫頁面。

它相似於Web Pages產品,沒必要和WebForm混淆。 你們其實以爲是WebForm的捲土重來,我的感受是滿懷但願的捲土重來,

架構作了更多抽象和思考,不會像以前同樣,帶來如此多的狀態與之相伴.

3.3 新的authentication 模型

  新的 authentication 模型能讓更好地使用了依賴注入, ASP.NETCore Identity 容許你使用OpenID OAuth 2

來爲你的API獲取訪問tokens .固然你能夠研究Identity Server 4 項目,它提供了相同的功能.

3.4 表單請求自動防僞

  你沒必要再爲表單添加防僞token(防止跨越僞造請求) (以前你不得不添加一個attributePost方法中進行驗證),

如今這一切都是自動的.

3.5性能提高

   ASP.NET Core有一些額外的與.NET Core無關的性能提高:

啓動時間經過即時編譯處理明顯減小,雖然這不是ASP.NET Core 2的新功能;

 output caching依然可用,在1.0時,只有response caching*(簡化了如何設置http header),

1.1 時,添加了memory cache,如今你能夠還使用分佈式緩存()SQL Server or Redis) 

.NET Standard 2.0

  .NET Standard 是一套正式的 .NET API 規範,目標是在全部 .NET 實現中推出。 推出 .NET Standard 的背後動機是要提升 .NET 生態系統中的一致性。

ECMA 335 持續爲 .NET 實現行爲創建統一性,但適用於 .NET 庫實現的 .NET 基類庫 (BCL) 沒有相似的規範。

.NET Framework 4.6.1實現了.NET Standard  2.0.

.NET Standard 可實現如下重要情境:

1.爲要實現的全部 .NET 實現定義一組統一的、與工做負荷無關的 BCL API

2.使開發人員可以經過同一組 API 生成可在各類 .NET 實現中使用的可移植庫。

3.減小甚至消除因爲 .NET API 方面的緣由而對共享源代碼進行的條件性編譯(僅適用於 OS API)。 

5、C# 6.0語言級別的新東西

5.1 屬性能夠連帶賦值

public DateTime BirthDay { get; set; } = DateTime.Now.AddYears(-20);

 

5.2 導入靜態類

using static System.Math;

Console.WriteLine($"導入後可直接使用方法: {Pow(4, 2)}");

 

5.3 字符串格式化的變化

Console.WriteLine(string.Format("當前時間:{0}",DateTime.Now.ToString()));

 

5.4 空值運算符

Console.WriteLine(name?.ToString()); // 程序不會報錯,也不會輸出任何值

 

5.5 對象初始化器

能夠經過索引的方式進行賦值

IDictionary<int, string> dictNew = new Dictionary<int, string>()
{
       [4] = "first",
       [5] = "second"
};

  

5.6 異常過濾器

int exceptionValue = 10;
try
{
       Int32.Parse("s");
}
catch (Exception e) when (exceptionValue > 1)//知足條件才進入catch
{
       Console.WriteLine("catch");
}

5.7 nameof表達式

Console.WriteLine(nameof(People));

5.8 在屬性/方法裏面使用Lambda表達式

 public void Print() => Console.WriteLine(Name);

 

6、C# 7.0語言級別的新東西

6.1 out變量不須要申明瞭

  var input = ReadLine();
  if (int.TryParse(input, out var result))
  {

      WriteLine("您輸入的數字是:{0}",result);
  }
  else
  {
      WriteLine("沒法解析輸入...");
  }

  

6.2元組

 元組(Tuple)在 .Net 4.0 的時候就有了,但元組也有些缺點,如:

   1)Tuple 會影響代碼的可讀性,由於它的屬性名都是:Item1,Item2.. 。

   2)Tuple 還不夠輕量級,由於它是引用類型(Class)。

   備註:上述所指 Tuple 還不夠輕量級,是從某種意義上來講的或者是一種假設,即假設分配操做很是的多。

 C# 7 中的元組(ValueTuple)解決了上述兩個缺點:

   1)ValueTuple 支持語義上的字段命名。

   2)ValueTuple 是值類型(Struct)。

 

傳統的建立方式

  var tuple = (1, 2);                           // 使用語法糖建立元組

  var tuple2 = ValueTuple.Create(1, 2);         // 使用靜態方法【Create】建立元組 

  var tuple3 = new ValueTuple<int, int>(1, 2);  // 使用 new 運算符建立元組 WriteLine($"first:{tuple.Item1}, second:{tuple.Item2}, 上面三種方式都是等價的。");

//建立給字段命名的元組
// 左邊指定字段名稱
  (int one, int two) tuple = (1, 2);
  WriteLine($"first:{tuple.one}, second:{tuple.two}");
  // 右邊指定字段名稱
  var tuple2 = (one: 1, two: 2);
  WriteLine($"first:{tuple2.one}, second:{tuple2.two}"); 
  // 左右兩邊同時指定字段名稱
  (int one, int two) tuple3 = (first: 1, second: 2);   
 /* 此處會有警告:因爲目標類型(xx)已指定了其它名稱,由於忽略元組名稱xxx */
  WriteLine($"first:{tuple3.one}, second:{tuple3.two}");

6.3 解構

6.3.1解構元組 

var (one, two) = GetTuple();
WriteLine($"first:{one}, second:{two}");
static (int, int) GetTuple() {
  return (12, 2);
} 

6.3.2解構能夠應用於 .Net 的任意類型,

但須要編寫 Deconstruct 方法成員(實例或擴展)

public void Deconstruct(out type variable1, out type variable2...)
public static void Deconstruct(this type instance, out type variable1, out type variable2...)

 6.4 模式匹配

6.4.1 is 表達式(is expressions

static int GetSum(IEnumerable<object> values)
  {
      var sum = 0;
      if (values == null) return sum;  
      foreach (var item in values)    
{
if (item is short) // C# 7 以前的 is expressions { sum += (short)item; } else if (item is int val) // C# 7 的 is expressions { sum += val; } else if (item is string str && int.TryParse(str, out var result)) // is expressions 和 out variables 結合使用 { sum += result; } else if (item is IEnumerable<object> subList) { sum += GetSum(subList); } } return sum; }  

6.4.2 switch語句

switch (item)
  {
      case type variable1:
          // processing...
          break;
      case type variable2 when predicate:
          // processing...
          break;
      default:
          // processing...
          break;
  }

6.5 Ref locals and returns

static ref int GetLocalRef(int[,] arr, Func<int, bool> func)
  {
      for (int i = 0; i < arr.GetLength(0); i++)
      {
          for (int j = 0; j < arr.GetLength(1); j++)
          {
              if (func(arr[i, j]))
              {
                  return ref arr[i, j];
              }
          }
      }
      throw new InvalidOperationException("Not found");
  }
  int[,] arr = { { 10, 15 }, { 20, 25 } };
  ref var num = ref GetLocalRef(arr, c => c == 20);
  num = 600; 
  Console.WriteLine(arr[1, 0]);  

 總結:雖然 C# 7 中提供了局部引用和引用返回,但爲了防止濫用因此也有諸多約束,如:

 1. 你不能將一個值分配給 ref 變量,如:

1   ref int num = 10;   // error:沒法使用值初始化按引用變量

 2. 你不能返回一個生存期不超過方法做用域的變量引用,如:

1 public ref int GetLocalRef(int num) => ref num;   // error: 沒法按引用返回參數,由於它不是 ref out 參數

 3. ref 不能修飾 「屬性」 和 「索引器」。 

1   var list = new List<int>();2   ref var n = ref list.Count;  // error: 屬性或索引器不能做爲 out ref 參數傳遞

 原理解析:很是簡單就是指針傳遞,而且我的以爲此語法的使用場景很是有限,都是用來處理大對象的,目的是減小GC提升性能。

6.5 局部函數

static IEnumerable<char> GetCharList(string str)
   {
       if (IsNullOrWhiteSpace(str))

           throw new ArgumentNullException(nameof(str));

       return GetList();   

       IEnumerable<char> GetList()
       {
           for (int i = 0; i < str.Length; i++)
           {
               yield return str[i];
           }
       }
   } 

6.6. 擴展異步返回類型(Generalized async return types 

 之前異步的返回類型必須是:Task、Task<T>、void,如今 C# 7 中新增了一種類型:ValueTask<T>,以下所示:

  public async ValueTask<int> Func()
  {
     await Task.Delay(3000);
     return 100;
  }

  總結:ValueTask<T> 與 ValueTuple 很是類似,因此就不列舉: ValueTask<T> 與 Task 之間的異同了,\但它們都是爲了優化特定場景性能而

 新增的類型。  使用 ValueTask<T> 則須要導入:

Install - Package System.Threading.Tasks.Extensions

6.7. 數字文本語法的改進(Numeric literal syntax improvements 

 C# 7 還包含兩個新特性:二進制文字、數字分隔符,以下所示:

var one = 0b0001;
var sixteen = 0b0001_0000;
long salary = 1000_000_000;
decimal pi = 3.141_592_653_589m;

 注:二進制文本是以0b(零b)開頭,字母不區分大小寫;數字分隔符只有三個地方不能寫:開頭,結尾,小數點先後。

 總結:二進制文本,數字分隔符 可以使常量值更具可讀性。

7、異步的優化

  儘管如此,異步方法能夠返回的內容一些小改進,可是能夠在某些狀況下提供巨大的性能提高。 你再也不須要返回一個Task,若是值已經可用這能夠減小開銷,使用async方法來建立Task對象。

8、總結

  在這個介紹性章節中,您看到了一個簡短而高級的摘要,與先前版本相比,.NET Core 2和ASP.NET Core 2衆多變化。

如今,你也知道了.NET Standard 2及其用途。咱們展現了C#6和C#7中可用的一些新功能的例子。

這些可能很是有用的是讓你用更少的東西編寫更多東西,並使你的代碼更易讀和更容易維護。

       《ASP.NET Core 高性能系列》這是一本關於通常Web應用程序性能改進的文章,並且不少無視語言或框架的知識。

  下一章中,您將瞭解性能如何重要,並瞭解嶄新的新.NET Core開發棧, 咱們還將看到可用的工具,並瞭解用圖表展現硬件性能。

相關文章
相關標籤/搜索