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

用100行代碼提升10倍的性能

開發 前端
在通過預計算之后,在 5000 條數據的情況下,無論是短搜索還是長搜索,字典樹的查找效率基本是在 1ms 左右,而常規的遍歷查找則處于 10ms 左右,的確是十倍的提升。但是這個提升的代價是建立在犧牲空間,以及提前花費了時間計算的情況下。

[[319992]]

提出問題

從一個我常用的面試題,也是真實需求開始聊起:

你需要在前端展示 5000 條甚至更多的數據,每一條數據的數據結構是一個對象,里面有各式各樣的屬性。每個屬性的值又可以是基本類型,對象,甚至數組。這里的對象或者數組內部的元素又可以繼續包含對象或者數組并且允許無限嵌套下去。比如

  1.   "name": { 
  2.     "firstName""yi"
  3.     "lastName""li" 
  4.   }, 
  5.   "age": 23, 
  6.   "roles": ['developer''admin'], 
  7.   "projects": [{ 
  8.     "name""demo"
  9.     "repo""" 
  10.   }] 

頁面上提供一個搜索框,用戶通過輸入搜索的內容可以找到包含這個內容的數據。注意,只要任意數據對象的任意屬性值 (比如在上面的數據結構中,只要 name, age, roles 任何一個屬性的值)包含這個關鍵詞即可。如果屬性值是數組或者對象,那么數組的元素或者對象的值繼續對輸入內容進行匹配檢測,并遞歸的檢測下去,只要有命中,便算該數據匹配

如何設計這個功能,讓搜索功能盡可能的快?

解決思路

  • 如果你稍有程序員的敏感度,此時你的腦海里應該有兩個念頭:
  • 遍歷以及深度優先遍歷是最直接的方式
  • 如果要求夠快的話遍歷我就輸了

的確,遍歷是最簡單但也是最慢的。所以通常的優化方法之一是通過空間換取時間;而另一個方法……稍后再引出。

這里我們嘗試通過建立字典樹(Trie)來優化搜索。

如果你還不了解什么是字典樹,下面做簡單的介紹:假設我們有一個簡單的對象,鍵值的對應關系如下: 

用 100 行代碼提升 10 倍的性能

我們根據「鍵」的字母出現順次構建出一棵樹出來,葉子節點值即有可能是某個「鍵」的值 

用 100 行代碼提升 10 倍的性能

那么此時無論用戶想訪問任何屬性的值,只要從樹的根節點出發,依據屬性字母出現的順序訪問樹的葉子節點,即可得到該屬性的值。比如當我們想訪問tea時: 

用 100 行代碼提升 10 倍的性能

但是在我們需要解決的場景中,我們不需要關心「屬性」,我們只關心「值」是否匹配上搜索的內容。所以我們只需要對「值」建立字典樹。

