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

Go map使用Swiss Table重新實現,性能最高提升近50%

開發 前端
本文探討了Go語言中的map實現的重塑,即引入Swiss Table這一高效哈希表結構的背景與優勢。Swiss Table由Google工程師開發,旨在優化內存使用和提升性能,解決了傳統哈希表在高負載情況下的性能瓶頸。

2024月11月5日的Go compiler and runtime meeting notes[1]中,我們注意到了一段重要內容,如下圖紅框所示:

圖片圖片

這表明,來自字節的一位工程師在兩年多前提出的“使用Swiss table重新實現Go map[2]”的建議即將落地,目前該issue已經被納入Go 1.24里程碑[3]

Swiss Table是由Google工程師于2017年開發的一種高效哈希表實現,旨在優化內存使用和提升性能,解決Google內部代碼庫中廣泛使用的std::unordered_map所面臨的性能問題。Google工程師Matt Kulukundis在2017年CppCon大會上詳細介紹了他們在Swiss Table上的工作[4]

圖片圖片

目前,Swiss Table已被應用于多種編程語言,包括C++ Abseil庫的flat_hash_map(可替換std::unordered_map)[5]、Rust標準庫Hashmap的默認實現[6]等。

Swiss Table的出色表現是字節工程師提出這一問題的直接原因。字節跳動作為國內使用Go語言較為廣泛的大廠。據issue描述,Go map的CPU消耗約占服務總體開銷的4%。其中,map的插入(mapassign)和訪問(mapaccess)操作的CPU消耗幾乎是1:1。大家可千萬不能小看4%這個數字,以字節、Google這樣大廠的體量,減少1%也意味著真金白銀的大幅節省。

Swiss Table被視為解決這一問題的潛在方案。字節工程師初版實現的基準測試結果顯示,與原實現相比,Swiss Table在查詢、插入和刪除操作上均提升了20%至50%的性能,尤其是在處理大hashmap時表現尤為突出;迭代性能提升了10%;內存使用減少了0%至25%,并且不再消耗額外內存。

這些顯著的性能提升引起了Go編譯器和運行時團隊的關注,特別是當時負責該子團隊的Austin Clements。在經過兩年多的實驗和評估后,Go團隊成員Michael Pratt[7]基于Swiss Table實現的internal/runtime/maps最終成為Go map的底層默認實現。

在本文中,我們將簡單介紹Swiss Table這一高效的哈希表實現算法,并提前看一下Go map的Swiss Table實現。

在進入swiss table工作原理介紹之前,我們先來回顧一下當前Go map的實現(Go 1.23.x)。

1. Go map的當前實現

map,也稱為映射,或字典,或哈希表[8],是和數組等一樣的最常見的數據結構。實現map有兩個關鍵的考量,一個是哈希函數(hash function),另一個就是碰撞處理(collision handling)。hash函數是數學家的事情,這里不表。對于碰撞處理,在大學數據結構課程中,老師通常會介紹兩種常見的處理方案:

  • 開放尋址法(Open Addressing)

在發生哈希碰撞時,嘗試在哈希表中尋找下一個可用的位置,如下圖所示k3與k1的哈希值發生碰撞后,算法會嘗試從k1的位置開始向后找到一個空閑的位置:

圖片圖片

  • 鏈式哈希法(拉鏈法, Chaining)

每個哈希桶(bucket)存儲一個鏈表(或其他數據結構),所有哈希值相同的元素(比如k1和k3)都被存儲在該鏈表中。

圖片圖片

Go當前的map實現采用的就是鏈式哈希,當然是經過優化過的了。要了解Go map的實現,關鍵把握住下面幾點:

  • 編譯器重寫

我們在用戶層代碼中使用的map操作都會被Go編譯器重寫為對應的runtime的map操作,就如下面Go團隊成員Keith Randall在GopherCon大會上講解map實現原理[9]的一個截圖所示:

圖片圖片

  • 鏈式哈希

前面提過,Go map當前采用的是鏈式哈希的實現,一個map在內存中的結構大致如下:

圖片圖片

來自Keith Randall的ppt截圖

我們看到,一個map Header代表了一個map類型的實例,map header中存儲了有關map的元數據(圖中字段與當前實現可能有少許差異,畢竟那是幾年前的一個片子了),如:

- len: 當前map中鍵值對的數量。
- bucket array: 存儲數據的bucket數組,可以對比前面的鏈式哈希的原理圖進行理解,不過不同的是,Go map中每個bucket本身就可以存儲多個鍵值對,而不是指向一個鍵值對的鏈表。
- hash seed: 用于哈希計算的種子,用于分散數據并提高安全性。

