国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

告別性能猜謎:一份Go并發操作的成本層級清單

開發 前端
本文將這一強大的“并發成本層級”模型完整地移植并適配到Go語言的語境中,通過一系列完整、可復現的Go基準測試代碼,為你打造一份專屬Gopher的“并發成本清單”。

Go語言的并發模型以其簡潔直觀著稱,但這種簡單性背后,隱藏著一個跨越五個數量級的巨大性能鴻溝。當你的高并發服務遭遇性能瓶頸時,你是否也曾陷入“性能猜謎”的困境:是sync.Mutex太慢?是atomic操作不夠快?還是某個channel的阻塞超出了預期?我們往往依賴直覺和pprof的零散線索,卻缺乏一個系統性的框架來指導我們的判斷。

最近,我讀到一篇5年前的,名為《A Concurrency Cost Hierarchy》的C++性能分析文章,該文通過精妙的實驗,為并發操作的性能成本劃分了六個清晰的、成本呈數量級遞增的層級。這個模型如同一份性能地圖,為我們提供了告別猜謎、走向系統化優化的鑰匙。

本文將這一強大的“并發成本層級”模型完整地移植并適配到Go語言的語境中,通過一系列完整、可復現的Go基準測試代碼,為你打造一份專屬Gopher的“并發成本清單”。讀完本文,你將能清晰地識別出你的代碼位于哪個性能層級,理解其背后的成本根源,并找到通往更高性能層級的明確路徑。

注:Go運行時和調度器的精妙之處,使得簡單的按原文的模型套用變得不準確,本文將以真實的Go benchmark數據為基礎。

基準測試環境與問題設定

為了具象化地衡量不同并發策略的成本,我們將貫穿使用一個簡單而經典的問題:在多個Goroutine之間安全地對一個64位整型計數器進行遞增操作

我們將所有實現都遵循一個通用接口,并使用Go內置的testing包進行基準測試。這能讓我們在統一的環境下,對不同策略進行公平的性能比較。

下面便是包含了通用接口的基準測試代碼文件main_test.go,你可以將以下所有代碼片段整合到該文件中,然后通過go test -bench=. -benchmem命令來親自運行和驗證這些性能測試。

// main_test.go
package concurrency_levels

import (
"math/rand"
"runtime"
"sync"
"sync/atomic"
"testing"
)

// Counter 是我們將要實現的各種并發計數器的通用接口
type Counter interface {
 Inc()
 Value() int64
}

// benchmark an implementation of the Counter interface
func benchmark(b *testing.B, c Counter) {
 b.ResetTimer()
 b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
   c.Inc()
  }
 })
}

// --- 在此之下,我們將逐一添加各個層級的 Counter 實現和 Benchmark 函數 ---

注意:請將所有后續代碼片段都放在這個concurrency_levels包內)。此外,下面文中的實測數據是基于我個人的Macbook Pro(intel x86芯片)測試所得:

$go test -bench .
goos: darwin
goarch: amd64
pkg: demo
cpu: Intel(R) Core(TM) i5-8257U CPU @ 1.40GHz
BenchmarkMutexCounter-8                 21802486         53.60 ns/op
BenchmarkAtomicCounter-8                75927309         15.55 ns/op
BenchmarkCasCounter-8                   12468513         98.30 ns/op
BenchmarkYieldingTicketLockCounter-8      401073       3516 ns/op
BenchmarkBlockingTicketLockCounter-8      986607       1619 ns/op
BenchmarkSpinningTicketLockCounter-8     6712968        154.6 ns/op
BenchmarkShardedCounter-8               201299956          5.997 ns/op
BenchmarkGoroutineLocalCounter-8        1000000000          0.2608 ns/op
PASS
ok   demo 10.128s

Level 2: 競爭下的原子操作與鎖 - 緩存一致性的代價 (15ns - 100ns)

這是大多數并發程序的性能基準線。其核心成本源于現代多核CPU的緩存一致性協議。當多個核心試圖修改同一塊內存時,它們必須通過總線通信,爭奪緩存行的“獨占”所有權。這個過程被稱為“緩存行彈跳”(Cache Line Bouncing),帶來了不可避免的硬件級延遲。

Go實現1: atomic.AddInt64 (實測: 15.55 ns/op)

