精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

速度追求:Objective-C高性能的循環

開發 后端
Cocoa編程的一個通常的任務是要去循環遍歷一個對象的集合 (例如,一個 NSArray, NSSet 或者是 NSDictionary). 這個看似簡單的問題有廣泛數量的解決方案,它們中的許多不乏有對性能方面問題的細微考慮.

Cocoa編程的一個通常的任務是要去循環遍歷一個對象的集合 (例如,一個 NSArray, NSSet 或者是 NSDictionary). 這個看似簡單的問題有廣泛數量的解決方案,它們中的許多不乏有對性能方面問題的細微考慮.

對于速度的追求

首先,是一個免責聲明: 相比其它問題而言,一個 Objective-C 方法原始的速度是你在編程時***才需要考慮的問題之一 – 區別就在于這個問題夠不上去同其它更加需要重點考慮的問題進行比較,比如說代碼的清晰度和可讀性.

但速度的次要性并不妨礙我們去理解它. 你應該經常去了解一下性能方面的考慮將如何對你正在編寫的代碼產生影響,一邊在極少數發生問題的情況下,你會知道如何下手.

還有,在循環的場景中,大多數時候不管是從可讀性或者是清晰度考慮,你選擇哪種技術都沒什么關系的, 所以你還不如選擇速度最快的那一種. 沒有必要選擇編碼速度比要求更慢的。

考慮到這一點,就有了如下的選擇:

經典的循環方式

  1. for (NSUInteger i = 0; i < [array count]; i++){  
  2.   id object = array[i];  
  3.   …} 

這是循環遍歷一個數組的一個簡單熟悉的方式; 從性能方面考慮它也相當的差勁. 這段代碼***的問題就是循環每進行一次我們都會調用數組的計數方法. 數組的總數是不會改變的,因此每次都去調用一下這種做法是多余的. 像這種代碼一般C編譯器一般都會優化掉, 但是 Objective-C 的動態語言特性意味著對這個方法的調用不會被自動優化掉. 因此,為了提升性能,值得我們在循環開始之前,將這個總數存到一個變量中,像這樣:

  1. NSUInteger count = [array count];for (NSUInteger i = 0; i < count; i++){  
  2.   id object = array[i];  
  3.   …} 

NSEnumerator