通常一個bucket可以存儲8個鍵值對,這些鍵值對是根據鍵的哈希值分配到對應的bucket中。

  • 溢出桶(overflow bucket)

每個bucket后面還會有Overflow Bucket。當一個bucket中的數據超出容量時,會創建overflow bucket來存儲多余的數據。這樣可以避免直接擴展bucket數組,節省內存空間。但如果出現過多的overflow bucket,性能就會下降。

  • “螞蟻搬家”式的擴容

當map中出現過多overflow bucket而導致性能下降時,我們就要考慮map bucket擴容的事兒了,以始終保證map的操作性能在一個合理的范圍。是否擴容由一個名為load factor的參數所控制。load factor是元素數量與bucket數量的比值,比值越高,map的讀寫性能越差。目前Go map采用了一個經驗值來確定是否要擴容,即load factor = 6.5。當load factor超過這個值時,就會觸發擴容。所謂擴容就是增大bucket數量(當前實現為增大一倍數量),減少碰撞,讓每個bucket中存放的element數量降下來。

擴容需要對存量element做rehash,在元素數量較多的情況下,“一次性”的完成桶的擴容會造成map操作延遲“突增”,無法滿足一些業務場景的要求,因此Go map采用“增量”擴容的方式,即在訪問和插入數據時,“螞蟻搬家”式的做點搬移元素的操作,直到所有元素完成搬移。

Go map的當前實現應該可以適合大多數的場合,但依然有一些性能和延遲敏感的業務場景覺得Go map不夠快,另外一個常被詬病的就是當前實現的桶擴容后就不再縮容(shrink)了[11],這會給內存帶來壓力。

來自issue 20135的截圖

下面我們再來看看swiss table的結構和工作原理。

2. Swiss table的工作原理

就像前面提到的,Swiss table并非來自某個大學或研究機構的論文,而是來自Google工程師在工程領域的"最佳實踐",因此關于Swiss table的主要資料都來自Google的開源C++ library Abseil[12]以及開發者的演講視頻[13]。在Abseil庫中,它是flat_hash_map、flat_hash_set、node_hash_map以及node_hash_set等數據結構的底層實現,并且Swiss table的實現在2018年9月正式開源[14]。

和Go map當前實現不同,Swiss table使用的不是拉鏈法,而是開放尋址,但并非傳統的方案。下面是根據公開資源畫出的一個Swiss table的邏輯結構圖(注意:并非真實內存布局):

圖片圖片

如果用一個式子來表示Swiss table,我們可以用:

A swiss table = N * (metdata array + slots array)

我們看到:swiss table將所謂的桶(這里叫slot)分為多個group,每個group中有16個slot,這也是swiss table的創新,即將開放尋址方法中的probing(探測key碰撞后下一個可用的位置(slot))放到一個16個slot的group中進行,這樣的好處是可以通過一個SIMD指令[15]并行探測16個slot,這種方法也被稱為Group Probing。

在上圖中,我們看到一個Group由metadata和16個slot組成。metadata中存儲的是元數據,而slot中存儲的是元素(key和value)。Group probling主要是基于metadata實現的,Google工程師的演講有對group probing實現的細節描述。

當我們向swiss table插入一個元素或是查找一個元素時,swiss table會通過hash函數對key進行求值,結果是一個8字節(64bit)的數。和Go map的當前實現一樣,這個哈希值的不同bit功用不同,下圖是一個來自abseil官網的示例:

圖片圖片

哈希值的高57bit被稱為H1,低7bit被稱為H2。前者用于標識該元素在Group內的索引,查找和插入時都需要它。后者將被用于該元素的元數據,放在metadata中存儲,用于快速的group probing之用,也被稱為哈希指紋

每個Group的metadata也是一個16字節數組,每個字節對應一個slot,是該slot的控制字節。這個字節的8個bit位的組成如下:

圖來自abseil庫官網圖來自abseil庫官網

metadata中的控制字節有三個狀態:

  • 最高位為1,其余全零為**空閑狀態(Empty)**,即對應的slot尚未曾被任何element占據過;
  • 最高位為0,后7位為哈希指紋(H2),為對應的slot當前已經有element占據的已使用狀態;
  • 最高位為1,其他位為1111110的,為對應的slot為已刪除狀態,后續可以被繼續使用。

下面是Abseil開發者演進slide中的一個針對swiss table的迭代邏輯:

圖片圖片

通過這幅圖可以看出H1的作用。不過這里通過pos = pos + 1進行probing(探測)顯然是不高效的!metadata之所以設計為如此,并保存了插入元素的哈希指紋就是為了實現高效的probing,下圖演示了基于key的hash值的H2指紋通過SIMD指令從16個位置中快速得到匹配的pos的過程:

圖片圖片