// --- Level 2: Atomic ---
type AtomicCounter struct {
 counter int64
}
func (c *AtomicCounter) Inc() { atomic.AddInt64(&c.counter, 1) }
func (c *AtomicCounter) Value() int64 { return atomic.LoadInt64(&c.counter) }
func BenchmarkAtomicCounter(b *testing.B) { benchmark(b, &AtomicCounter{}) }

分析atomic.AddInt64直接映射到CPU的原子加指令(如x86的LOCK XADD),是硬件層面最高效的競爭處理方式。15.5ns的成績展示了在高競爭下,硬件仲裁緩存行訪問的驚人速度。

Go實現2: sync.Mutex (實測: 53.60 ns/op)

// --- Level 2: Mutex ---
type MutexCounter struct {
 mu      sync.Mutex
 counter int64
}

func (c *MutexCounter) Inc() { c.mu.Lock(); c.counter++; c.mu.Unlock() }
func (c *MutexCounter) Value() int64 { c.mu.Lock(); defer c.mu.Unlock(); return c.counter }
func BenchmarkMutexCounter(b *testing.B) { benchmark(b, &MutexCounter{}) }

分析: Go的sync.Mutex是一個經過高度優化的混合鎖。在競爭激烈時,它會先進行幾次CPU自旋,若失敗再通過調度器讓goroutine休眠。53.6ns的成本包含了自旋的CPU消耗以及可能的調度開銷,比純硬件原子操作慢,但依然高效。

Go實現3: CAS循環 (實測: 98.30 ns/op)

// --- Level 2: CAS ---
type CasCounter struct {
 counter int64
}
func (c *CasCounter) Inc() {
for {
  old := atomic.LoadInt64(&c.counter)
if atomic.CompareAndSwapInt64(&c.counter, old, old+1) {
   return
  }
 }
}

func (c *CasCounter) Value() int64 { return atomic.LoadInt64(&c.counter) }
func BenchmarkCasCounter(b *testing.B) { benchmark(b, &CasCounter{}) }

分析出乎意料的是,CAS循環比sync.Mutex慢。 這是因為在高競爭下,CompareAndSwap失敗率很高,導致for循環多次執行。每次循環都包含一次Load和一次CompareAndSwap,多次的原子操作累加起來的開銷,超過了sync.Mutex內部高效的自旋+休眠策略。這也從側面證明了Go的sync.Mutex針對高競爭場景做了非常出色的優化。

Level 3 & 4: Scheduler深度介入 - Goroutine休眠與喚醒 (1,600ns - 3,600ns)

當我們強制goroutine進行休眠和喚醒,而不是讓sync.Mutex自行決定時,性能會迎來一個巨大的數量級下降。這里的成本來自于Go調度器執行的復雜工作:保存goroutine狀態、將其移出運行隊列、并在未來某個時間點再將其恢復。

Go實現1: 使用sync.Cond的阻塞鎖 (實測: 1619 ns/op)

// --- Level 3: Blocking Ticket Lock ---
type BlockingTicketLockCounter struct {
 mu sync.Mutex; cond *sync.Cond; ticket, turn, counter int64
}
func NewBlockingTicketLockCounter() *BlockingTicketLockCounter {
 c := &BlockingTicketLockCounter{}; c.cond = sync.NewCond(&c.mu); return c
}
func (c *BlockingTicketLockCounter) Inc() {
 c.mu.Lock()
 myTurn := c.ticket; c.ticket++
for c.turn != myTurn { c.cond.Wait() } // Goroutine休眠,等待喚醒
 c.mu.Unlock()
 atomic.AddInt64(&c.counter, 1) // 鎖外遞增
 c.mu.Lock()
 c.turn++; c.cond.Broadcast(); c.mu.Unlock()
}
func (c *BlockingTicketLockCounter) Value() int64 { c.mu.Lock(); defer c.mu.Unlock(); return c.counter }
func BenchmarkBlockingTicketLockCounter(b *testing.B) { benchmark(b, NewBlockingTicketLockCounter()) }

分析: 1619ns的成本清晰地展示了顯式cond.Wait()的代價。每個goroutine都會被park(休眠),然后被Broadcast unpark(喚醒)。這個過程比sync.Mutex的內部調度要重得多。

Go實現2: 使用runtime.Gosched()的公平票據鎖 (實測: 3516 ns/op)