NSEnumerator 是循環遍歷集合的一種可選方式. 所有的集合都已一個或者更多個枚舉方法,每次它們被調用的時候都會返回一個NSEnumerator實體. 一個給定的 NSEnumerator 會包含一個指向集合中***個對象的指針, 并且會有一個 nextObject 方法返回當前的對象并對指針進行增長. 你可以重復調用它直到它返回nil,這表明已經到了集合的末尾了:

  1. id obj = nil;NSEnumerator *enumerator = [array objectEnumerator];while ((obj = [enumerator nextObject]));{  
  2.   …            

NSEnumerator 的性能可以媲美原生的for循環, 但它更加實用,因為它對索引的概念進行了抽象,這意味著它應用在結構化數據上,比如鏈表,或者甚至是無窮序列和數據流,這些結構中的數據條數未知或者并沒有被定義.

快速枚舉

快速枚舉是在 Objective-C 2.0 中作為傳統的NSEnumerator的更便利(并且明顯更快速) 的替代方法而引入的. 它并沒有使得枚舉類過時因為其仍然被應用于注入反向枚舉, 或者是當你需要對集合進行變更操作 (之后會更多地提到) 這些場景中.
快速枚舉添加了一個看起來像下面這樣子的新的枚舉方法:

  1. - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state   
  2.    objects:(id *)stackbuf count:(NSUInteger)len; 

如果你正在想著“那看起來并不怎么舒服啊!”, 我不會怪你的. 但是新的方法順便帶來了一種新的循環語法, for…in 循環. 這是在幕后使用了新的枚舉方法, 并且重要的是在語法和性能上都比使用傳統的for循環或者 NSEnumerator 方法都更省心了:

  1. for (id object in array){  
  2.   …} 

枚舉塊

隨著塊的誕生,Apple加入第四個基于塊語法的枚舉機制. 這無疑比快速枚舉更加的少見, 但是有一個優勢就是對象和索引都會返回, 而其他的枚舉方法只會返回對象.

枚舉塊的另外一個關鍵特性就是可選擇型的并發枚舉 (在幾個并發的線程中枚舉對象). 這不是經常有用,取決于你在自己的循環中具體要做些什么, 但是在你正有許多工作要做,并且你并不怎么關心枚舉順序的場景下,它在多核處理器上可能會產生顯著的性能提高 (現在所有的 Mac和iOS設備都已經有了多核處理器).

基準測試

那么這些方法疊加起來會如何呢, 性能會更加的好么? 這里有一個簡單的基準測試命令行應用,比較了使用多種不同方法枚舉一個數據的性能. 我們已經在 ARC 關閉的情況下運行了它,以排除任何干擾最終結果的隱藏在幕后的保留或者排除處理. 由于是運行在一個很快的 Mac 機上面, 所有這些方法運行極快以至于我們實際上不得不使用一個存有10,000,000 (一千萬) 對象的數組來測量結果. 如果你決定在一個 iPhone 進行測試, 最明智的做法是使用一個小得多的數量!

為了編譯這段代碼:

  • 把代碼保存在一個文件中,命名為 benchmark.m

  • 在終端中編譯應用程序:
    clang -framework Foundation benchmark.m -o benchmark

  • 運行程序: ./benchmark

  1. #import <Foundation/Foundation.h> int main(int argc, const char * argv[]){  
  2.   @autoreleasepool  {  
  3.     static const NSUInteger arrayItems = 10000000;  
  4.      NSMutableArray *array = [NSMutableArray arrayWithCapacity:arrayItems];    for (int i = 0; i < arrayItems; i++) [array addObject:@(i)];  
  5.     array = [array copy];  
  6.     
  7.     CFTimeInterval start = CFAbsoluteTimeGetCurrent();  
  8.      // Naive for loop  
  9.     for (NSUInteger i = 0; i < [array count]; i++)  
  10.     {  
  11.       id object = array[i];    }   
  12.     CFTimeInterval forLoop = CFAbsoluteTimeGetCurrent();  
  13.     NSLog(@"For loop: %g", forLoop - start);  
  14.      // Optimized for loop  
  15.     NSUInteger count = [array count];    for (NSUInteger i = 0; i <  count; i++)  
  16.     {  
  17.       id object = array[i];    }   
  18.     CFTimeInterval forLoopWithCountVar = CFAbsoluteTimeGetCurrent();  
  19.     NSLog(@"Optimized for loop: %g", forLoopWithCountVar - forLoop);  
  20.      // NSEnumerator  
  21.     id obj = nil;    NSEnumerator *enumerator = [array objectEnumerator];    while ((obj = [enumerator nextObject]))  
  22.     {     }   
  23.     CFTimeInterval enumeratorLoop = CFAbsoluteTimeGetCurrent();  
  24.     NSLog(@"Enumerator: %g", enumeratorLoop - forLoopWithCountVar);  
  25.      // Fast enumeration  
  26.     for (id object in array)  
  27.     {     }   
  28.     CFTimeInterval forInLoop = CFAbsoluteTimeGetCurrent();  
  29.     NSLog(@"For…in loop: %g", forInLoop - enumeratorLoop);  
  30.      // Block enumeration  
  31.     [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {     }];  
  32.     
  33.     CFTimeInterval enumerationBlock = CFAbsoluteTimeGetCurrent();  
  34.     NSLog(@"Enumeration block: %g", enumerationBlock - forInLoop);  
  35.      // Concurrent enumeration  
  36.     [array enumerateObjectsWithOptions:NSEnumerationConcurrent   
  37.       usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {     }];  
  38.     
  39.     CFTimeInterval concurrentEnumerationBlock = CFAbsoluteTimeGetCurrent();  
  40.     NSLog(@"Concurrent enumeration block: %g",   
  41.       concurrentEnumerationBlock - enumerationBlock);  }  
  42.   return 0;} 

下面展示出了結果:

  1. $ For loop: 0.119066  
  2. $ Optimized for loop: 0.092441  
  3. $ Enumerator: 0.123687  
  4. $ For…in loop: 0.049296  
  5. $ Enumeration block: 0.295039  
  6. $ Concurrent enumeration block: 0.199684 