雖然有兩個匹配項,但這個過程就像“布隆過濾器”一樣,快速排除了不可能的匹配項,減少了不必要的內存訪問。

由于metadata僅有16個字節,它的內存局部性更好。16個控制字節正好填充一個64字節的緩存行(cache line),使用SIMD指令一次性加載整組控制字節,預取效率高,幾乎沒有cache miss。

由此也可以看到:swiss table的16個條目的分組大小不是隨意選擇的,而是基于現代CPU的緩存行大小(64字節)優化的,保證了一個Group的控制字節能被單次SIMD指令處理。

此外swiss table也是通過load factor來判定是否需要對哈希表進行擴容,一旦擴容,swiss table通常是會將group數量增加一倍,然后重新計算當前所有元素在新groups中的新位置(rehash),這個過程是有一定開銷的。如果不做優化,當表中元素數量較多時,這個過程會導致操作延遲增加。

最后,雖然多數情況是在group內做probing,但當元素插入時,如果當前Group已滿,就必須探測到下一個Group,并將元素插入到下一個Group。這樣,在該元素的查找操作中,probing也會跨group進行。

到這里,我們已經粗略了解了swiss table的工作原理,那么Go tip對swiss table當前的實現又是怎樣的呢?我們下面就來看看。

3. Go tip版本當前的實現

Go tip版本基于swiss table的實現在https://github.com/golang/go/blob/master/src/internal/runtime/maps下。

由于Go map是原生類型,且有了第一版實現,考慮到Go1兼容性,新版基于swiss table的實現也要繼承已有的語義約束。同時,也要盡量避免swiss table自身的短板,Go團隊在swiss table之上做了局部改進。比如為了將擴容帶來的開銷降到最低,Go引入了多table的設計,以支持漸進式擴容。也就是說一個map實際上是多個swiss table,而不是像上面說的一個map就是一個swiss table。每個table擁有自己的load factor,可以獨立擴容(table的擴容是一次性擴容),這樣就可以將擴容的開銷從全部數據變為局部少量數據,減少擴容帶來的影響。

Go swiss-table based map的邏輯結構大致如下:

圖片圖片

我們可以看出與C++ swisstable的最直觀不同之處除了有多個table外,每個group包含8個slot和一個control word,而不是16個slot。此外,Go使用了二次探測(quadratic probing), 探測序列必須以空slot結束。

為了實現漸進式擴容,數據分散在多個table中;單個table容量有上限(maxTableCapacity),超過上限時分裂成兩個table;使用可擴展哈希(extendible hashing)根據hash高位選擇table,且每個table可以獨立增長。

Go使用Directory管理多個table,Directory是Table的數組,大小為2^globalDepth。如果globalDepth=2,那Directory最多有4個表,分為0x00、0x01、0x10、0x11。Go通過key的hash值的前globalDepth個bit來選擇table。這是一種“extendible hashing”,這是一種動態哈希技術,其核心特點是通過動態調整使用的哈希位數(比如上面提到的globalDepth)來實現漸進式擴容。比如:初始可能只用1位哈希值來區分,需要時可以擴展到用2位,再需要時可以擴展到用3位,以此類推。

舉個例子,假設我們用二進制表示哈希值的高位,來看一個漸進式擴容的過程:

  • 初始狀態 (Global Depth = 1):
directory
hash前綴  指向的table
0*** --> table1 (Local Depth = 1)
1*** --> table2 (Local Depth = 1)
  • 當table1滿了需要分裂時,增加一位哈希值 (Global Depth = 2):
directory
hash前綴  指向的table
00** --> table3 (Local Depth = 2)  // 由table1擴容而成
01** --> table4 (Local Depth = 2)  // 由table1擴容而成
10** --> table2 (Local Depth = 1)
11** --> table2 (Local Depth = 1)  // 復用table2因為它的Local Depth還是1
  • 如果table2也滿了,需要分裂:
directory
hash前綴  指向的table
00** --> table3 (Local Depth = 2)
01** --> table4 (Local Depth = 2)
10** --> table5 (Local Depth = 2) // 由table2擴容而成
11** --> table6 (Local Depth = 2) // 由table2擴容而成

通過extendible hashing實現的漸進式擴容,每次只處理一部分數據,擴容過程對其他操作影響小,空間利用更靈活。

對于新版go map實現而言,單個Table達到負載因子閾值時觸發Table擴容。當需要分裂的Table的localDepth等于map的globalDepth時觸發Directory擴容,這就好理解了。

除此之外,Go版本對small map也有特定優化,比如少量元素(<=8)時直接使用單個group,避免或盡量降低swiss table天生在少量元素情況下的性能回退問題。

更多實現細節,大家可以自行閱讀https://github.com/golang/go/blob/master/src/internal/runtime/maps/下的Go源碼進行理解。