在深入代碼之前,我們必須理解設計這種鎖的動機。在某些并發場景中,“公平性”(Fairness)是一個重要的需求。一個公平鎖保證了等待鎖的線程(或goroutine)能按照它們請求鎖的順序來獲得鎖,從而避免“饑餓”(Starvation)——即某些線程長時間無法獲得執行機會。

票據鎖(Ticket Lock) 是一種經典的實現公平鎖的算法。它的工作方式就像在銀行排隊叫號:

  1. 取號:當一個goroutine想要獲取鎖時,它原子性地獲取一個唯一的“票號”(ticket)。
  2. 等待叫號:它不斷地檢查當前正在“服務”的號碼(turn)。
  3. 輪到自己:直到當前服務號碼與自己的票號相符,它才能進入臨界區。
  4. 服務下一位:完成工作后,它將服務號碼加一,讓下一個持有票號的goroutine進入。

這種機制天然保證了“先到先得”的公平性。然而,關鍵在于“等待叫號”這個環節如何實現。YieldingTicketLockCounter選擇了一種看似“友好”的方式:在等待時調用runtime.Gosched(),主動讓出CPU給其他goroutine。我們想通過這種方式來測試:當一個并發原語的設計強依賴于Go調度器的介入時,其性能成本會達到哪個數量級。

// --- Level 3: Yielding Ticket Lock ---
type YieldingTicketLockCounter struct {
 ticket, turn uint64; _ [48]byte; counter int64
}
func (c *YieldingTicketLockCounter) Inc() {
 myTurn := atomic.AddUint64(&c.ticket, 1) - 1
 for atomic.LoadUint64(&c.turn) != myTurn {
  runtime.Gosched() // 主動讓出執行權
 }
 c.counter++; atomic.AddUint64(&c.turn, 1)
}
func (c *YieldingTicketLockCounter) Value() int64 { return c.counter }
func BenchmarkYieldingTicketLockCounter(b *testing.B) { benchmark(b, &YieldingTicketLockCounter{}) }

分析另一個意外發現:runtime.Gosched()cond.Wait()更慢! 這可能是因為cond.Wait()是一種目標明確的休眠——“等待特定信號”,調度器可以高效地處理。而runtime.Gosched()則是一種更寬泛的請求——“請調度別的goroutine”,這可能導致了更多的調度器“抖動”和不必要的上下文切換,從而產生了更高的平均成本。

Go調度器能否化解Level 5災難?

現在,我們來探討并發性能的“地獄”級別。這個級別的產生,源于一個在底層系統編程中常見,但在Go等現代托管語言中被刻意規避的設計模式:無限制的忙等待(Unbounded Spin-Wait)

在C/C++等語言中,為了在極低延遲的場景下獲取鎖,開發者有時會編寫一個“自旋鎖”(Spinlock)。它不會讓線程休眠,而是在一個緊湊的循環中不斷檢查鎖的狀態,直到鎖被釋放。這種方式的理論優勢是避免了昂貴的上下文切換,只要鎖的持有時間極短,自旋的CPU開銷就會小于一次線程休眠和喚醒的開銷。

災難的根源:超訂(Oversubscription)

自旋鎖的致命弱點在于核心超訂——當活躍的、試圖自旋的線程數量超過了物理CPU核心數時。在這種情況下,一個正在自旋的線程可能占據著一個CPU核心,而那個唯一能釋放鎖的線程卻沒有機會被調度到任何一個核心上運行。結果就是,自旋線程白白燒掉了整個CPU時間片(通常是毫-秒-級別),而程序毫無進展。這就是所謂的“鎖護航”(Lock Convoy)的極端形態。

我們的SpinningTicketLockCounter正是為了在Go的環境中復現這一經典災難場景。我們使用與之前相同的公平票據鎖邏輯,但將等待策略從“讓出CPU”(runtime.Gosched())改為最原始的“原地空轉”。我們想借此探索:Go的搶占式調度器,能否像安全網一樣,接住這個從高空墜落的性能災難?

Go實現: 自旋票據鎖 (實測: 154.6 ns/op,但在超訂下會凍結)