忽略掉時間的具體長短. 我們感興趣的是它們同其它方法比較的相對大小. 如果我們按順序排列它們,快的放前面,我會得到了下面的結果:

  1. For…in循環 – 最快.

  2. 對for循環的優化 – 比 for…in 慢兩倍.

  3. 沒有優化的for循環 – 比 for…in 慢2.5倍.

  4. Enumerator – 大約同沒有優化的循環相同.

  5. 并發的枚舉塊 – 比 for…in 大約慢6倍.

  6. 枚舉塊 – 比 for…in 幾乎慢6倍.

For…in 是勝出者. 顯然他們將其稱為快速枚舉是有原因的! 并發枚舉看起來是比單線程的快一點點, 但是你沒必要對其做更多的解讀: 我們這里是在枚舉一個非常非常大型的對象數組,而對于小一些的數據并發執行的開銷遠多于其帶來的好處.

并發執行的主要是在當你的循環需要大量的執行時間時有優勢. 如果你在自己的循環中有許多東西要運行,那就考慮試下并行枚舉,在你不關心枚舉順序的前提下 (但是請用行動的去權衡一下它是否變得更快樂,不要空手去揣度).

#p#

其它集合類型Other Collection Types

那么其它的結合類型怎么樣呢, 比如 NSSet 和 NSDictionary? NSSet 是無序的, 因此沒有按索引去取對象的概念.我們也可以進行一下基準測試:

  1. $ Enumerator: 0.421863  
  2. $ For…in loop: 0.095401  
  3. $ Enumeration block: 0.302784  
  4. $ Concurrent enumeration block: 0.390825 

結果同 NSArray 一致; for…in 再一次勝出了. NSDictionary怎么樣了? NSDictionary 有一點不同因為我們同時又一個鍵和值對象需要迭代. 在一個字典中單獨迭代鍵或者值是可以的, 但典型的情況下我們兩者都需要. 這里我們有一段適配于操作NSDictionary的基準測試代碼:

  1. #import <Foundation/Foundation.h> int main(int argc, const char * argv[]){  
  2.   @autoreleasepool  {  
  3.     static const NSUInteger dictItems = 10000;  
  4.      NSMutableDictionary *dictionary =   
  5.       [NSMutableDictionary dictionaryWithCapacity:dictItems];    for (int i = 0; i < dictItems; i++) dictionary[@(i)] = @(i);  
  6.     dictionary = [dictionary copy];  
  7.     
  8.     CFTimeInterval start = CFAbsoluteTimeGetCurrent();  
  9.      // Naive for loop  
  10.     for (NSUInteger i = 0; i < [dictionary count]; i++)  
  11.     {  
  12.       id key = [dictionary allKeys][i];      id object = dictionary[key];    }   
  13.     CFTimeInterval forLoop = CFAbsoluteTimeGetCurrent();  
  14.     NSLog(@"For loop: %g", forLoop - start);  
  15.      // Optimized for loop  
  16.     NSUInteger count = [dictionary count];    NSArray *keys = [dictionary allKeys];    for (NSUInteger i = 0; i <  count; i++)  
  17.     {  
  18.       id key = keys[i];      id object = dictionary[key];    }   
  19.     CFTimeInterval forLoopWithCountVar = CFAbsoluteTimeGetCurrent();  
  20.     NSLog(@"Optimized for loop: %g", forLoopWithCountVar - forLoop);  
  21.      // NSEnumerator  
  22.     id key = nil;    NSEnumerator *enumerator = [dictionary keyEnumerator];    while ((key = [enumerator nextObject]))  
  23.     {  
  24.       id object = dictionary[key];    }   
  25.     CFTimeInterval enumeratorLoop = CFAbsoluteTimeGetCurrent();  
  26.     NSLog(@"Enumerator: %g", enumeratorLoop - forLoopWithCountVar);  
  27.      // Fast enumeration  
  28.     for (id key in dictionary)  
  29.     {  
  30.       id object = dictionary[key];    }   
  31.     CFTimeInterval forInLoop = CFAbsoluteTimeGetCurrent();  
  32.     NSLog(@"For…in loop: %g", forInLoop - enumeratorLoop);  
  33.      // Block enumeration  
  34.     [dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {     }];  
  35.     
  36.     CFTimeInterval enumerationBlock = CFAbsoluteTimeGetCurrent();  
  37.     NSLog(@"Enumeration block: %g", enumerationBlock - forInLoop);  
  38.      // Concurrent enumeration  
  39.     [dictionary enumerateKeysAndObjectsWithOptions:NSEnumerationConcurrent   
  40.       usingBlock:^(id key, id obj, BOOL *stop) {     }];  
  41.     
  42.     CFTimeInterval concurrentEnumerationBlock = CFAbsoluteTimeGetCurrent();  
  43.     NSLog(@"Concurrent enumeration block: %g",   
  44.       concurrentEnumerationBlock - enumerationBlock);  }  
  45.   return 0;}  