假設有以下的對象值

  1. const o = { 
  2.   message: 'ack' 
  3.   fruit: 'apple'
  4.   unit: 'an'
  5.   name'anna'

建立的樹狀結構如下:

  1. root--a 
  2.       |--c 
  3.          |--k 
  4.       |--p 
  5.          |--p 
  6.             |--l 
  7.                |--e     
  8.       |--n 
  9.          |--n 
  10.             |--a 

當用戶搜索 apple 時,從a開始訪問,至最后訪問到字母 e 時,若在樹中有對應的節點,表示命中;當用戶搜索 aha 時,在訪問 h 時就已經無法在樹中找到對應的節點了,表示該對象不符合搜索條件

但實際工作中我們會有非常多個對象值,多個對象值之間可能有重復的值,所以匹配時,我們要把所有可能的匹配結果都返回。比如

  1.   { 
  2.     id: 1, 
  3.     message: 'ack' 
  4.     fruit: 'apple'
  5.     unit: 'an'
  6.     name'anna'
  7.   }, 
  8.   { 
  9.     id: 2, 
  10.     message: 'ack' 
  11.     fruit: 'banana'
  12.     unit: 'an'
  13.     name'lee'
  14.   }, 

上面兩個對象有相同的值 ack 和 an,所以在樹上的葉子節點中我們還要添加對象的 id 辨識信息

  1. root--a 
  2.       |--c 
  3.          |--k (ids: [1,2]) 
  4.       |--p 
  5.          |--p 
  6.             |--l 
  7.                |--e (ids: [1]) 
  8.       |--n (ids: [1, 2]) 
  9.          |--n 
  10.             |--a (ids: [1]) 

這樣當用戶搜索 an 時,我們能返回所有的匹配項

OK,有了思路之后我們開始實現代碼。

代碼實現

假數據

首先要解決的一個問題是如果快速的偽造 5000 條數據?這里我們使用 https://randomuser.me/api/開源 API。為了簡單起見,我們讓它只返回 gender, email, phone, cell, nat基本數據類型的值,而不返回嵌套結構(對象和數組)。注意這里只是為了便于代碼展示和理解,略去了復雜的結構,也就避免了復雜的代碼。加入復雜結構之后代碼其實也沒有大的變化,只是增加了遍歷的邏輯和遞歸邏輯而已。

請求 https://randomuser.me/api/?results=5000&inc=gender,email,phone,cell,nat 結果如下:

  1.   "results": [ 
  2.     { 
  3.       "gender""male"
  4.       "email""enzo.dumont@example.com"
  5.       "phone""02-65-13-26-00"
  6.       "cell""06-09-02-19-99"
  7.       "nat""FR" 
  8.     }, 
  9.     { 
  10.       "gender""male"
  11.       "email""gerald.omahony@example.com"
  12.       "phone""011-376-3811"
  13.       "cell""081-697-1414"
  14.       "nat""IE" 
  15.     } 
  16.     //... 
  17.   ] 

葉子節點數據結構

根據思路中的描述,數據結構描述如下:

  1. class Leaf { 
  2.   constructor(id = "", value = "") { 
  3.     this.ids = id ? [id] : []; 
  4.     this.value = value; 
  5.     this.children = {}; 
  6.   } 
  7.   share(id) { 
  8.     this.ids.push(id); 
  9.   } 

share方法用于向該葉子節點添加多個相同的匹配的id

幫助函數

在編碼的過程中我們需要一些幫助函數,比如:

  • isEmptyObject: 判斷是否是空對象
  • distinct: 移除一個數組中的重復元素

這兩個函數可以借用lodash類庫實現,即使手動實現起來也很簡單,這里就不贅述了

另一個重要的方法是normalize,我更習慣將normalize翻譯為「扁平化」(而不是「標準化」),因為這樣更形象。該方法用于將一個數組里的對象拆分為 id 與對象的映射關系。

比如將

  1.   { 
  2.     id: 1, 
  3.     message: 'ack' 
  4.     fruit: 'apple'
  5.     unit: 'an'
  6.     name'anna'
  7.   }, 
  8.   { 
  9.     id: 2, 
  10.     message: 'ack' 
  11.     fruit: 'banana'
  12.     unit: 'an'
  13.     name'lee'
  14.   }, 

扁平化之后為

  1.   '1': { 
  2.     id: 1, 
  3.     message: 'ack' 
  4.     fruit: 'apple'
  5.     unit: 'an'
  6.     name'anna'
  7.   }, 
  8.   '2': { 
  9.     id: 2, 
  10.     message: 'ack' 
  11.     fruit: 'banana'
  12.     unit: 'an'
  13.     name'lee',    
  14.   } 

之所以要這么做是為了當檢索結果返回一個 id 數組時:[1, 2, 3],我們只需要遍歷一邊返回結果就能通過 id 在扁平化的 Map 里立即找到對應的數據。否則還要不停的遍歷原始數據數組找到對應的數據.

因為 randomuser.me 返回的信息中不包含 id 信息,所以我們暫時用 email 信息作為唯一標示。normalize 的實現如下:

  1. function normalize(identify, data) { 
  2.   const id2Value = {}; 
  3.   data.forEach(item => { 
  4.     const idValue = item[identify]; 
  5.     id2Value[idValue] = item; 
  6.   }); 
  7.   return id2Value; 

構建一棵樹

這部分代碼就沒有什么秘密了,完全是按照遞算法歸構建一顆樹了

  1. fetch("https://randomuser.me/api/?results=5000&inc=gender,email,phone,cell,nat"
  2.   .then(response => { 
  3.     return response.json(); 
  4.   }) 
  5.   .then(data => { 
  6.     const { results } = data; 
  7.     const root = new Leaf(); 
  8.     const identifyKey = "email"
  9.  
  10.     results.forEach(item => { 
  11.       const identifyValue = item[identifyKey]; 
  12.       Object.values(item).forEach(itemValue => { 
  13.         // 注意這里會把 Number 和 Boolean 類型也字符串化 
  14.         const stringifiedValue = String(itemValue); 
  15.         let tempRoot = root; 
  16.         const arraiedStringifiedValue = Array.from(stringifiedValue); 
  17.         arraiedStringifiedValue.forEach((character, characterIndex) => { 
  18.           const reachEnd = 
  19.             characterIndex === arraiedStringifiedValue.length - 1; 
  20.           if (!tempRoot.children[character]) { 
  21.             tempRoot.children[character] = new Leaf( 
  22.               reachEnd ? identifyValue : ""
  23.               character 
  24.             ); 
  25.             tempRoot = tempRoot.children[character]; 
  26.           } else { 
  27.             if (reachEnd) { 
  28.               tempRoot.children[character].share(identifyValue); 
  29.             } 
  30.             tempRoot = tempRoot.children[character]; 
  31.           } 
  32.         }); 
  33.       }); 
  34.     }); 

模糊搜索

搜索部分代碼也沒有什么秘密,按圖索驥而已:

  1. function searchBlurry(root, keyword, userMap) { 
  2.   const keywordArr = Array.from(String(keyword)); 
  3.   let tempRoot = root; 
  4.   let result = []; 
  5.  
  6.   for (let i = 0; i < keywordArr.length; i++) { 
  7.     const character = keywordArr[i]; 
  8.     if (!tempRoot.children[character]) { 
  9.       break; 
  10.     } else { 
  11.       tempRoot = tempRoot.children[character]; 
  12.     } 
  13.     if (keywordArr.length - 1 === i) { 
  14.       result = [ 
  15.         ...tempRoot.ids, 
  16.         ...collectChildrenInsideIds(tempRoot.children) 
  17.       ]; 
  18.     } 
  19.   } 
  20.   return distinct(result).map(id => { 
  21.     return userMap[id]; 
  22.   }); 

注意這里有一個collectChildrenInsideIds方法,這個方法用于收集該葉子節點下所有的子節點的 id。這么做是因為當前操作模糊匹配,當你搜索a時,apple, anna, ack 都算匹配。

常規搜索辦法以及字典樹的缺陷

為了對比效率,并且為了測試搜索結果的正確性,我們仍然需要編寫一個常規的遍歷的搜索方法:

  1. function regularSearch(searchKeyword) { 
  2.   const regularSearchResults = []; 
  3.   results.forEach(item => { 
  4.     for (const key in item) { 
  5.       const value = item[key]; 
  6.       if (String(value).startsWith(searchKeyword)) { 
  7.         regularSearchResults.push(item); 
  8.         break; 
  9.       } 
  10.     } 
  11.   }); 
  12.   return regularSearchResults 

注意在測試對象值是否匹配搜索詞時,我們使用了startsWith,而不是indexOf,這是因為字典樹的缺陷在于只能匹配以搜索詞開頭的詞!比如當你搜索a時,只能匹配apple、anna而不能匹配banana。為了便于對比,我們不得不使用startsWith

性能的對比

性能的對比結果是很有意思的:

  • 當數據量較小時,查找效率不會有大的差異
  • 當數據量較大時,比如 5000 條的情況下,當你的搜索詞非常短小,比如a,那么字典樹的查找效率會比遍歷搜索低,也就是反而花費的時間長;當搜索詞變得具體時,比如ali,字典樹的查找效率會比遍歷搜索高
  • 效率反而低的問題不難想到是為什么:當你搜索詞簡單時,訪問的葉子節點會少,所以只能掃描children收集子節點的所有的可能 id,這步操作中遍歷的過程占用了大部分時間

但是我們仍然需要滿足這部分的查詢需求,所以我們要針對這個場景做一些優化

優化簡短搜索的場景

我們回想一下簡單搜索的場景,性能的瓶頸主要在于我們需要遍歷葉子節點下的所有子節點。好辦,鑒于樹構建完之后不會再發生變化,那么我們只需要提前計算好每個葉子節點的所以子 id 就好了,這就是文章開頭說的第二類優化方案,即預計算。

我編寫了一個新的方法,用于遞歸的給每個葉子節點添加它所有子節點的 id:

  1. function decorateWithChildrenIds(root) { 
  2.   const { children } = root; 
  3.   root.childrenIds = collectChildrenInsideIds(root.children); 
  4.   for (const character in children) { 
  5.     const characterLeaf = children[character]; 
  6.     characterLeaf.childrenIds = collectChildrenInsideIds( 
  7.       characterLeaf.children 
  8.     ); 
  9.     decorateWithChildrenIds(characterLeaf); 
  10.   } 

那么在構建完樹之后,用這個方法把所有葉子節點「裝飾」一遍就好了

結論

在通過預計算之后,在 5000 條數據的情況下,無論是短搜索還是長搜索,字典樹的查找效率基本是在 1ms 左右,而常規的遍歷查找則處于 10ms 左右,的確是十倍的提升。但是這個提升的代價是建立在犧牲空間,以及提前花費了時間計算的情況下。相信如果數據結構變得更復雜,效率提升會更明顯

 

責任編輯:未麗燕 來源: 今日頭條
相關推薦

2020-07-22 08:30:02

代碼開發工具

2011-07-01 10:11:39

2022-09-09 09:33:14

支付寶代碼性能

2022-04-21 07:51:51

場景JavaSQL

2014-03-26 10:00:06

RailsRails性能

2022-11-27 17:39:06

大數據集群性能

2024-07-17 08:25:44

2021-12-29 11:06:25

Java代碼技巧

2025-09-30 02:11:00

2020-07-21 15:40:55

NginxJava服務器

2025-05-27 01:55:00

TypeScript開發者項目

2023-05-04 07:34:37

Rust代碼CPU

2024-10-29 08:21:05

2018-08-23 17:45:52

2019-09-26 08:33:51

Nginx技術Java

2013-09-26 14:11:23

SQL性能優化

2021-04-21 18:57:16

二進制存儲空間

2024-12-13 13:58:53

2025-05-09 02:00:00

代碼接口吞吐量

2017-12-13 13:09:36

NginxWeb應用
點贊
收藏

51CTO技術棧公眾號

猛男gaygay欧美视频| 我爱我色成人网| hitomi一区二区三区精品| 秋霞av国产精品一区| 国产午夜福利一区| 欧美国产中文高清| 婷婷综合五月天| 在线观看精品视频| 网站黄在线观看| 日韩欧美不卡在线| 自拍视频在线播放| 成人免费视频网站在线观看| 国产精品福利无圣光在线一区| 一级黄色片日本| 午夜欧洲一区| 日韩欧美一级精品久久| 日韩免费高清在线| 成人av影院在线观看| 国产精品三级电影| 久久婷婷开心| 亚洲av永久无码国产精品久久| 日韩国产欧美在线播放| 国产69精品久久久| 日韩精品123区| 国产区精品区| 日韩电影在线观看中文字幕| 亚洲欧美日韩网站| 人人视频精品| 黄网站色欧美视频| 国产亚洲精品久久久久久久| wwwxxx在线观看| 99久久综合国产精品| 亚洲自拍av在线| 夜夜狠狠擅视频| 久久狠狠一本精品综合网| 欧美肥婆姓交大片| 国产极品国产极品| 午夜精品一区二区三区国产 | 欧美喷水视频| 北条麻妃99精品青青久久| 中文字幕成人动漫| 日韩有码一区| 亚洲精品videossex少妇| 久久综合桃花网| 成人亚洲精品| 91麻豆精品国产自产在线| 色婷婷成人在线| 成人黄色免费网站| 欧美私模裸体表演在线观看| 噜噜噜久久亚洲精品国产品麻豆 | 日韩美女在线观看一区| 国产成人无码一区二区三区在线| 欧美日本精品| 欧美第一淫aaasss性| 欧美日韩成人免费观看| 欧美私人啪啪vps| 欧美日韩福利视频| 久久久久久激情| 亚洲一级网站| 91精品国产色综合久久不卡98口| 国产手机在线视频| 国产一区91| 奇米成人av国产一区二区三区| 日韩精品在线观看免费| 国产精品毛片| 欧洲日本亚洲国产区| 无码视频一区二区三区| 日韩激情在线观看| 国产日本欧美一区二区三区| 一区二区视频免费观看| 久久爱www久久做| 91牛牛免费视频| 亚洲成人77777| 99久久伊人网影院| 日韩一区不卡| www在线免费观看视频| 一区二区三区日韩精品视频| 九九热只有这里有精品| 在线看片福利| 欧美日免费三级在线| 交换做爰国语对白| 国产精品xxx在线观看| 亚洲理论在线a中文字幕| 毛片aaaaaa| 欧美区亚洲区| 国产suv精品一区二区三区88区| 真实的国产乱xxxx在线91| 国模娜娜一区二区三区| 成人黄色在线免费观看| 欧美日韩在线精品一区二区三区激情综| 国产午夜久久久久| 51xx午夜影福利| 欧美三级网站| 欧美精品 国产精品| 国产大学生视频| 久久精品高清| 97精品久久久中文字幕免费| 凹凸精品一区二区三区| 国产成人日日夜夜| 久久免费一区| 米奇精品一区二区三区| 黑人巨大精品欧美一区二区免费| 爱爱爱爱免费视频| 欧美日韩麻豆| 成人444kkkk在线观看| 69国产精品视频免费观看| 精品中文字幕一区二区小辣椒 | 亚洲精品国产精品乱码不卡| 国产香蕉久久精品综合网| 99亚洲国产精品| 国精产品一区一区三区四川| 精品久久一二三区| 激情无码人妻又粗又大| 午夜在线一区| 成人黄色片视频网站| 视频三区在线| 日韩欧美有码在线| 亚洲少妇一区二区三区| 999久久久国产精品| 清纯唯美亚洲激情| 四虎永久在线观看| 亚洲精品午夜久久久| 国产精品拍拍拍| 日本午夜精品久久久| 欧美日韩高清区| 影音先锋黄色网址| 久久视频一区二区| 水蜜桃色314在线观看| 高清不卡一区| 久久精品在线视频| 中文字幕精品一区二区精| 2020国产精品久久精品美国| 国产欧美日韩小视频| 国产精品毛片无码| 久久久999精品免费| 在线免费观看av片| 欧美国产成人在线| 妞干网在线免费视频| 日韩成人av在线资源| 97香蕉超级碰碰久久免费的优势| 亚洲第一成年人网站| 亚洲精品日产精品乱码不卡| 在线观看日本www| 欧美激情黄色片| 国产精品影片在线观看 | 美日韩丰满少妇在线观看| 国产精品第6页| 日本一区二区三区dvd视频在线| 男人天堂999| 亚州综合一区| 全球成人中文在线| 国产中文字幕在线视频| 91国产视频在线观看| 国产精品无码无卡无需播放器| 日韩精品一卡二卡三卡四卡无卡| 欧美精品123| 日韩欧美亚洲国产| 亚洲精品69| 最近2019中文字幕大全第二页 | 欧美午夜激情视频| 亚洲少妇18p| 国产欧美日本| 免费在线观看一区二区| 丝袜美腿诱惑一区二区三区| 亚洲色无码播放| 国产在线一级片| 国产精品国产精品国产专区不蜜 | 青青草视频国产| 国产精品一区二区三区美女| 91精品国产精品| 国产高清视频在线观看| 精品视频资源站| 在线免费看av网站| 成人av在线一区二区三区| av在线播放亚洲| 狠狠做六月爱婷婷综合aⅴ| 国产欧美精品xxxx另类| 羞羞网站在线看| 亚洲精品久久久久| 中文字幕理论片| 一区二区三区中文在线观看| 国产又黄又粗又猛又爽的视频| 久久久青草婷婷精品综合日韩 | 尤物精品在线| 日韩精品资源| 日韩欧美激情电影| 日韩美女免费观看| 尤物视频在线看| 亚洲欧美日韩精品| 999久久久久久| 欧美视频一区二区三区…| 四虎影视一区二区| 成人h动漫精品一区二区| 欧美少妇性生活视频| 亚洲精品小说| 欧美日韩亚洲在线| 日韩视频一二区| 国产精品视频久久| 96av在线| 久久视频中文字幕| 欧美日韩视频精品二区| 日韩一级高清毛片| 亚洲视屏在线观看| 午夜国产精品影院在线观看| 99热这里只有精品4| 99久久久国产精品免费蜜臀| 一本色道久久亚洲综合精品蜜桃| 91久久夜色精品国产九色| 亚洲永久一区二区三区在线| 麻豆一区二区| 亚洲在线www| 欧美黄页免费| 日本免费一区二区三区视频观看| 中文在线手机av| 在线国产精品视频| 天堂√在线中文官网在线| 日韩欧美在线影院| 国产亚洲久一区二区| 欧美日韩国产一区在线| 久草免费在线视频观看| 中文字幕中文字幕一区| 国产在线观看无码免费视频| 国产成人精品一区二区三区四区| 成人亚洲精品777777大片| 国产农村妇女精品一二区| 精品视频在线观看一区二区| 国产精品黑丝在线播放| 四虎永久在线精品免费一区二区| 香蕉久久夜色精品国产更新时间 | 中文 日韩 欧美| 日日夜夜精品免费视频| 男人的天堂99| 国产欧美不卡| 欧美亚洲日本一区二区三区| 欧美亚洲不卡| 蜜桃视频一区二区在线观看| 五月久久久综合一区二区小说| 日韩资源av在线| 亚洲调教一区| 欧美日韩一区二区三区在线视频 | 日韩一区在线播放| 亚洲午夜久久久久久久国产| 久久噜噜亚洲综合| 91网站免费视频| 久久亚洲综合色一区二区三区| 亚洲最大免费视频| www欧美成人18+| 国产在线观看无码免费视频| www久久精品| 3d动漫精品啪啪一区二区下载 | 欲香欲色天天天综合和网| 97视频免费在线看| 亚洲精品一区| 国产成人涩涩涩视频在线观看| gogo亚洲高清大胆美女人体| 国产精品成人播放| 国产精品99| 91精品视频在线播放| 久久免费福利| 狠狠干一区二区| 九九久久婷婷| 亚洲国产一区二区在线| 亚洲一区二区三区无吗| 肉大捧一出免费观看网站在线播放 | 这里只有精品66| 亚洲一级淫片| 免费国产a级片| 日韩高清在线一区| 999这里有精品| 国产99精品视频| 亚洲熟女乱综合一区二区三区| 久久久午夜精品理论片中文字幕| 亚洲欧美va天堂人熟伦| 1000部国产精品成人观看| www.youjizz.com亚洲| 天天影视色香欲综合网老头| 国产字幕在线观看| 3d动漫精品啪啪1区2区免费| 好男人在线视频www| 亚洲天堂av电影| av黄色在线| 91av在线免费观看| 日韩欧美三区| 精品国产乱码久久久久久蜜柚 | 欧美疯狂性受xxxxx另类| 高清视频在线观看三级| 国产精品成人av在线| 久久精品免视看国产成人| 精品一区二区国产| 99久久综合狠狠综合久久aⅴ| 精品国产一区二区三区无码| 首页综合国产亚洲丝袜| 手机在线免费毛片| 91蜜桃网址入口| 婷婷伊人五月天| 色综合天天狠狠| 亚洲第九十九页| 最近更新的2019中文字幕| a天堂资源在线| 成人国产精品一区二区| 特黄特色欧美大片| 四虎4hu永久免费入口| 国产精品主播| 野战少妇38p| 国产精品白丝在线| 精品国产xxx| 亚洲第一二三四五区| 麻豆传媒在线免费看| 2024亚洲男人天堂| 136导航精品福利| 欧美日韩视频免费在线观看| 久久午夜视频| 久久午夜夜伦鲁鲁片| 一区二区激情视频| 亚洲自拍第二页| 亚洲日本成人网| 黄色在线观看www| av资源一区二区| 欧美在线免费| www.色欧美| 国产精品视频一区二区三区不卡| 亚洲伊人成人网| 亚洲福利在线观看| 欧美色图天堂| 91网站在线免费观看| 欧美激情成人| 最新天堂中文在线| 国产精品午夜电影| 亚洲高清视频免费观看| 亚洲美女动态图120秒| 国产粉嫩在线观看| 国产精品久久一区二区三区| 欧美精品一级| 在线播放av网址| 亚洲韩国一区二区三区| 精品国产无码一区二区| 久久综合电影一区| 国产高清亚洲| 久久久无码中文字幕久...| 精品无码三级在线观看视频| 又色又爽的视频| 欧美精品丝袜中出| 免费在线观看av| 亚洲va男人天堂| 欧美成人高清| av在线网站免费观看| 亚洲精品免费播放| 欧美在线 | 亚洲| 97在线观看视频国产| 啪啪激情综合网| 免费成人在线视频网站| 久久久精品国产免大香伊| 无码视频在线观看| 中文字幕亚洲欧美一区二区三区 | 久久午夜免费视频| 日韩精品小视频| 久久久人成影片一区二区三区在哪下载 | 日本免费中文字幕在线| 国产日韩欧美在线看| 91精品国产乱码久久久久久久 | 一级特黄色大片| 久久久99久久精品女同性| 视频在线一区| 国产免费观看高清视频| 国产欧美一区二区精品仙草咪| 五月天中文字幕| 欧美成人免费播放| 久久婷婷国产| 男女啪啪网站视频| 亚洲视频每日更新| 成人久久久精品国产乱码一区二区 | 精品国产一区二区精华| 极品视频在线| 亚洲国产精品123| 国产精品一卡二| 日韩精品在线免费视频| 色婷婷av一区二区三区久久| 欧美成年网站| 无码人妻丰满熟妇区毛片18| 国产精品每日更新| 欧美 日韩 国产 精品| 国产91热爆ts人妖在线| 亚洲国产精品91| 在线观看国产网站| 69堂国产成人免费视频| 97人人在线视频| 一本色道婷婷久久欧美 | 国产精品久久久久久成人| 欧美一级二级三级蜜桃| 中国色在线日|韩| 中文字幕av久久| 久久无码av三级| jizz中国女人| 国产精品第3页| 亚洲二区在线| 99鲁鲁精品一区二区三区| 亚洲精品一区二三区不卡| 日本在线一区二区三区| 嫩草av久久伊人妇女超级a| 一区av在线播放|