// --- Level "5" Mitigated: Spinning Ticket Lock ---
type SpinningTicketLockCounter struct {
 ticket, turn uint64; _ [48]byte; counter int64
}
func (c *SpinningTicketLockCounter) Inc() {
 myTurn := atomic.AddUint64(&c.ticket, 1) - 1
for atomic.LoadUint64(&c.turn) != myTurn {
/* a pure spin-wait loop */
 }
 c.counter++; atomic.AddUint64(&c.turn, 1)
}
func (c *SpinningTicketLockCounter) Value() int64 { return c.counter }
func BenchmarkSpinningTicketLockCounter(b *testing.B) { benchmark(b, &SpinningTicketLockCounter{}) }

驚人的結果與分析:

默認并發下 (-p=8, 8 goroutines on 4 cores): 性能為 154.6 ns/op。這遠非災難,而是回到了Level 2的范疇。原因是Go的搶占式調度器。它檢測到長時間運行的無函數調用的緊密循環,并強制搶占,讓其他goroutine(包括持有鎖的那個)有機會運行。這是Go的運行時提供的強大安全網,將系統性災難轉化為了性能問題。

但在嚴重超訂的情況下(通過b.SetParallelism(2)模擬16 goroutines on 4 cores):

func BenchmarkSpinningTicketLockCounter(b *testing.B) {
    // 在測試中模擬超訂場景
    // 例如,在一個8核機器上,測試時設置 b.SetParallelism(2) * runtime.NumCPU()
    // 這會讓goroutine數量遠超GOMAXPROCS
 b.SetParallelism(2)
    benchmark(b, &SpinningTicketLockCounter{})
}

我們的基準測試結果顯示,當b.SetParallelism(2)(在4核8線程機器上創建16個goroutine)時,這個測試無法完成,最終被手動中斷。這就是Level 5的真實面貌。

系統并未技術性死鎖,而是陷入了“活鎖”(Livelock)。過多的goroutine在瘋狂自旋,耗盡了所有CPU時間片。Go的搶占式調度器雖然在努力工作,但在如此極端的競爭下,它無法保證能在有效的時間內將CPU資源分配給那個唯一能“解鎖”并推動系統前進的goroutine。整個系統看起來就像凍結了一樣,雖然CPU在100%運轉,但有效工作吞吐量趨近于零。

這證明了Go的運行時安全網并非萬能。它能緩解一般情況下的忙等待,但無法抵御設計上就存在嚴重缺陷的、大規模的CPU資源濫用。

從災難到高成本:runtime.Gosched()的“救贖” (實測: 5048 ns/op)

那么,如何從Level 5的災難中“生還”?答案是:將非協作的忙等待,變為協作式等待,即在自旋循環中加入runtime.Gosched()

// --- Level 3+: Cooperative High-Cost Wait ---
type CooperativeSpinningTicketLockCounter struct {
 ticket  uint64
 turn    uint64
 _       [48]byte
 counter int64
}

func (c *CooperativeSpinningTicketLockCounter) Inc() {
 myTurn := atomic.AddUint64(&c.ticket, 1) - 1
for atomic.LoadUint64(&c.turn) != myTurn {
// 通過主動讓出,將非協作的自旋變成了協作式的等待。
  runtime.Gosched()
 }
 c.counter++
 atomic.AddUint64(&c.turn, 1)
}

func (c *CooperativeSpinningTicketLockCounter) Value() int64 {
return c.counter
}

func BenchmarkCooperativeSpinningTicketLockCounter(b *testing.B) {
 b.SetParallelism(2)
 benchmark(b, &CooperativeSpinningTicketLockCounter{})
}

性能分析與討論

基準測試結果為5048 ns/op

$go test -bench='^BenchmarkCooperativeSpinningTicketLockCounter$' -benchmem 
goos: darwin
goarch: amd64
pkg: demo
cpu: Intel(R) Core(TM) i5-8257U CPU @ 1.40GHz
BenchmarkCooperativeSpinningTicketLockCounter-8      328173       5048 ns/op        0 B/op        0 allocs/op
PASS
ok   demo 1.701s

程序不再凍結,但性能成本極高,甚至高于我們之前測試的BlockingTicketLockCounterYieldingTicketLockCounter

runtime.Gosched()在這里扮演了救世主的角色。它將一個可能導致系統停滯的活鎖問題,轉化成了一個單純的、可預測的性能問題。每個等待的goroutine不再霸占CPU,而是禮貌地告訴調度器:“我還在等,但你可以先運行別的任務。” 這保證了持有鎖的goroutine最終能獲得執行機會。