NSDictionary 填充起來比 NSArray 或者 NSSet 慢得多, 因此我們把數據條數減少到了10,000 (一萬) 以避免機器鎖住. 因而你應該忽略結果怎么會比那些 NSArray 低那么多,因為我們使用的是更少對象的 1000 次循環:

  1. $ For loop: 2.25899  
  2. $ Optimized for loop: 0.00273103  
  3. $ Enumerator: 0.00496799  
  4. $ For…in loop: 0.001041  
  5. $ Enumeration block: 0.000607967  
  6. $ Concurrent enumeration block: 0.000748038 

沒有優化過的循環再這里慢得很壯觀,因為每一次我們都復制了鍵數組. 通過把鍵數組和總數存到變量中,我們獲得了更快的速度. 查找對象的消耗現在主宰了其它的因素,因此使用一個for循環, NSEnumerator 或者for…in 差別很小. 但是對于枚舉塊方法而言,它在一個方法中把鍵和值都返回了,所以現在變成了最快的選擇。

反轉齒輪

基于我們所見,如果所有其它的因素都一樣的話,在循環遍歷數組時你應該嘗試去使用for...in循環, 而遍歷字典時,則應該選擇枚舉塊. 也有一些場景下這樣的做法并不可能行得通,比如我們需要回頭來進行枚舉,或者當我們在遍歷時想要變更集合的情況.
為了回過頭來枚舉一個數據,我們可以調用reverseObjectEnumerator方法來獲得一個NSEnumerator 以從尾至頭遍歷數組. NSEnumerator, 就像是 NSArray 它自己, 支持快速的枚舉協議. 那就意味著我們仍然可以在這種方式下使用 for…in, 而無速度和簡潔方面的損失:

  1. for (id object in [array reverseObjectEnumerator])   
  2. {  
  3. …  } 

(除非你異想天開, NSSet 或者 NSDictionary 是沒有等效的方法的, 而反向枚舉一個 NSSet 或者NSDictionary無論如何都沒啥意義, 因為鍵是無序的.)

如果你想使用枚舉塊的話, NSEnumerationReverse你可以試試, 像這樣:

  1. [array enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {  
  2.   …  }]; 

變更Mutation

應用同樣的循環技術到變更中的集合上是可能的; 其性能也大致相同. 然而當你嘗試在循環數組或者字典的時候修改它們,你可能經常會面臨這樣的異常:

  1. '*** Collection XYZ was mutated while being enumerated.' 

就像我們優化了的for循環, 所有這些循環技術的性能取決于事先把數據總數存下來,這意味著如果你開始在循環中間加入或者去掉一個數據時,這個數據就不正確了. 但是在循環進行中加入,替換或者移除一條數據時經常想要做的事情. 那么什么才是這個問題的解決之道呢?

我們經典的for循環可以工作得很好,因為它不依賴于駐留的總數常量; 我們只需要記得,如果我們添加或者移除了一條數據,就要增加或者減小索引. 但我們已經了解到for循環并不是一種速度快的解決方案. 我們優化過的for循環則是一個合理的選擇, 只要我們記得按需遞增或者遞減技術變量,還有索引.

我們仍然可以使用for…in, 但前提是我們首先創建了一個數組的拷貝. 這會起作用的,例如:

  1. for (id object in [array copy])   
  2.  {  
  3.    // Do something that modifies the array, e.g. [array removeObject:object];  
  4.  } 

如果我們對不同的技術進行基準測試(必要時把復制數組的開銷算在內,以便我們可以對原來數組內的數據進行變更), 我們發現復制抵消了 for…in 循環之前所擁有的好處:

  1. $ For loop: 0.111422  
  2. $ Optimized for loop: 0.08967  
  3. $ Enumerator: 0.313182  
  4. $ For…in loop: 0.203722  
  5. $ Enumeration block: 0.436741  
  6. $ Concurrent enumeration block: 0.388509 