注:目前swiss table版的go map依然還未最終定型,并且后續還會有各種優化加入,這里只是對當前的實現(2024.11.10)做概略介紹,不代表以后的map實現與上述思路完全一致。

4. Benchmark

目前gotip版本中GOEXPERIMENT=swissmap默認已經打開[16],我們直接用gotip版本即可體驗基于swiss table實現的map。

字節工程師zhangyunhao的gomapbench repo[17]提供了對map的性能基準測試代碼,不過這個基準測試太多,我大幅簡化了一下,只使用Int64,并只測試了元素個數分別為12、256和8192時的情況。

注:我基于Centos 7.9,使用Go 1.23.0和gotip(devel go1.24-84e58c8 linux/amd64)跑的benchmark。

// 在experiments/swiss-table-map/mapbenchmark目錄下
$go test -run='^$' -timeout=10h -bench=. -count=10 > origin-map.txt 
$GOEXPERIMENT=swissmap gotip test -run='^$' -timeout=10h -bench=. -count=10 > swiss-table-map.txt 
$benchstat origin-map.txt swiss-table-map.txt > result.txt

下面是result.txt中的結果:

goos: linux
goarch: amd64
pkg: demo
cpu: Intel(R) Xeon(R) Platinum
                                  │ origin-map.txt │         swiss-table-map.txt          │
                                  │     sec/op     │    sec/op     vs base                │
MapIter/Int/12-8                      179.7n ± 10%   190.6n ±  4%        ~ (p=0.436 n=10)
MapIter/Int/256-8                     4.328μ ±  5%   3.748μ ±  1%  -13.40% (p=0.000 n=10)
MapIter/Int/8192-8                    137.3μ ±  1%   123.6μ ±  1%   -9.95% (p=0.000 n=10)
MapAccessHit/Int64/12-8               10.12n ±  2%   10.68n ± 14%   +5.64% (p=0.000 n=10)
MapAccessHit/Int64/256-8              10.29n ±  3%   11.29n ±  1%   +9.77% (p=0.000 n=10)
MapAccessHit/Int64/8192-8             25.99n ±  1%   14.93n ±  1%  -42.57% (p=0.000 n=10)
MapAccessMiss/Int64/12-8              12.39n ± 88%   20.99n ± 50%        ~ (p=0.669 n=10)
MapAccessMiss/Int64/256-8             13.12n ±  6%   11.34n ±  7%  -13.56% (p=0.000 n=10)
MapAccessMiss/Int64/8192-8            15.71n ±  1%   14.03n ±  1%  -10.66% (p=0.000 n=10)
MapAssignGrow/Int64/12-8              607.1n ±  2%   622.6n ±  2%   +2.54% (p=0.000 n=10)
MapAssignGrow/Int64/256-8             25.98μ ±  3%   23.22μ ±  1%  -10.64% (p=0.000 n=10)
MapAssignGrow/Int64/8192-8            792.3μ ±  1%   844.1μ ±  1%   +6.54% (p=0.000 n=10)
MapAssignPreAllocate/Int64/12-8       450.2n ±  2%   409.2n ±  1%   -9.11% (p=0.000 n=10)
MapAssignPreAllocate/Int64/256-8     10.412μ ±  1%   6.055μ ±  2%  -41.84% (p=0.000 n=10)
MapAssignPreAllocate/Int64/8192-8     342.4μ ±  1%   232.6μ ±  2%  -32.05% (p=0.000 n=10)
MapAssignReuse/Int64/12-8             374.2n ±  1%   235.4n ±  2%  -37.07% (p=0.000 n=10)
MapAssignReuse/Int64/256-8            8.737μ ±  1%   4.716μ ±  4%  -46.03% (p=0.000 n=10)
MapAssignReuse/Int64/8192-8           296.4μ ±  1%   181.0μ ±  1%  -38.93% (p=0.000 n=10)
geomean                               1.159μ         984.2n        -15.11%

我們看到了除了少數測試項有不足外(比如MapAssignGrow以及一些元素數量少的情況下),大多數測試項中,新版基于swiss table的map的性能都有大幅提升,有些甚至接近50%!

5. 小結

本文探討了Go語言中的map實現的重塑,即引入Swiss Table這一高效哈希表結構的背景與優勢。Swiss Table由Google工程師開發,旨在優化內存使用和提升性能,解決了傳統哈希表在高負載情況下的性能瓶頸。通過對比現有的鏈式哈希實現,Swiss Table展示了在查詢、插入和刪除操作上顯著提高的性能,尤其是在處理大規模數據時。