然而,這份“保證”的代價是高昂的。每次Gosched()調用都可能是一次昂貴的調度事件。在超訂的高競爭場景下,每個Inc()操作都可能觸發多次Gosched(),累加起來的成本甚至超過了sync.Cond的顯式休眠/喚醒。

因此,這個測試結果為我們的成本層級清單增加了一個重要的層次:它處于Level 3和Level 4之間,可以看作是一個“高成本的Level 3”。它展示了通過主動協作避免系統性崩潰,但為此付出了巨大的性能開銷。

Level 1: 無競爭原子操作 - 設計的力量 (~6 ns)

性能優化的關鍵轉折點在于從“處理競爭”轉向“避免競爭”。Level 1的核心思想是通過設計,將對單個共享資源的競爭分散到多個資源上,使得每次操作都接近于無競爭狀態。

Go實現:分片計數器 (Sharded Counter)

// --- Level 1: Uncontended Atomics (Sharded) ---
const numShards = 256
type ShardedCounter struct {
 shards [numShards]struct{ counter int64; _ [56]byte }
}
func (c *ShardedCounter) Inc() {
 idx := rand.Intn(numShards) // 隨機選擇一個分片
 atomic.AddInt64(&c.shards[idx].counter, 1)
}
func (c *ShardedCounter) Value() int64 {
var total int64
for i := 0; i < numShards; i++ {
  total += atomic.LoadInt64(&c.shards[i].counter)
 }
return total
}
func BenchmarkShardedCounter(b *testing.B) { benchmark(b, &ShardedCounter{}) }

性能分析與討論: 5.997 ns/op!性能實現了數量級的飛躍。通過將寫操作分散到256個獨立的、被緩存行填充(padding)保護的計數器上,我們幾乎完全消除了緩存行彈跳。Inc()的成本急劇下降到接近單次無競爭原子操作的硬件極限。代價是Value()操作變慢了,且內存占用激增。這是一個典型的空間換時間、讀性能換寫性能的權衡。

Level 0: “香草(Vanilla)”操作 - 并發的終極圣杯 (~0.26 ns)

性能的頂峰是Level 0,其特點是在熱路徑上完全不使用任何原子指令或鎖,只使用普通的加載和存儲指令(vanilla instructions)。

Go實現:Goroutine局部計數

我們通過將狀態綁定到goroutine自己的棧上,來徹底消除共享。

// --- Level 0: Vanilla Operations (Goroutine-Local) ---
func BenchmarkGoroutineLocalCounter(b *testing.B) {
var totalCounter int64
 b.ResetTimer()
 b.RunParallel(func(pb *testing.PB) {
var localCounter int64// 每個goroutine的棧上局部變量
for pb.Next() {
   localCounter++ // 在局部變量上操作,無任何同步!
  }
// 在每個goroutine結束時,將局部結果原子性地加到總數上
  atomic.AddInt64(&totalCounter, localCounter)
 })
}

性能分析與討論: 0.2608 ns/op!這個數字幾乎是CPU執行一條簡單指令的速度。在RunParallel的循環體中,localCounter++操作完全在CPU的寄存器和L1緩存中進行,沒有任何跨核通信的開銷。所有的同步成本(僅一次atomic.AddInt64)都被移到了每個goroutine生命周期結束時的冷路徑上。這種模式的本質是通過算法和數據結構的重新設計,從根本上消除共享

結論:你的Go并發操作成本清單

基于真實的Go benchmark,我們得到了這份為Gopher量身定制的并發成本清單:

等級

名稱

Go 實現范例

實測成本(ns/op)

關鍵特征

5

災難級

嚴重超訂

下的純自旋鎖

凍結/ >>100,000

Go調度器被壓垮,系統活鎖

3+

協作式高成本等待

超訂下的Gosched循環

~5,000

通過主動讓出避免活鎖,但調度開銷巨大

3&4

Scheduler深度介入

sync.Cond

, 非超訂Gosched

1,600 - 3,600

Goroutine休眠/喚醒,調度器深度介入

2

競爭下的同步

sync.Mutex

, atomic, CAS

15 - 100

默認狀態

,緩存行在多核間“彈跳”

1

無競爭原子操作

分片鎖/多計數器

~6

通過設計避免競爭,原子操作走快速路徑