在我們遍歷一個數組時修改這個數組最快的計數,似乎是需要使用一個優化了的for循環的.

對于一個 NSDictionary, 我們不需要為了使用NSEnumerator 或者快速枚舉而復制整個字典; 我們可以只去使用allKeys方法獲取到所有鍵的一個副本. 這都將能很好的運作起來:

  1. // NSEnumerator  
  2.   id key = nil;  NSEnumerator *enumerator = [[items allKeys] objectEnumerator];  while ((key = [enumerator nextObject]))  
  3.   {  
  4.     id object = items[key];    // Do something that modifies the value, e.g. dictionary[key] = newObject;  
  5.   }   // Fast enumeration  
  6.   for (id key in [dictionary allkeys])   
  7.   {  
  8.     id object = items[key];    // Do something that modifies the value, e.g. dictionary[key] = newObject;  
  9.   } 

然而同樣的技術在使用enumerateKeysAndObjectsUsingBlock方法時并不能起作用. 如果我們循環遍歷一個字典進行基準測試, 按照需要對鍵或者對字典整體創建備份,我們得到了下面的結果:

  1. $ For loop: 2.24597  
  2. $ Optimized for loop: 0.00282001  
  3. $ Enumerator: 0.00508499  
  4. $ For…in loop: 0.000990987  
  5. $ Enumeration block: 0.00144804  
  6. $ Concurrent enumeration block: 0.00166804 

這里我們可以看到 for…in 循環是最快的一個. 那是因為在for...in循環中根據鍵取對象的開銷現在已經被在調用枚舉塊方法之前復制字典的開銷蓋過去了.

當枚舉一個NSArray的時候:

  • 使用 for (id object in array) 如果是順序枚舉

  • 使用 for (id object in [array reverseObjectEnumerator]) 如果是倒序枚舉

  • 使用 for (NSInteger i = 0; i < count; i++) 如果你需要知道它的索引值,或者需要改變數組

  • 嘗試 [array enumerateObjectsWithOptions:usingBlock:] 如果你的代碼受益于并行執行

當枚舉一個NSSet的時候:

  • 使用  for (id object in set) 大多數時候

  • 使用 for (id object in [set copy]) 如果你需要修改集合(但是會很慢)

  • 嘗試 [array enumerateObjectsWithOptions:usingBlock:] 如果你的代碼受益于并行執行

當枚舉一個NSDictionary的時候:

  • 使用  for (id object in set) 大多數時候

  • 使用 for (id object in [set copy]) 如果你需要修改詞典

  • 嘗試 [array enumerateObjectsWithOptions:usingBlock:] 如果你的代碼受益于并行執行

這些方法可能不是最快的,但他們都是非常清晰易讀的。所以請記住,有時是在不寫干凈的代碼,和快速的代碼之間做出選擇,你會發現,你可以在兩個世界得到***的。

英文原文:Tips for High Performance Collection Looping in Objective-C

譯文鏈接:http://www.oschina.net/translate/high-performance-collection-looping-objective-c

責任編輯:林師授 來源: 中國開源社區編譯
相關推薦

2011-08-10 18:07:29

Objective-C反射

2013-03-27 12:54:00

iOS開發Objective-C

2013-06-20 10:40:32

Objective-C實現截圖

2011-05-11 15:58:34

Objective-C

2011-05-11 11:20:26

Objective-C

2014-11-25 10:18:17

Objective-C

2014-07-29 09:44:35

2013-04-11 13:41:30

Objective-CiOS編程

2011-08-04 11:15:46

Objective-C 構造函數 構造方法

2011-05-11 13:54:08

Objective-C

2011-05-11 14:06:49

Objective-C

2011-05-11 15:45:50

內存管理Objective-C

2011-08-04 14:58:37

Objective-C Cocoa NSString

2013-08-21 14:57:42

objective-c問題

2011-08-02 13:16:36

Objective-C 語法 函數

2011-07-08 13:49:46

Objective-C UUID

2011-08-17 10:58:59

Objective-C構造函數

2012-03-07 13:43:59

Objective-C

2011-08-03 16:55:05

Objective-C 代理

2011-07-29 16:16:30

Objective-c block
點贊
收藏

51CTO技術棧公眾號