經過兩年多的實驗與評估,Go團隊決定將Swiss Table作為Go map的底層實現,預計將在Go 1.24[19]中正式落地。新的實現不僅承繼了原有的語義約束,還通過引入多表和漸進式擴容的設計,進一步優化了擴容過程的性能。盡管當前實現仍在完善中,但Swiss Table的引入無疑為Go語言的性能提升提供了新的可能性,并為未來進一步優化奠定了基礎。

對于那些因Go引入自定義iterator[20]而批評Go團隊的Gopher來說,這個Go map的重塑無疑會很對他們的胃口。

本文涉及的源碼可以在這里[21]下載。

6. 參考資料

  • runtime: use SwissTable[22] - https://github.com/golang/go/issues/54766
  • swiss table benchmark result[23] - https://gist.github.com/aclements/9fb32ac0a287d2ff360f1bc166cdf4b8
  • Swisstable, a Quick and Dirty Description[24] - https://faultlore.com/blah/hashbrown-tldr/
  • Swiss Tables Design Notes[25] - https://abseil.io/about/design/swisstables
  • Designing a Fast, Efficient, Cache-friendly Hash Table, Step by Step[26] - https://www.youtube.com/watch?v=ncHmEUmJZf4
  • Abseil's Open Source Hashtables: 2 Years In[27] - https://www.youtube.com/watch?v=JZE3_0qvrMg
  • Swiss Tables and absl::Hash[28] - https://abseil.io/blog/20180927-swisstables
  • SwissMap: A smaller, faster Golang Hash Table[29] - https://www.dolthub.com/blog/2023-03-28-swiss-map/
  • What is a Hash Map?[30] - https://www.freecodecamp.org/news/what-is-a-hash-map/
  • Inside the Map Implementation[31] - https://www.youtube.com/watch?v=Tl7mi9QmLns

參考資料

[1] 2024月11月5日的Go compiler and runtime meeting notes: https://github.com/golang/go/issues/43930#issuecomment-2458068992

[2] 使用Swiss table重新實現Go map: https://github.com/golang/go/issues/54766

[3] Go 1.24里程碑: https://github.com/golang/go/milestone/322

[4] Google工程師Matt Kulukundis在2017年CppCon大會上詳細介紹了他們在Swiss Table上的工作: https://www.youtube.com/watch?v=ncHmEUmJZf4

[5] C++ Abseil庫的flat_hash_map(可替換std::unordered_map): https://abseil.io/about/design/swisstables

[6] Rust標準庫Hashmap的默認實現: https://github.com/rust-lang/hashbrown

[7] Michael Pratt: https://github.com/prattmic

[8] 哈希表: https://en.wikipedia.org/wiki/Hash_table

[9] map實現原理: https://www.youtube.com/watch?v=Tl7mi9QmLns

[10] 《Go語言第一課》: http://gk.link/a/10AVZ

[11] 不再縮容(shrink)了: https://github.com/golang/go/issues/20135

[12] Google的開源C++ library Abseil: https://abseil.io/

[13] 開發者的演講視頻: https://www.youtube.com/watch?v=ncHmEUmJZf4

[14] Swiss table的實現在2018年9月正式開源: https://abseil.io/blog/20180927-swisstables

[15] SIMD指令: https://tonybai.com/2024/07/21/simd-in-go

[16] GOEXPERIMENT=swissmap默認已經打開: https://github.com/golang/go/commit/99d60c24e23d4d97ce51b1ee5660b60a5651693a

[17] gomapbench repo: https://github.com/zhangyunhao116/gomapbench

[18] 《Go語言第一課》: http://gk.link/a/10AVZ

[19] Go 1.24: https://github.com/golang/go/milestone/322

[20] 自定義iterator: https://tonybai.com/2024/06/24/range-over-func-and-package-iter-in-go-1-23/

[21] 這里: https://github.com/bigwhite/experiments/tree/master/swiss-table-map

[22] runtime: use SwissTable: https://github.com/golang/go/issues/54766

[23] swiss table benchmark result: https://gist.github.com/aclements/9fb32ac0a287d2ff360f1bc166cdf4b8

[24] Swisstable, a Quick and Dirty Description: https://faultlore.com/blah/hashbrown-tldr/

[25] Swiss Tables Design Notes: https://abseil.io/about/design/swisstables

[26] Designing a Fast, Efficient, Cache-friendly Hash Table, Step by Step: https://www.youtube.com/watch?v=ncHmEUmJZf4

[27] Abseil's Open Source Hashtables: 2 Years In: https://www.youtube.com/watch?v=JZE3_0qvrMg

[28] Swiss Tables and absl::Hash: https://abseil.io/blog/20180927-swisstables

[29] SwissMap: A smaller, faster Golang Hash Table: https://www.dolthub.com/blog/2023-03-28-swiss-map/