0

“香草”操作

Goroutine局部變量

< 1

性能圣杯

,熱路徑無任何同步原語

有了這份清單,我們可以:

  1. 系統性地診斷:對照清單,分析你的熱點代碼究竟落在了哪個成本等級。
  2. 明確優化方向:最大的性能提升來自于從高成本層級向低成本層級的“降級”
  3. 優先重構算法:通往性能之巔(Level 1和Level 0)的道路,往往不是替換更快的鎖,而是從根本上重新設計數據流和算法

Go的運行時為我們抹平了一些最危險的底層陷阱,但也讓性能分析變得更加微妙。這份清單,希望能成為你手中那張清晰的地圖,讓你在Go的并發世界中,告別猜謎,精準導航

參考資料:https://travisdowns.github.io/blog/2020/07/06/concurrency-costs.html

本文涉及的示例源碼可以在這里下載 - https://github.com/bigwhite/experiments/tree/master/concurrency-costs

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

2016-08-24 16:55:18

DevOps結構清單

2018-08-15 13:49:06

數據分析學習Python

2020-06-08 09:15:14

前端 開發 Git

2018-05-16 09:00:00

物聯網物聯網平臺IoT

2018-10-10 09:30:29

Spring Boot知識框架

2023-03-21 09:44:34

模型AI

2018-05-22 09:07:54

數據科學語言職位

2018-03-30 10:10:11

區塊鏈數字貨幣記賬模式

2018-08-21 08:49:53

Nginx服務器配置

2023-09-26 11:03:42

數據中心服務器

2021-04-25 08:24:10

Linux系統Adobe全家桶Office套件

2023-11-24 08:00:54

工具Go模板

2019-01-15 09:34:30

MySQL高性能優化

2015-03-26 11:25:29

Linux平臺CC++

2020-07-15 15:38:15

人臉識別照片活化手機

2018-04-19 10:33:39

DevOps開源工具

2016-05-13 13:48:19

普華基礎軟件操作系統

2025-07-03 09:28:44

架構群消息開發

2019-03-24 14:14:40

代碼閱讀源代碼

2020-06-01 15:04:44

甲骨文自治數據庫
點贊
收藏

51CTO技術棧公眾號