亚洲福利国产| 亚洲不卡视频| 国产精品高潮久久久久无| 91免费人成网站在线观看18| 久久久久久久久艹| 亚洲精品国产动漫| 欧美久久婷婷综合色| 久久av综合网| av在线免费观看网站| 国产成人免费视频精品含羞草妖精| 午夜精品久久17c| youjizz亚洲女人| 亚洲无线观看| 欧美伊人久久久久久久久影院| 中文字幕中文字幕在线中一区高清| 欧美性受xxxx狂喷水| 日韩高清在线电影| 97国产精品人人爽人人做| 99久久99久久精品免费看小说.| 亚洲第一二区| 欧美人狂配大交3d怪物一区| 人妻熟妇乱又伦精品视频| 麻豆传媒在线完整视频| 99国产精品99久久久久久| 成人有码在线播放| 国产一区二区视频免费| 在线日韩视频| 欧美成人精品在线| 亚洲欧美日韩第一页| 日韩成人午夜| 精品欧美黑人一区二区三区| 一路向西2在线观看| 一区一区三区| 香蕉影视欧美成人| 2022中文字幕| 黄色网址在线免费播放| 国产欧美一区二区精品秋霞影院| 黑人另类av| 农村少妇久久久久久久| 国产麻豆成人精品| 国产日本欧美视频| 日韩中文字幕高清| 午夜亚洲性色视频| 97在线看福利| 国产一级久久久| 欧美一区成人| 欧美成人免费在线观看| 久久99久久99精品免费看小说| 欧洲美女日日| 亚洲小视频在线| 91中文字幕永久在线| 西瓜成人精品人成网站| 亚洲国产中文字幕久久网| 欧美成人精品一区二区综合免费| 欧美一区一区| 日韩午夜激情电影| 一级黄色片在线免费观看| 亚洲人成网站在线在线观看| 欧美久久久影院| 日韩在线一区视频| 国产精品亚洲一区二区在线观看| 69av一区二区三区| 国产精品嫩草影视| 亚洲日本视频在线| 亚洲第一在线视频| 久久久午夜精品福利内容| 国产伦精品一区二区三区在线播放| 精品国产制服丝袜高跟| 娇妻高潮浓精白浆xxⅹ| 乱亲女h秽乱长久久久| 亚洲精品97久久| 成人免费网站黄| 成人亚洲一区| 久久高清视频免费| 日本少妇性高潮| 巨乳诱惑日韩免费av| 国产精品亚洲片夜色在线| 国产精品毛片一区视频播| 国产传媒日韩欧美成人| 狠狠久久综合婷婷不卡| 国产精品视频二区三区| 亚洲女爱视频在线| 黄页网站大全在线观看| 欧美xxx网站| 在线电影院国产精品| 国产无套精品一区二区三区| 久久精品色播| 色七七影院综合| 男女免费视频网站| 久久精品午夜| 91精品视频在线| 五月婷婷六月丁香综合| 国产精品久久看| 成人免费a级片| 日韩精品影院| 精品免费99久久| 亚洲国产天堂av| 欧美亚韩一区| 国产精品丝袜高跟| 亚洲成熟女性毛茸茸| 久久久久久久久久看片| 中文字幕在线中文| 日本欧美日韩| 精品精品欲导航| 亚洲色图27p| 国产日韩欧美一区| 亚洲aⅴ日韩av电影在线观看| 天天干天天草天天射| ㊣最新国产の精品bt伙计久久| 青草青青在线视频| 亚洲高清影院| 国产亚洲激情视频在线| 久久免费视频播放| 久久精品国产一区二区| 久久99精品久久久水蜜桃| 国产理论在线观看| 欧美性videosxxxxx| 黄色短视频在线观看| 欧美日韩一区二区国产| 国产精品三级美女白浆呻吟| 视频午夜在线| 亚洲动漫第一页| 亚欧精品在线视频| 大片网站久久| 国产成人a亚洲精品| 天堂在线视频观看| 亚洲专区一二三| 亚洲高清在线不卡| 欧美韩日一区| 国产精品丝袜视频| 精品999视频| 一本一道综合狠狠老| 加勒比精品视频| 精品1区2区3区4区| 国产91一区二区三区| www在线免费观看视频| 欧美情侣在线播放| 人人妻人人藻人人爽欧美一区| 日韩视频二区| 国产经品一区二区| 欧美性爽视频| 精品久久免费看| 久久久久久国产精品免费播放| 国内精品久久久久影院色| 一卡二卡3卡四卡高清精品视频| japanese23hdxxxx日韩| 国产一区二区三区在线观看网站 | 亚洲第一页在线观看| 国产精品不卡在线| 色婷婷一区二区三区av免费看| 不卡一区2区| 国产精品美女久久| 69视频在线观看| 欧美日韩你懂的| 日韩精品久久久久久久的张开腿让| 爽好久久久欧美精品| 日韩精品一区二区三区丰满| 精品亚洲美女网站| 中文字幕日韩高清| 国产精品一区二区免费视频| 亚洲乱码国产乱码精品精的特点 | 日日骚av一区| 国产精品国产三级国产aⅴ| 最新国产精品久久精品| 午夜激情视频网| 好看的日韩av电影| 久久99精品久久久久久久久久| 中文在线8资源库| 中文字幕视频在线免费欧美日韩综合在线看 | 成人国产免费电影| 精品日韩一区二区| 九九热在线视频播放| 久久精品欧美日韩精品| 国产aⅴ爽av久久久久| 狠久久av成人天堂| 欧美午夜欧美| 中文字幕免费高清网站| 亚洲怡红院av| 久久天天久久| 日韩中文视频免费在线观看| 国产色综合视频| 亚洲成人av一区二区三区| 国产偷人妻精品一区| 免费的成人av| 精品国偷自产一区二区三区| 免费成人结看片| 成人自拍性视频| 天堂资源在线| 精品国产一区久久久| 蜜臀av午夜精品| 欧美日韩一卡二卡三卡 | 亚洲欧美在线高清| 无码国产69精品久久久久网站| 久久国产精品99国产| 国产盗摄视频在线观看| 中文字幕中文字幕精品| 91沈先生作品| 色老头在线一区二区三区| 日韩视频在线免费| 亚洲人成色777777精品音频| 欧美日韩高清一区| 日本道在线观看| 亚洲欧美电影一区二区| 性猛交╳xxx乱大交| 男女视频一区二区| 青娱乐自拍偷拍| 伊人色**天天综合婷婷| 日韩免费av电影| 婷婷亚洲精品| 风间由美久久久| 欧美性www| 国产成人精品久久二区二区91| 欧美xxxx做受欧美88bbw| 中文字幕欧美日韩精品| 青青草免费观看免费视频在线| 欧美一卡二卡在线| 中文字幕人妻互换av久久| 午夜电影久久久| 99精品久久久久| 国产精品国产馆在线真实露脸| 亚洲精品女人久久久| 国产91对白在线观看九色| 久久精品久久99| 久久精品国产在热久久| 久久综合伊人77777麻豆最新章节| 一区在线视频观看| 大地资源网在线观看免费官网| 日韩欧美精品综合| 日本在线观看不卡| 蜜臀av免费一区二区三区 | 国产a久久精品一区二区三区| 国产91精品入口17c| 久久av偷拍| 95av在线视频| 国产一区二区三区| 亚洲综合视频1区| 国产麻豆一区二区三区| 成人免费网站在线看| 一区二区三区无毛| 国产精品专区第二| 精品九九久久| 成人午夜高潮视频| 91麻豆精品一二三区在线| 成人免费在线视频网址| 伊人久久大香伊蕉在人线观看热v 伊人久久大香线蕉综合影院首页 伊人久久大香 | av中文字幕免费在线观看| 欧美精品久久99久久在免费线 | 日本三级免费看| 亚洲成人激情综合网| 中文字幕亚洲精品一区| 色综合久久久久久久久| 无码人妻黑人中文字幕| 在线一区二区三区做爰视频网站| 午夜精品免费观看| 欧美日本一道本在线视频| 国产口爆吞精一区二区| 日韩一级免费观看| 99热这里只有精品66| 精品久久久久久久久久久久久久久| 国产jzjzjz丝袜老师水多| 精品国产网站在线观看| 午夜视频福利在线观看| 国产一区二区三区在线观看视频 | 中文字幕制服丝袜成人av | 亚洲高清视频中文字幕| 亚洲免费在线观看av| 色伊人久久综合中文字幕| 国产精华7777777| 在线电影欧美成精品| 成人毛片视频免费看| 日韩精品亚洲精品| 国产大片在线免费观看| www.亚洲一区| 欧美草逼视频| 国产精品激情av在线播放| 日本精品网站| www.久久久| 国内精品久久久久久久久电影网| 中文字幕一区二区三区乱码 | 欧美国产精品一区二区| 紧身裙女教师波多野结衣| 亚洲不卡一区二区三区| 伊人中文字幕在线观看| 91麻豆精品国产91久久久久久久久 | 亚洲精品一区久久久久久| 在线看的av网站| 久久久人成影片一区二区三区观看| 免费福利视频一区二区三区| 91久久在线播放| 牛牛影视一区二区三区免费看| 亚洲精品成人久久久998| 国产精品九九| 国产野外作爱视频播放| fc2成人免费人成在线观看播放| 天天躁夜夜躁狠狠是什么心态| 亚洲精品videosex极品| 91麻豆精品在线| 精品国产sm最大网站| yw在线观看| 91超碰中文字幕久久精品| 色综合视频一区二区三区日韩| 久久久精品国产一区二区三区| 亚洲啊v在线观看| 久久精品网站视频| 成人久久久精品乱码一区二区三区| 天天舔天天操天天干| 精品久久久久久久久久久| av高清一区二区| 色噜噜狠狠狠综合曰曰曰| 成人黄色免费短视频| 久久av免费观看| 国内揄拍国内精品久久| 中文字幕第一页在线视频| 国产亚洲一区二区三区在线观看| 国产真实的和子乱拍在线观看| 欧美猛男男办公室激情| 蜜桃成人在线视频| 97色伦亚洲国产| caoporn成人| 在线观看av的网址| 精品一区二区三区免费毛片爱 | 精品国产91久久久久久浪潮蜜月| 日韩人妻无码精品久久久不卡| 国产一区视频在线看| 亚洲色图日韩精品| 91国产丝袜在线播放| 丝袜+亚洲+另类+欧美+变态| 97在线免费观看视频| 999国产精品一区| 日韩精品久久一区二区| 国产麻豆精品视频| 亚洲欧美综合7777色婷婷| 欧美视频中文一区二区三区在线观看 | 成人国产二区| 欧美日韩一区二区视频在线| 久久xxxx| 一级片手机在线观看| 日韩欧美在线视频日韩欧美在线视频 | 另类专区亚洲| 日韩激情久久| 日韩成人免费看| 久久久久久久久福利| 欧美日韩综合色| 一区二区三区视频网站| 国产欧美中文字幕| 天天综合精品| 久久综合桃花网| 亚洲一区二区三区三| 黄色福利在线观看| 26uuu另类亚洲欧美日本老年| 视频福利一区| 手机在线看福利| 国产精品视频第一区| 国产免费久久久| 欧美精品一区在线播放| 99这里只有精品视频| 日韩精品一区二区免费| 国产91精品久久久久久久网曝门| 日本一区二区三区四区五区| 日韩电影大片中文字幕| free欧美| 一区二区三区国产福利| 国产盗摄精品一区二区三区在线| 国产真实的和子乱拍在线观看| 亚洲精品网站在线播放gif| 免费观看成人性生生活片| 一区二区视频在线播放| 国产成人免费在线观看不卡| 日韩不卡在线播放| 曰本色欧美视频在线| 免费一级欧美片在线观看网站| 日本午夜激情视频| 国产女同互慰高潮91漫画| 91在线你懂的| 午夜精品久久久久久久99黑人 | 黄色一级大片在线观看| 中文字幕制服丝袜一区二区三区| 亚洲成人精品女人久久久| 国产成人精品av| 欧美精品观看| 极品人妻videosss人妻| 91精品国产91热久久久做人人| 毛片大全在线观看| 无码免费一区二区三区免费播放| 国产在线看一区| 黄色在线观看国产| 久久这里有精品视频| 亚州av日韩av| 99精品视频免费版的特色功能| 高跟丝袜欧美一区| 黄色免费在线观看| 乱色588欧美| 国产精品羞羞答答xxdd| 亚洲国产无线乱码在线观看| 久久久久亚洲精品| 日韩理论电影| 无码精品一区二区三区在线播放| 欧美日韩卡一卡二| 天天综合av| 日韩国产一级片|