[30] What is a Hash Map?: https://www.freecodecamp.org/news/what-is-a-hash-map/

[31] Inside the Map Implementation: https://www.youtube.com/watch?v=Tl7mi9QmLns

責任編輯:武曉燕 來源: TonyBai
相關推薦

2021-12-29 11:06:25

Java代碼技巧

2013-05-22 09:38:03

GoGo語言Go性能

2023-06-26 07:08:11

RTX 3060RTX 40603DMark

2015-01-21 15:40:44

GoRuby

2025-11-12 08:55:00

AI模型推理

2025-03-10 00:00:50

2023-03-27 18:18:47

GPT-4AI

2024-12-25 14:03:03

2024-02-26 00:02:00

開發Go

2021-09-27 08:16:38

Webpack 前端Cache

2023-10-23 20:03:02

Go緩存

2014-07-17 14:08:37

阿里云

2014-10-08 10:37:41

SQLite

2024-04-07 07:46:00

谷歌架構

2012-03-16 09:26:13

LVMXen虛擬機

2025-05-08 00:00:00

RedisRedis 8.0數據庫

2024-12-05 10:18:48

2023-03-01 15:14:48

數據集機器學習

2022-02-11 17:45:47

Raspberry操作系統樹莓派
點贊
收藏

51CTO技術棧公眾號

