<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      NativeBuffering,一種高性能、零內(nèi)存分配的序列化解決方案[性能測(cè)試篇]

      第一版的NativeBuffering[上篇]、[下篇])發(fā)布之后,我又對(duì)它作了多輪迭代,對(duì)性能作了較大的優(yōu)化。比如確保所有類型的數(shù)據(jù)都是內(nèi)存對(duì)齊的,內(nèi)部采用了池化機(jī)器確保真正的“零內(nèi)存分配”等。對(duì)于字典類型的數(shù)據(jù)成員,原來(lái)只是“表現(xiàn)得像個(gè)字段”,這次真正使用一段連續(xù)的內(nèi)存構(gòu)架了一個(gè)“哈希表”。我們知道對(duì)于每次.NET新版本的發(fā)布,原生的JSON序列化(System.Text.Json)的性能都作了相應(yīng)的提升,本篇文章通過(guò)具體的性能測(cè)試比較NativeBuffering和它之間的性能差異。

      一、一種“特別”的序列化解決方案
      二、Source Generator驅(qū)動(dòng)的編程模式
      三、序列化性能比較
      四、原生類型性能“友好”
      五、Unmanaged 類型“性能加速”
      六、無(wú)需反序列化
      七、數(shù)據(jù)讀取的成本

      一、一種“特別”的序列化解決方案

      一般的序列化/發(fā)序列化都是數(shù)據(jù)對(duì)象和序列化結(jié)果(字符串或者單純的字節(jié)序列)之間的轉(zhuǎn)換。以下圖為例,我們定義了一個(gè)名為Person的數(shù)據(jù)類型,如果采用典型的JSON序列化方案,序列化器會(huì)將該對(duì)象轉(zhuǎn)換成一段具有JSON格式的字符串,這段字符串可以通過(guò)反序列化的方式“恢復(fù)”成一個(gè)Person對(duì)象。

      image

      如果采用NativeBuffering序列化解決方案,它會(huì)引入一個(gè)新的數(shù)據(jù)類型PersonBufferedMessage,我們采用Source Generator的方式根據(jù)Person的數(shù)據(jù)結(jié)構(gòu)自動(dòng)生成PersonBufferedMessage類型。除此之外,PersonBufferedMessage還會(huì)為Person生成額外的方式將自身對(duì)象以字節(jié)的方式寫入提供的緩沖區(qū)。

      換句話說(shuō),Person對(duì)象會(huì)轉(zhuǎn)換成一段連續(xù)的字節(jié)序列化,PersonBufferedMessage就是對(duì)這段字節(jié)序列的封裝。它的數(shù)據(jù)成員(Name、Age和City)不再定義成“地段”,而被定義成“只讀屬性”,它能找到對(duì)應(yīng)的數(shù)據(jù)成員在這段字節(jié)序列中的位置,從而將其讀出來(lái)。為了提供數(shù)據(jù)讀取的性能,所有的數(shù)據(jù)成員在序列化字節(jié)序列中總是按照“原生(Native)”的形式存儲(chǔ),并且確保是內(nèi)存對(duì)齊的。也正是這個(gè)原因,NativeBuffering并不是一個(gè)跨平臺(tái)的序列化解決方案。

      二、Source Generator驅(qū)動(dòng)的編程模式

      NativeBuffering的整個(gè)編程圍繞著“Source Generator”進(jìn)行的,接下來(lái)我們簡(jiǎn)單演示一下如何使用它。我們?cè)谝粋€(gè)控制臺(tái)程序中添加NativeBuffering相關(guān)的兩個(gè)NuGet包NativeBuffering和NativeBuffering.Generator(使用最新版本),并定義如下這個(gè)數(shù)據(jù)類型Person。由于我們需要為Person生成額外的類型成員,我們必須將其定義成partial class。

      [BufferedMessageSource]
      public partial class Person
      {
          public string Name { get; set; }
          public int Age { get; set; }
          public string[] Hobbies { get; set; }
          public string Address { get; set; }
          public string PhoneNumber { get; set; }
          public string Email { get; set; }
          public string Gender { get; set; }
          public string Nationality { get; set; }
          public string Occupation { get; set; }
          public string EducationLevel { get; set; }
          public string MaritalStatus { get; set; }
          public string SpouseName { get; set; }
          public int NumberOfChildren { get; set; }
          public string[] ChildrenNames { get; set; }
          public string[] LanguagesSpoken { get; set; }
          public bool HasPets { get; set; }
          public string[] PetNames { get; set; }
      
          public static Person Instance = new Person
          {
              Name = "Bill",
              Age = 30,
              Hobbies = new string[] { "Reading", "Writing", "Coding" },
              Address = "123 Main St.",
              PhoneNumber = "555-555-5555",
              Email = "bill@gmail.com",
              Gender = "M",
              Nationality = "China",
              Occupation = "Software Engineer",
              EducationLevel = "Bachelor's",
              MaritalStatus = "Married",
              SpouseName = "Jane",
              NumberOfChildren = 2,
              ChildrenNames = new string[] { "John", "Jill" },
              LanguagesSpoken = new string[] { "English", "Chinese" },
              HasPets = true,
              PetNames = new string[] { "Fido", "Spot" }
          };
      }

      我們?cè)陬愋蜕蠘?biāo)注BufferedMessageSourceAttribute特性將其作為BufferedMessage的“源”。此時(shí)如果我們查看VS的Solution Explorer,就會(huì)從項(xiàng)目的Depedences/Analyers/NativeBuffering.Generator看到生成的兩個(gè).cs文件。我們使用的PersonBufferedMessage就定義在PersonBufferedMessage.g.cs文件中。為Person額外添加的類型成員就定義在Person.g.cs文件中。

      image

      我們使用下的代碼來(lái)演示針對(duì)Person和PersonBufferedMessage的序列化和反序列化。如下面的代碼片段所示,我們利用Instance靜態(tài)屬性得到Person單例對(duì)象,直接調(diào)用其WriteToAsync方法(Person.g.cs文件會(huì)使Person類型實(shí)現(xiàn)IBufferedObjectSource接口,WriteToAsync方法使針對(duì)該接口定義的擴(kuò)展方法)對(duì)自身進(jìn)行序列化,并將作為序列化結(jié)果的字節(jié)序列存儲(chǔ)到指定的文件(person.bin)文件中。

      using NativeBuffering;
      var fileName = "person.bin";
      await Person.Instance.WriteToAsync(fileName);
      using (var pooledBufferedMessage = await BufferedMessage.LoadAsync<PersonBufferedMessage>(fileName))
      {
          var bufferedMessage = pooledBufferedMessage.BufferedMessage;
          Console.WriteLine(
      @$"{nameof(bufferedMessage.Name),-17}: {bufferedMessage.Name}
      {nameof(bufferedMessage.Age),-17}: {bufferedMessage.Age}
      {nameof(bufferedMessage.Hobbies),-17}: {string.Join(", ", bufferedMessage.Hobbies)}
      {nameof(bufferedMessage.Address),-17}: {bufferedMessage.Address}
      {nameof(bufferedMessage.PhoneNumber),-17}: {bufferedMessage.PhoneNumber}
      {nameof(bufferedMessage.Email),-17}:{bufferedMessage.Email}
      {nameof(bufferedMessage.Nationality),-17}:{bufferedMessage.Nationality},
      {nameof(bufferedMessage.Occupation),-17}:{bufferedMessage.Occupation},
      {nameof(bufferedMessage.EducationLevel),-17}:{bufferedMessage.EducationLevel}
      {nameof(bufferedMessage.MaritalStatus),-17}:{bufferedMessage.MaritalStatus}
      {nameof(bufferedMessage.SpouseName),-17}:{bufferedMessage.SpouseName}
      {nameof(bufferedMessage.NumberOfChildren),-17}:{bufferedMessage.NumberOfChildren}
      {nameof(bufferedMessage.ChildrenNames),-17}: {string.Join(", ", bufferedMessage.ChildrenNames)}
      {nameof(bufferedMessage.LanguagesSpoken),-17}: {string.Join(", ", bufferedMessage.LanguagesSpoken)}
      {nameof(bufferedMessage.HasPets),-17}:{bufferedMessage.HasPets}
      {nameof(bufferedMessage.PetNames),-17}: {string.Join(", ", bufferedMessage.PetNames)}");
      }

      然后我們調(diào)用BufferedMessage的靜態(tài)方法LoadAsync<PersonBufferedMessage>加載該文件的內(nèi)容。該方法會(huì)返回一個(gè)PooledBufferedMessage<PersonBufferedMessage>對(duì)象,它的BufferedMessage返回我們需要的PersonBufferedMessage對(duì)象。PersonBufferedMessage具有與Person一致的數(shù)據(jù)成員,我們將它們的內(nèi)容一一輸出,可以看出PersonBufferedMessage承載的內(nèi)容與Person對(duì)象使完全一致的。

      image

      NativeBuffering之所以能供實(shí)現(xiàn)真正意義的“零內(nèi)存分配”,得益于對(duì)“池化機(jī)制”的應(yīng)用。LoadAsync<T>方法返回的PooledBufferedMessage<T>使用一段池化的緩存區(qū)來(lái)存儲(chǔ)序列化的字節(jié),當(dāng)我們不再使用的時(shí)候,需要調(diào)用其Dispose方法緩存區(qū)釋放到緩存池內(nèi)。

      三、序列化性能比較

      接下來(lái)我們以就以上面定義的Person類型為例,利用BenchmarkDotNet比較一下NativeBuffering與JSON序列化在性能上的差異。如下面的代碼片段所示,針對(duì)JSON序列化的Benchmark方法直接調(diào)用JsonSerializer的Serialize方法將Person單例對(duì)象序列化成字符串。

      [MemoryDiagnoser]
      public class Benchmark
      {
          private  static readonly Func<int, byte[]> _bufferFactory = ArrayPool<byte>.Shared.Rent;
      
          [Benchmark]
          public string SerializeAsJson() => JsonSerializer.Serialize(Person.Instance);
      
          [Benchmark]
          public void SerializeNativeBuffering()
          {
              var arraySegment = Person.Instance.WriteTo(_bufferFactory);
              ArrayPool<byte>.Shared.Return(arraySegment.Array!);
          }
      }

      在針對(duì)NativeBuffering的Benchmark方法中,我們調(diào)用Person單例對(duì)象的WriteTo擴(kuò)展方法對(duì)它進(jìn)行序列化,并利用一個(gè)ArraySegment<T>結(jié)構(gòu)返回序列化結(jié)果。WriteTo方法具有一個(gè)類型為Func<int, byte[]>的參數(shù),我們使用它來(lái)提供一個(gè)存放序列化結(jié)果的字節(jié)數(shù)組。作為Func<int, byte[]>輸入?yún)?shù)的整數(shù)代表序列化結(jié)果的字節(jié)長(zhǎng)度,這樣我們才能確保提供的字節(jié)數(shù)組具有充足的存儲(chǔ)空間。

      為了避免內(nèi)存分配,我們利用這個(gè)委托從ArrayPool<byte>.Shared表示的“數(shù)組池”中借出一個(gè)大小適合的字節(jié)數(shù)組,并在完成序列化之后將其釋放。這段性能測(cè)試結(jié)果如下,可以看出從耗時(shí)來(lái)看,針對(duì)NativeBuffering的序列化稍微多了一點(diǎn),但是從內(nèi)存分配來(lái)看,它真正做到了內(nèi)存的“零分配”,而JSON序列化則分配了1K多的內(nèi)存。

      image

      四、原生類型性能“友好”

      從上面展示的性能測(cè)試結(jié)果可以看出,NativeBuffering在序列化上確實(shí)可以不用分配額外的內(nèi)存,但是耗時(shí)似乎多了點(diǎn)。那么是否意味著NativeBuffering不如JSON序列化高效嗎?其實(shí)也不能這么說(shuō)。NativeBuffering會(huì)使用一段連續(xù)的內(nèi)存(而不是多段緩存的拼接)來(lái)存儲(chǔ)序列化結(jié)果,所以它在序列化之前需要先計(jì)算字節(jié)數(shù)。由于Person定義的絕大部分?jǐn)?shù)據(jù)成員都是字符串,這導(dǎo)致了它需要計(jì)算字符串編碼后的字節(jié)數(shù),這個(gè)計(jì)算會(huì)造成一定的耗時(shí)。

      所以字符串不是NativeBuffering的強(qiáng)項(xiàng),對(duì)于其他數(shù)據(jù)類型,NativeBuffering性能其實(shí)很高的?,F(xiàn)在我們重新定義如下這個(gè)名為Entity的數(shù)據(jù)類型,它將常用的Primitive類型和一個(gè)字節(jié)數(shù)組作為數(shù)據(jù)成員

      [BufferedMessageSource]
      public partial class Entity
      {
          public byte ByteValue { get; set; }
          public sbyte SByteValue { get; set; }
          public short ShortValue { get; set; }
          public ushort UShortValue { get; set; }
          public int IntValue { get; set; }
          public uint UIntValue { get; set; }
          public long LongValue { get; set; }
          public ulong ULongValue { get; set; }
          public float FloatValue { get; set; }
          public double DoubleValue { get; set; }
          public decimal DecimalValue { get; set; }
          public bool BoolValue { get; set; }
          public char CharValue { get; set; }
          public byte[] Bytes { get; set; }
      
          public static Entity Instance = new Entity
          {
              ByteValue = 1,
              SByteValue = 2,
              ShortValue = 3,
              UShortValue = 4,
              IntValue = 5,
              UIntValue = 6,
              LongValue = 7,
              ULongValue = 8,
              FloatValue = 9,
              DoubleValue = 10,
              DecimalValue = 11,
              BoolValue = true,
              CharValue = 'a',
              Bytes = Enumerable.Range(0, 128).Select(it => (byte)it).ToArray()
          };
      }

      然后我們將性能測(cè)試的兩個(gè)Benchmark方法使用的數(shù)據(jù)類型從Person改為Entity。

      [MemoryDiagnoser]
      public class Benchmark
      {
          private static readonly Func<int, byte[]> _bufferFactory = ArrayPool<byte>.Shared.Rent;
      
          [Benchmark]
          public string SerializeAsJson() => JsonSerializer.Serialize(Entity.Instance);
      
          [Benchmark]
          public void SerializeNativeBuffering()
          {
              var arraySegment = Entity.Instance.WriteTo(_bufferFactory);
              ArrayPool<byte>.Shared.Return(arraySegment.Array!);
          }
      }

      再來(lái)看看如下的測(cè)試結(jié)果,可以看出NativeBuffering序列化的耗時(shí)差不多是JSON序列化的一半,并且它依然沒(méi)有任何內(nèi)存分配。

      image

      五、Unmanaged 類型“性能加速”

      NativeBuffering不僅僅對(duì)Primitive類型“友好”,對(duì)于自定義的Unmanaged結(jié)構(gòu),更能體現(xiàn)其性能優(yōu)勢(shì)。原因很簡(jiǎn)單,Unmanaged類型(含Primitive類型和自定義的unmanaged結(jié)構(gòu))的內(nèi)存布局就是連續(xù)的,NativeBuffering在進(jìn)行序列化的適合不需要對(duì)它進(jìn)行“分解”,直接拷貝這段內(nèi)存的內(nèi)容就可以了。

      作為演示,我們定義了如下這個(gè)Foobarbazqux結(jié)構(gòu)體,可以看出它滿足unmanaged結(jié)構(gòu)的要求。作為序列化數(shù)據(jù)類型的Record中,我們定義了一個(gè)Foobarbazqux數(shù)組類型的屬性Data。Instance靜態(tài)字段表示的單例對(duì)象的Data屬性包含100個(gè)Foobarbazqux對(duì)象。

      [BufferedMessageSource]
      public partial class Record
      {
          public Foobarbazqux[] Data { get; set; } = default!;
          public static Record Instance = new Record {  Data = Enumerable.Range(1, 100).Select(_ => new Foobarbazqux(new Foobarbaz(new Foobar(111, 222), 1.234f), 3.14d)).ToArray()};
      }
      
      public readonly record struct Foobar(int Foo, long Bar);
      public readonly record struct Foobarbaz(Foobar Foobar, float Baz);
      public readonly record struct Foobarbazqux(Foobarbaz Foobarbaz, double Qux);

      我們同樣只需要將性能測(cè)試的數(shù)據(jù)類型改成上面定義的Record就可以了。

      [MemoryDiagnoser]
      public class Benchmark
      {
          private static readonly Func<int, byte[]> _bufferFactory = ArrayPool<byte>.Shared.Rent;
      
          [Benchmark]
          public string SerializeAsJson() => JsonSerializer.Serialize(Record.Instance);
      
          [Benchmark]
          public void SerializeNativeBuffering()
          {
              var arraySegment = Record.Instance.WriteTo(_bufferFactory);
              ArrayPool<byte>.Shared.Return(arraySegment.Array!);
          }
      }

      這次NativeBuffering針對(duì)JSON序列化的性能優(yōu)勢(shì)完全是“碾壓式”的。耗時(shí):72us/3us。JSON序列化不僅帶來(lái)了26K的內(nèi)存分配,還將部分內(nèi)存提升到了Gen1。

      image

      六、無(wú)需反序列化

      對(duì)于序列化來(lái)說(shuō),NativeBuffering不僅僅可以避免內(nèi)存的分配。如果不是大規(guī)模涉及字符串,它在耗時(shí)方面依然具有很大的優(yōu)勢(shì)。即使大規(guī)模使用字符串,考慮到JSON字符串最終還是需要編碼轉(zhuǎn)換成字節(jié)序列化,兩者之間的總體耗時(shí)其實(shí)差別也不大。NativeBuffering針對(duì)反序列化的性能優(yōu)勢(shì)更是毋庸置疑,因?yàn)槲覀兪褂玫腂ufferedMessage就是對(duì)序列化結(jié)果的封裝,所以反序列化的成本幾乎可以忽略(經(jīng)過(guò)測(cè)試耗時(shí)在幾納秒)。

      為了讓大家能夠感覺(jué)到與JSON分序列化的差異,我們將讀取數(shù)據(jù)成員的操作也作為反序列化的一部分。如下面這個(gè)Benchmark所示,我們?cè)诔跏蓟詣?dòng)執(zhí)行的Setup方法中,針對(duì)同一個(gè)Entity對(duì)象的兩種序列化結(jié)果(字節(jié)數(shù)組)存儲(chǔ)在_encodedJson 和_payload字段中。

      [MemoryDiagnoser]
      
      public class Benchmark
      {
          private  byte[] _encodedJson = default!;
          private  byte[] _payload = default!;
      
          [GlobalSetup]
          public void Setup()
          {
              _encodedJson = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(Entity.Instance));
              _payload = new byte[Entity.Instance.CalculateSize()];
              Person.Instance.WriteToAsync(new MemoryStream(_payload), true);
          }
      
          [Benchmark]
          public void DeserializeFromJson()
          {
              var entity = JsonSerializer.Deserialize<Entity>(Encoding.UTF8.GetString(_encodedJson))!;
              Process(entity.ByteValue);
              Process(entity.SByteValue);
              Process(entity.ShortValue);
              Process(entity.UShortValue);
              Process(entity.IntValue);
              Process(entity.UIntValue);
              Process(entity.LongValue);
              Process(entity.ULongValue);
              Process(entity.FloatValue);
              Process(entity.DoubleValue);
              Process(entity.DecimalValue);
              Process(entity.BoolValue);
              Process(entity.CharValue);
              Process(entity.Bytes);
          }
      
          [Benchmark]
          public void DeserializeFromNativeBuffering()
          {
              unsafe
              {
                  fixed (byte* _ = _payload)
                  {
                      var entity = new EntityBufferedMessage(new NativeBuffer(_payload));
                      Process(entity.ByteValue);
                      Process(entity.SByteValue);
                      Process(entity.ShortValue);
                      Process(entity.UShortValue);
                      Process(entity.IntValue);
                      Process(entity.UIntValue);
                      Process(entity.LongValue);
                      Process(entity.ULongValue);
                      Process(entity.FloatValue);
                      Process(entity.DoubleValue);
                      Process(entity.DecimalValue);
                      Process(entity.BoolValue);
                      Process(entity.CharValue);
                      Process(entity.Bytes);
                  }
              }
          }
      
          [MethodImpl(MethodImplOptions.NoInlining)]
          private void Process<T>(T expected)
          { }
      }

      針對(duì)JSON反序列化的Benchmark方法利用JsonSerializer將解碼生成的字符串反序列化成Entity對(duì)象,并調(diào)用Process方法讀取每個(gè)數(shù)據(jù)成員。在針對(duì)NativeBuffering的Benchmark方法中,我們需要?jiǎng)?chuàng)建一個(gè)fixed上下文將字節(jié)數(shù)組內(nèi)存地址固定,因?yàn)锽ufferedMessage的讀取涉及很多Unsafe的內(nèi)存地址操作,然后將這個(gè)字節(jié)數(shù)組封裝成NativeBuffer對(duì)象,并據(jù)此將EntityBufferedMessage創(chuàng)建出來(lái)。這個(gè)方法的耗時(shí)花在后面針對(duì)數(shù)據(jù)成員的讀取上。如下所示的兩種“反序列”方式的測(cè)試結(jié)果。從如下所示的測(cè)試結(jié)果可以看出相對(duì)于NativeBuffering的無(wú)需反序列化,JSON反序列化的成本還是巨大的,不僅反映在耗時(shí)上,同時(shí)也反映在內(nèi)存分配上。

      image

      七、數(shù)據(jù)讀取的成本

      上面的測(cè)試結(jié)果也體現(xiàn)了NativeBuffering針對(duì)數(shù)據(jù)讀取的成本。和普通類型直接讀取字段的值不同,NativeBuffering生成的BufferedMessage對(duì)象是對(duì)一段連續(xù)字節(jié)序列的封裝,此字節(jié)序列就是序列化的結(jié)果。如下所示的是這段字節(jié)序列的布局:整個(gè)序列包括兩個(gè)部分,后面一部分依次存儲(chǔ)每個(gè)字段的內(nèi)容,前面一部分則存儲(chǔ)每個(gè)字段內(nèi)容在整個(gè)字節(jié)序列的位置(偏移量)。

      image

      BufferedMessage的每個(gè)數(shù)據(jù)成員都是只讀屬性,針對(duì)數(shù)據(jù)成員的讀取至少需要兩個(gè)步驟:

      • 根據(jù)數(shù)據(jù)成員的序號(hào)讀取存儲(chǔ)內(nèi)容的偏移量;
      • 將偏移量轉(zhuǎn)換成內(nèi)存地址,結(jié)合當(dāng)前數(shù)據(jù)類型將數(shù)據(jù)讀出來(lái);

      所以NativeBuffering最大的問(wèn)題就是:讀取數(shù)據(jù)成員的性能肯定比直接讀取字段值要高。從上面的測(cè)試結(jié)果大體可以測(cè)出單次讀取耗時(shí)大體在1-2納米之間(24.87ns包括創(chuàng)建EntityBufferedMessage和調(diào)用空方法Process的耗時(shí)),也就是說(shuō)1秒中可以完成5-10億次讀取。我想這個(gè)讀取成本大部分應(yīng)用是可以接受的,尤其是相對(duì)于它在序列化/反序列化在耗時(shí)和內(nèi)存分配帶來(lái)的巨大優(yōu)勢(shì)來(lái)說(shuō),讀取數(shù)據(jù)成員帶來(lái)時(shí)間損耗基本上可以忽略了。


      NativeBuffering針對(duì)字符串序列化的性能在最新版本中已經(jīng)得到提升,并完全超越了System.Text.Json序列化的性能,具體的性能測(cè)試結(jié)果和背后的原理可以參閱《性能測(cè)試?yán)m(xù)篇》。

      posted @ 2023-11-02 09:46  Artech  閱讀(3091)  評(píng)論(26)    收藏  舉報(bào)
      主站蜘蛛池模板: 日韩人妻无码精品专区综合网| 深夜av免费在线观看| 精品国产AⅤ无码一区二区| 人妻蜜臀久久av不卡| 成人综合人人爽一区二区| 亚洲日韩精品无码一区二区三区| 好吊视频一区二区三区| 久青草精品视频在线观看| 日韩淫片毛片视频免费看| 在线看免费无码的av天堂| 美女禁区a级全片免费观看| 狠狠色婷婷久久综合频道日韩| 97无码人妻福利免费公开在线视频| 国产精品无码av不卡| 色呦呦九九七七国产精品| 亚洲中文一区二区av| 少妇特黄a一区二区三区| brazzers欧美巨大| 蜜臀av一区二区国产精品| 亚洲无av在线中文字幕| 亚洲国产精品久久无人区| 高清自拍亚洲精品二区| 五月天天天综合精品无码| 亚洲精品无码av天堂| 中文字幕在线视频不卡一区二区 | 久久精品人人看人人爽| 国产一区二区三区黄色片| 人妻熟女一区无中文字幕| 清水河县| 国产一区二区不卡在线| 又黄又刺激又黄又舒服| 精品午夜福利在线观看| 日本久久99成人网站| 亚洲热妇无码av在线播放| 久久亚洲国产精品五月天| 最新国产精品亚洲| 久青草国产在视频在线观看 | 国产精品无码无需播放器| 亚洲国产精品毛片在线看| 亚洲伊人久久精品影院| 91九色国产成人久久精品|