精品国产鲁一鲁一区二区张丽| 国产伦精品一区二区三区视频金莲| 国产一区二区三区四区五区传媒| 欧美色综合影院| 日本黄大片在线观看| 国产精品丝袜视频| 美女精品国产| 欧美日韩卡一| 91精品国产手机| 国产a级片网站| 亚洲精品1234| 欧美中文在线字幕| 日韩黄色在线| 日韩h在线观看| 大片免费在线看视频| 国产精品国产三级国产有无不卡| dy888午夜| 国产精品久久国产愉拍| 久久精品精品电影网| 欧美日韩精品免费在线观看视频| 国产欧美日韩精品一区二区三区| 中文字幕一区日韩电影| 欧美大胆a人体大胆做受| 在线免费观看不卡av| 中午字幕在线观看| 一区二区三区影院| 1024亚洲| 一区二区三区在线观看欧美 | 欧美aaa一级片| 国产欧美精品国产国产专区 | 亚洲综合欧美日韩| 玖玖视频精品| 日韩视频专区| 国产精品一区二区免费不卡 | 狠狠v欧美v日韩v亚洲ⅴ| 欧美一区二区视频17c| 日本亚洲最大的色成网站www| 国产高清精品软男同| 成人高清视频在线| 九色成人在线| 欧美性猛交xxxxx水多| 午夜不卡视频| 亚洲男人天堂2024| 免费成人蒂法| 女人一区二区三区| 国产乱妇无码大片在线观看| 久无码久无码av无码| 国产欧美日韩视频在线观看| 国产特级毛片| 亚洲国产欧美一区二区丝袜黑人 | 日韩精品免费视频一区二区三区| 亚洲色图欧洲色图| 精品久久久久一区二区三区| 精品国产成人在线影院| 成人免费在线电影网| www.久久草| 成人妖精视频yjsp地址| 在线亚洲电影| 自拍偷拍免费精品| 亚洲精品久久久| 人人爽人人av| 亚洲国内精品在线| 国产精品久久久久无码av| 亚洲精品乱码久久久久久自慰| 日韩欧美国产成人一区二区| 国产精品极品在线观看| 久久一区二区精品| 亚洲乱码国产乱码精品精的特点| 福利一区二区| 日韩免费av一区二区三区| 欧美经典一区二区| 免费观看亚洲天堂| ts人妖另类在线| 亚洲aaaaaa| 久久夜色精品国产噜噜av| av天在线观看| 国产精品欧美日韩| 久久久久国产精品人| 国产在线精彩视频| 国产日韩欧美精品| 亚洲国产一区二区三区青草影视| 九九久久国产精品| 国产午夜久久av| 艳母动漫在线免费观看| 日韩欧美一级特黄在线播放| 中文字幕一区二区av| 在线影院福利| 99精品国产一区二区| 欧美午夜激情在线| 亚洲最新色图| 一本一道波多野毛片中文在线| 国产精品夜夜夜一区二区三区尤| 欧美亚洲国产日韩| 美女免费免费看网站| 国产成人亚洲精品| 精品国产乱码久久久久久天美 | 欧美精品一区二区久久婷婷| 精品一区二区在线播放| 91av亚洲| 国产va在线观看| 国产欧美一区二区在线播放| 欧美一三区三区四区免费在线看| 免费日本视频一区| 日日夜夜亚洲| 91网页版在线登录入口| 亚洲精品欧美日韩| 一本一本久久a久久精品综合小说| www.久久精品| 欧美精品一卡| 国产福利91精品一区二区| eeuss在线观看| 日韩亚洲视频| 青青草国产精品一区二区| 欧美日韩亚洲不卡| 91一区一区三区| 六月丁香婷婷激情| 日本免费不卡一区二区| 成人国产精品一区二区免费麻豆| 日日狠狠久久偷偷四色综合免费 | 国产 日韩 亚洲 欧美| 黑人欧美xxxx| 国产日韩三级在线| 国产成a人亚洲精| 国产精品一区二区三区网站| 久久久一二三| 石原莉奈在线亚洲三区| 中文字幕一区二区精品区| 亚洲无线一线二线三线区别av| 羞羞答答成人影院www| 久久99视频| 视频一区国产| 91精品啪在线观看国产手机| 精品午夜视频| www.8ⅹ8ⅹ羞羞漫画在线看| 国产在线传媒| 少妇高潮喷水在线观看| 成人在线激情视频| 久久69精品久久久久久久电影好| 在线播放日韩导航| 91极品视觉盛宴| 欧美色视频日本高清在线观看| 免费高清不卡av| 亚洲激情77| www.久久爱.com| av免费在线观看网址| 水莓100在线视频| 久久精品丝袜高跟鞋| 国产在线999| 成+人+亚洲+综合天堂| 99久久精品免费观看国产| 成人免费观看a| 亚洲精品乱码久久久久久黑人 | 亚洲女人天堂av| 亚洲一区黄色| 国产高清一级毛片在线不卡| 91在线观看免费观看| 天天操天天综合网| 99久久亚洲精品蜜臀| 水莓100国产免费av在线播放| 国产日韩av在线| 午夜精品123| 欧美大片专区| av大片在线播放| 精品国产一区二区三区麻豆免费观看完整版 | 日韩一区有码在线| 国产精品丝袜在线播放| 国产高清视频网站| 欧美专区福利在线| 亚洲综合丝袜美腿| 婷婷综合伊人| 成年人视频免费在线观看| 春色成人在线视频| 欧美日韩视频在线第一区| 国产日韩欧美在线播放不卡| 中文字幕在线三区| 丰满的少妇愉情hd高清果冻传媒| 久久精品在线播放| 亚洲精品免费电影| 91久久视频| 日韩福利一区| 天堂在线资源视频| 国产精品黄页免费高清在线观看| 日韩欧美在线视频观看| 亚洲一区区二区| 99久久er| 啊啊啊啊啊啊啊视频在线播放| 91精品在线观| 亚洲成人久久一区| 波多野结衣中文字幕一区二区三区| 精品国产麻豆| 蜜桃视频免费网站| 久久国产精品免费一区| 亚洲乱码av中文一区二区| 国产欧美一区二区精品仙草咪| 日韩国产专区| 成人影院在线看| 久久精品国产精品亚洲色婷婷| 欧美日本不卡视频| 日本精品视频网站| 欧美婷婷精品激情|