欧美亚洲愉拍一区二区| 国产日韩精品一区二区浪潮av | 69xxxx欧美| 狠狠久久亚洲欧美| 97久久精品视频| 国产日韩精品中文字无码| 日韩一区二区三区精品视频第3页 日韩一区二区三区精品 | 亚洲精品国产日韩| 亚洲欧美日韩天堂一区二区| av中文字幕网址| 黄在线观看免费网站ktv| 91天堂素人约啪| 成人观看高清在线观看免费| 国产精品成人久久| 欧美一区二区性| 欧美变态tickle挠乳网站| 亚洲中文字幕无码不卡电影| 成人国产免费电影| 国产色产综合色产在线视频| 99视频免费观看| 中文字幕久久久久| 99精品热视频只有精品10| 精品国偷自产在线视频99| 国产精品久久AV无码| 亚洲高清影院| 色婷婷av一区二区| 国产aaa免费视频| 欧美性天天影视| 久久久综合九色合综国产精品| 国产精品专区一| 久久国产视频精品| 亚洲黄色大片| 久色乳综合思思在线视频| 自拍偷拍视频亚洲| 奇米777国产一区国产二区| 91精品国产综合久久婷婷香蕉| 已婚少妇美妙人妻系列| 超碰在线97国产| 亚洲欧美一区二区久久| 亚洲免费久久| youjizz在线播放| 久久蜜桃香蕉精品一区二区三区| 精品一区二区三区日本| 精品久久久久中文慕人妻| 蜜臀av性久久久久蜜臀aⅴ流畅| 国产成人精品一区二区| 在线视频一区二区三区四区| 亚洲激情午夜| 久久久久久久久久久免费| 午夜爽爽爽男女免费观看| 九九热线有精品视频99| 国产视频精品一区二区三区| 一级特级黄色片| 精品国产乱子伦一区二区| 日韩一区二区三区在线视频| 国产欧美精品一二三| 97久久精品一区二区三区的观看方式| 欧美性色黄大片| 天天操天天爱天天爽| 欧美日韩亚洲国产| 欧美日韩不卡一区| 亚洲综合20p| 日韩一区网站| 精品捆绑美女sm三区| 在线精品视频播放| 美国十次av导航亚洲入口| 亚洲精品国产电影| 超碰97人人干| 成人嫩草影院| 久久久999精品视频| 日韩a级片在线观看| 国内久久视频| 国产91对白在线播放| 久久精品久久久久久久| 免费观看一级特黄欧美大片| 成人午夜在线视频一区| 亚洲高清精品视频| 成人国产亚洲欧美成人综合网| 国产视频一区二区三区四区| 天堂在线免费av| 国产欧美va欧美不卡在线| 色撸撸在线观看| 55av亚洲| 欧美私人免费视频| 中文字幕在线观看视频www| 国产成人一二| 国产一区二区三区18 | 亚洲亚洲精品在线观看| 女人天堂av手机在线| 中韩乱幕日产无线码一区| 欧美精品日韩综合在线| 69xxx免费视频| 伊人久久大香线蕉无限次| 色偷偷噜噜噜亚洲男人| 久久精品国产亚洲av无码娇色| 夜久久久久久| 国产欧美精品日韩精品| 亚洲大尺度视频| 久久久一区二区三区| 中文字幕欧美人与畜| 国产资源在线观看入口av| 欧美日韩成人高清| 国产精品边吃奶边做爽| 91tv官网精品成人亚洲| 欧美中文字幕在线播放| a级片在线免费看| 久久久不卡影院| 日韩欧美精品免费| 欧美美女福利视频| 亚洲精品一区二区网址| 免费黄色国产视频| 国产精品尤物| 成人女人免费毛片| 天天在线视频色| 动漫精品一区二区| 自拍一级黄色片| 欧美日韩精品一区二区视频| 55夜色66夜色国产精品视频| 亚洲爆乳无码一区二区三区| 国产精品美女视频| 欧美日韩在线视频一区二区三区| 一级欧美视频| 一色桃子一区二区| 国产精品久免费的黄网站| 国产麻豆日韩欧美久久| 午夜精品一区二区在线观看| 欧美男男激情videos| 日韩欧美中文字幕一区| 乱老熟女一区二区三区| 人妖欧美一区二区| 欧洲久久久久久| 色是在线视频| 亚洲第一区中文99精品| 色婷婷在线视频观看| 日韩高清一区二区| 欧美日韩国产一二| 国产精品论坛| 亚洲护士老师的毛茸茸最新章节| 久久久久国产精品夜夜夜夜夜| 国产乱一区二区| 在线观看日韩片| 欧美成人高清视频在线观看| 中文字幕精品av| 欧美成人精品网站| 亚洲国产精品激情在线观看| 成人黄色一区二区| 国产真实有声精品录音| 日本精品久久久| 国内av一区二区三区| 欧美性色19p| 男人舔女人下部高潮全视频| 日韩精品视频网| 四虎永久国产精品| 国产精品久久久久久久久免费高清| 国产亚洲欧美日韩一区二区| 免费黄色一级大片| 国产精品视频第一区| 国模私拍视频在线观看| 久久久久久久久99精品大| 亚洲综合社区网| 蜜臀av国内免费精品久久久夜夜| 精品成人在线观看| 影音先锋亚洲天堂| 久久久精品tv| 亚洲免费999| 欧美激情1区2区| 国产伦理一区二区三区| 欧美大胆性生话| 深夜福利91大全| 精品国产av鲁一鲁一区| 亚洲国产成人porn| 国精产品一区二区三区| 极品少妇xxxx偷拍精品少妇| 真实国产乱子伦对白视频| 欧洲vs亚洲vs国产| 国产欧美精品一区二区三区介绍 | 精品国精品国产自在久国产应用| 国产精品视频26uuu| 国产1区在线| 亚洲国产精品成人va在线观看| 国产成人无码av| 成人欧美一区二区三区视频网页| 精品1卡二卡三卡四卡老狼| 久久精品道一区二区三区| 一级二级三级欧美| 国产精品久av福利在线观看| 国产精品国产三级国产aⅴ9色| av片在线观看| 亚洲美女激情视频| 国产又大又粗又长| 亚洲区一区二区三| 99国产欧美另类久久久精品| www.国产视频.com| 亚洲免费播放| 中文字幕欧美人与畜| 亚洲桃色综合影院| 91免费电影网站| 香蕉成人av| 欧美富婆性猛交| 一区二区高清不卡| 日韩av在线看| 国产高清第一页| 在线观看国产91| 精品一区免费观看| 综合久久国产九一剧情麻豆| av直播在线观看| 成人免费黄色大片| 97超碰人人看| 蜜臀va亚洲va欧美va天堂| 成人av一级片| 欧美深夜福利| 国产精品波多野结衣| 视频一区中文| 久久精品国产精品青草色艺| 日本在线一区二区三区| 国产成人小视频在线观看| 1234区中文字幕在线观看| 欧美成人免费大片| 免费看美女视频在线网站| 亚洲人av在线影院| 五月婷婷综合久久| 亚洲成人久久电影| 国产浮力第一页| 91精品国产综合久久国产大片| 懂色av蜜臀av粉嫩av喷吹| 精品久久久免费| 国产午夜精品无码| 亚洲精品视频在线看| frxxee中国xxx麻豆hd| 国产精品免费aⅴ片在线观看| wwwwww日本| 91在线播放网址| 91丝袜在线观看| 99视频一区二区三区| 久草视频福利在线| 成人精品高清在线| 国内精品免费视频| 粉嫩aⅴ一区二区三区四区| 波多野结衣电影免费观看| 国产精品一区二区视频| 一级网站在线观看| 国产一区二区三区高清播放| 中文字幕22页| 国内精品伊人久久久久av影院| 一级做a免费视频| 久久精品久久综合| 中文字幕永久有效| 激情久久久久久久久久久久久久久久| 女人高潮一级片| 国产在线国偷精品产拍免费yy| 亚洲网中文字幕| 国产福利91精品一区二区三区| 日本中文字幕精品| 成人爱爱电影网址| 91精品国产自产| 国产嫩草影院久久久久| 自拍偷拍你懂的| 亚洲视频一二三| 久久久久久久久久99| 亚洲高清免费一级二级三级| 一级免费在线观看| 欧美午夜www高清视频| 青青国产在线视频| 欧美军同video69gay| 精品国产无码一区二区| 精品成人一区二区| 嫩草精品影院| 日韩中文字幕在线播放| 肉肉视频在线观看| 91wwwcom在线观看| 成人影院在线免费观看| 川上优av一区二区线观看| 伊人www22综合色| 欧美男人的天堂| 色欧美自拍视频| av动漫在线免费观看| 国产精品婷婷| 午夜剧场高清版免费观看| 国产99久久久国产精品潘金| 在线观看日韩精品视频| 中文幕一区二区三区久久蜜桃| 国内偷拍精品视频| 欧美日韩一区免费| 91tv国产成人福利| 精品播放一区二区| jizz视频在线观看| 欧美大片大片在线播放| 蜜桃成人精品| 亚洲一区制服诱惑| 蜜桃精品噜噜噜成人av| 好色先生视频污| 男人的天堂亚洲在线| 久久精品视频在线观看免费| 久久亚洲精华国产精华液| 免费看一级大片| 色婷婷国产精品| 99国产精品99| 亚洲男人天堂视频| 中文字幕免费高清电视剧网站在线观看| 欧美一级视频免费在线观看| 99久久久国产| 欧美一进一出视频| 激情综合亚洲| 激情五月婷婷基地| 久久综合九色欧美综合狠狠| 国产成人av免费在线观看| 在线日韩国产精品| 色婷婷av一区二区三区之e本道| 最近2019中文字幕大全第二页| 99色在线观看| 91成人免费视频| 99tv成人| caoporn超碰97| 91美女片黄在线| 国产在线拍揄自揄拍| 88在线观看91蜜桃国自产| 国产三级视频在线播放线观看| 久久久久久亚洲精品中文字幕| 中文成人激情娱乐网| 日日夜夜精品网站| 夜夜爽av福利精品导航| 中文字幕一区二区三区人妻在线视频| 国产精品伦一区二区三级视频| 亚洲欧美一区二区三区在线观看| 亚洲国产成人精品久久久国产成人一区| 国产黄a三级三级三级av在线看| 国产精品久久久久久久久久新婚| 亚洲v天堂v手机在线| 91好吊色国产欧美日韩在线| 国产成a人亚洲精| 欧美成人精品欧美一| 欧美一区日韩一区| 含羞草www国产在线视频| 国产日韩欧美在线播放| 第一会所亚洲原创| 成年人在线看片| 国产三级欧美三级日产三级99| 综合激情网五月| 亚洲美女av在线| 欧美日韩五码| 小说区图片区图片区另类灬| 日韩制服丝袜先锋影音| 久久久久久久久久久久久久久| 一本久道久久综合中文字幕 | 久久久影视传媒| 伊人久久久久久久久久久久| 国产亚洲精品va在线观看| 性欧美videohd高精| 色姑娘综合网| 老司机午夜精品| 麻豆精品国产免费| 5566中文字幕一区二区电影| 在线黄色网页| 国内精品视频免费| 噜噜噜躁狠狠躁狠狠精品视频 | 色爱综合网欧美| 国产亚洲色婷婷久久| 一区二区三区久久久| 丰满岳乱妇国产精品一区| 97在线看免费观看视频在线观看| 自拍亚洲一区| 国产三级三级看三级| 亚洲视频香蕉人妖| 黄色小视频免费在线观看| 欧美有码在线视频| 欧美亚洲国产激情| 免费成人黄色大片| 一二三四区精品视频| 午夜在线视频免费| 国产精品久久久久不卡| 伊人青青综合网| 日b视频在线观看| 欧美系列一区二区| 曰本三级在线| 欧美二区在线看| 九九久久精品视频| 国产小视频在线看| 亚洲色图美腿丝袜| 成人自拍视频| 自慰无码一区二区三区| 国产精品天干天干在线综合| www.天堂在线| 国产suv精品一区二区| 亚洲欧洲日韩| 伊人网伊人影院| 日韩一级完整毛片| 天天免费亚洲黑人免费| 国产成人免费高清视频| 91蝌蚪国产九色| 国产xxxx孕妇| 国产福利成人在线| 国语对白精品一区二区| 无码 人妻 在线 视频| 日韩一区二区在线观看视频| 神马久久午夜| 国产成人生活片| 国产欧美视频在线观看| 色香蕉在线视频| 91欧美精品午夜性色福利在线| 先锋亚洲精品|