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

Sonic: Go語言的超級JSON庫,解析與編碼速度狂飆

開發 前端
Sonic是一款由字節跳動開發的一個全新的高性能、適用廣泛的 JSON 庫。在設計上借鑒了多款JSON庫,同時為了實現對標準庫的真正插拔式替換,Sonic使用了 JIT[1] (即時編譯) 。

介紹

我們在日常開發中,常常會對JSON進行序列化和反序列化。Golang提供了encoding/json包對JSON進行Marshal/Unmarshal操作。但是在大規模數據場景下,該包的性能和開銷確實會有點不夠看。在生產環境下,JSON 序列化和反序列化會被頻繁的使用到。在測試中,CPU使用率接近 10%,其中極端情況下超過 40%。因此,JSON 庫的性能是提高機器利用率的關鍵問題。

Sonic是一款由字節跳動開發的一個全新的高性能、適用廣泛的 JSON 庫。在設計上借鑒了多款JSON庫,同時為了實現對標準庫的真正插拔式替換,Sonic使用了 JIT[1] (即時編譯) 。

Sonic的特色

我們可以看出:Sonic是一個主打快的JSON庫。

  • 運行時對象綁定,無需代碼生成
  • 完備的 JSON 操作 API
  • 快,更快,還要更快!

Sonic的設計

  1. 針對編解碼動態匯編的函數調用開銷,使用 JIT 技術在運行時組裝與模式對應的字節碼(匯編指令) ,最終將其以 Golang 函數的形式緩存在堆外內存上。
  2. 針對大數據和小數據共存的實際場景,使用預處理判斷(字符串大小、浮點數精度等)將 SIMD 與標量指令相結合,從而實現對實際情況的最佳適應。
  3. 對于 Golang 語言編譯優化的不足,使用 C/Clang 編寫和編譯核心計算函數,并且開發了一套 asm2asm[2] 工具,將經過充分優化的 x86 匯編代碼轉換為 Plan9 格式,最終加載到 Golang 運行時中。
  4. 考慮到解析和跳過解析之間的速度差異很大, 惰性加載機制當然也在 AST 解析器中使用了,但以一種更具適應性和高效性的方式來降低多鍵查詢的開銷。

在細節上,Sonic進行了一些進一步的優化:

  1. 由于 Golang 中的原生匯編函數不能被內聯,發現其成本甚至超過了 C 編譯器的優化所帶來的改善。所以在 JIT 中重新實現了一組輕量級的函數調用:

全局函數表+靜態偏移量,用于調用指令

使用寄存器傳遞參數

  1. Sync.Map 一開始被用來緩存編解碼器,但是對于準靜態(讀遠多于寫),元素較少(通常不足幾十個)的場景,它的性能并不理想,所以使用開放尋址哈希和 RCU 技術重新實現了一個高性能且并發安全的緩存。

安裝使用

當前我使用的go version是1.21。

官方建議的版本:

  • Go 1.16~1.21
  • Linux / MacOS / Windows(需要 Go1.17 以上)
  • Amd64 架構
# 下載sonic依賴
$ go get github.com/bytedance/sonic

基本使用

sonic提供了許多功能。本文僅列舉其中較為有特色的功能。感興趣的同學可以去看一下官方的examples

序列化/反序列化

sonic的使用類似于標準包encoding/json包的使用.

func base() {
 m := map[string]interface{}{
  "name": "z3",
  "age":  20,
 }
 
 // sonic序列化
 byt, err := sonic.Marshal(&m)
 if err != nil {
  log.Println(err)
 }
 fmt.Printf("json: %+v\n", string(byt))

 // sonic反序列化
 um := make(map[string]interface{})
 err = sonic.Unmarshal(byt, &um)
 if err != nil {
  log.Println(err)
 }
 fmt.Printf("unjson: %+v\n", um)
}

// print
// json: {"name":"z3","age":20}
// unjson: map[age:20 name:z3]

sonic還支持流式的輸入輸出

Sonic 支持解碼 io.Reader 中輸入的 json,或將對象編碼為 json 后輸出至 io.Writer,以處理多個值并減少內存消耗

func base() {
 m := map[string]interface{}{
  "name": "z3",
  "age":  20,
 }

 // 流式io編解碼
 // 編碼
 var encbuf bytes.Buffer
 enc := sonic.ConfigDefault.NewEncoder(&encbuf)
 if err := enc.Encode(m); err != nil {
  log.Fatal(err)
 } else {
  fmt.Printf("cutomize encoder: %+v", encbuf.String())
 }

 // 解碼
 var decbuf bytes.Buffer
 decbuf.WriteString(encbuf.String())
 clear(m)

 dec := sonic.ConfigDefault.NewDecoder(&decbuf)
 if err := dec.Decode(&m); err != nil {
  log.Fatal(err)
 } else {
  fmt.Printf("cutomize decoder: %+v\n", m)
 }
}

// print
// cutomize encoder: {"name":"z3","age":20}
// cutomize decoder: map[age:20 name:z3]

配置

在上面的自定義流式編碼解碼器,細心的朋友可能看到我們創建編碼器和解碼器的時候,是通過sonic.ConfigDefault.NewEncoder() / sonic.ConfigDefault.NewDecoder()這兩個函數進行調用的。那么sonic.ConfigDefault是什么?

我們可以通過查看源碼:

var (
    // ConfigDefault is the default config of APIs, aiming at efficiency and safty.
    // ConfigDefault api的默認配置,針對效率和安全。
    ConfigDefault = Config{}.Froze()
 
    // ConfigStd is the standard config of APIs, aiming at being compatible with encoding/json.
    // ConfigStd是api的標準配置,旨在與encoding/json兼容。
    ConfigStd = Config{
        EscapeHTML : true,
        SortMapKeys: true,
        CompactMarshaler: true,
        CopyString : true,
        ValidateString : true,
    }.Froze()
 
    // ConfigFastest is the fastest config of APIs, aiming at speed.
    // ConfigFastest是api的最快配置,旨在提高速度。
    ConfigFastest = Config{
        NoQuoteTextMarshaler: true,
    }.Froze()
)

sonic提供了三種常用的Config配置。這些配置中對一些場景已經預定義好了對應的Config。

其實我們使用的sonic.Marshal()函數就是調用了默認的ConfigDefault

// Marshal returns the JSON encoding bytes of v.
func Marshal(val interface{}) ([]byte, error) {
    return ConfigDefault.Marshal(val)
}

// Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v.
// NOTICE: This API copies given buffer by default,
// if you want to pass JSON more efficiently, use UnmarshalString instead.
func Unmarshal(buf []byte, val interface{}) error {
    return ConfigDefault.Unmarshal(buf, val)
}

但是在一些場景下我們不滿足于sonic預定義的三個Config。此時我們可以定義自己的Config進行個性化的編碼和解碼。

首先先看一下Config的結構。

// Config is a combination of sonic/encoder.Options and sonic/decoder.Options
type Config struct {
    // EscapeHTML indicates encoder to escape all HTML characters 
    // after serializing into JSON (see https://pkg.go.dev/encoding/json#HTMLEscape).
    // WARNING: This hurts performance A LOT, USE WITH CARE.
    EscapeHTML                    bool
    // SortMapKeys indicates encoder that the keys of a map needs to be sorted 
    // before serializing into JSON.
    // WARNING: This hurts performance A LOT, USE WITH CARE.
    SortMapKeys                   bool
    // CompactMarshaler indicates encoder that the output JSON from json.Marshaler 
    // is always compact and needs no validation 
    CompactMarshaler              bool
    // NoQuoteTextMarshaler indicates encoder that the output text from encoding.TextMarshaler 
    // is always escaped string and needs no quoting
    NoQuoteTextMarshaler          bool
    // NoNullSliceOrMap indicates encoder that all empty Array or Object are encoded as '[]' or '{}',
    // instead of 'null'
    NoNullSliceOrMap              bool
    // UseInt64 indicates decoder to unmarshal an integer into an interface{} as an
    // int64 instead of as a float64.
    UseInt64                      bool
    // UseNumber indicates decoder to unmarshal a number into an interface{} as a
    // json.Number instead of as a float64.
    UseNumber                     bool
    // UseUnicodeErrors indicates decoder to return an error when encounter invalid
    // UTF-8 escape sequences.
    UseUnicodeErrors              bool
    // DisallowUnknownFields indicates decoder to return an error when the destination
    // is a struct and the input contains object keys which do not match any
    // non-ignored, exported fields in the destination.
    DisallowUnknownFields         bool
    // CopyString indicates decoder to decode string values by copying instead of referring.
    CopyString                    bool
    // ValidateString indicates decoder and encoder to valid string values: decoder will return errors 
    // when unescaped control chars(\u0000-\u001f) in the string value of JSON.
    ValidateString                    bool
}

由于字段較多。筆者就選擇幾個字段進行演示,其他字段使用方式都是一致。

假設我們希望對JSON序列化按照key進行排序以及將JSON編碼成緊湊的格式。我們可以配置Config進行Marshal操作

func base() {
 snc := sonic.Config{
  CompactMarshaler: true,
  SortMapKeys:      true,
 }.Froze()

 snc.Marshal(obj)
}

考慮到排序帶來的性能損失(約 10% ), sonic 默認不會啟用這個功能。

Sonic 默認將基本類型( struct , map 等)編碼為緊湊格式的 JSON ,除非使用 json.RawMessage or json.Marshaler 進行編碼:sonic 確保輸出的 JSON 合法,但出于性能考慮,不會加工成緊湊格式。我們提供選項 encoder.CompactMarshaler 來添加此過程,

Ast.Node

sonic提供了Ast.Node的功能。Sonic/ast.Node 是完全獨立的 JSON 抽象語法樹庫。它實現了序列化和反序列化,并提供了獲取和修改通用數據的魯棒的 API。

先來簡單介紹一下Ast.Node:ast.Node 通常指的是編程語言中的抽象語法樹(Abstract Syntax Tree)節點。抽象語法樹是編程語言代碼在編譯器中的內部表示,它以樹狀結構展現代碼的語法結構,便于編譯器進行語法分析、語義分析、優化等操作。

在很多編程語言的編譯器或解釋器實現中,抽象語法樹中的每個元素(節點)都會有對應的數據結構表示,通常這些數據結構會被稱為 ast.Node 或類似的名字。每個 ast.Node 表示源代碼中的一個語法結構,如表達式、語句、函數聲明等。

抽象語法樹的節點可以包含以下信息:

  • 節點的類型:例如表達式、語句、函數調用等。
  • 節點的內容:節點所代表的源代碼的內容。
  • 子節點:一些節點可能包含子節點,這些子節點也是抽象語法樹的節點,用于構建更復雜的語法結構。
  • 屬性:一些節點可能會包含附加的屬性,如變量名、操作符類型等。

我們通過幾個案例理解一下Ast.Node的使用。

準備數據

data := `{"name": "z3","info":{"num": [11,22,33]}}`

將數據轉換為Ast.Node

通過傳入bytes或者string返回一個Ast.Node。其中你可以指定path獲取JSON中的子路徑元素。

每個路徑參數必須是整數或者字符串

  • 整數是目標索引(>=0),表示以數組形式搜索當前節點。
  • 字符串為目標key,表示搜索當前節點為對象。
// 函數簽名:
func Get(src []byte, path ...interface{}) (ast.Node, error) {
    return GetFromString(string(src), path...)
}
// GetFromString與Get相同,只是src是字符串,這樣可以減少不必要的內存拷貝。
func GetFromString(src string, path ...interface{}) (ast.Node, error) {
    return ast.NewSearcher(src).GetByPath(path...)
}

獲取當前節點的完整數據

func base() {
 data := `{"name": "z3","info":{"num": [11,22,33]}}`

 // no path return all json string
 root, err := sonic.GetFromString(data)
 if err != nil {
  log.Panic(err)
 }
 if raw, err := root.Raw(); err != nil {
  log.Panic(err)
 } else {
  log.Println(raw)
 }
}

// print
// 2023/08/26 17:15:52 {"name": "z3","info":{"num": [11,22,33]}}

根據path或者索引獲取數據

func base() {
 data := `{"name": "z3","info":{"num": [11,22,33]}}`

 // no path return all json string
 root, err := sonic.GetFromString(data)
 if err != nil {
  log.Panic(err)
 }

    // according to path(根據key,查詢當前node下的元素)
 if path, err := root.GetByPath("name").Raw(); err != nil {
  log.Panic(err)
 } else {
  log.Println(path)
 }

 // indexOrget (同時提供index和key進行索引和key的匹配)
 if path, err := root.IndexOrGet(1, "info").Raw(); err != nil {
  log.Panic(err)
 } else {
  log.Println(path)
 }

    // index (按照index進行查找當前node下的元素)
    // root.Index(1).Index(0).Raw()意味著
    // root.Index(1) == "info"
    // root.Index(1).Index(0) == "num"
    // root.Index(1).Index(0).Raw() == "[11,22,33]"
 if path, err := root.Index(1).Index(0).Raw(); err != nil {
  log.Panic(err)
 } else {
  log.Println(path)
 }

}

// print
// 2023/08/26 17:17:49 "z3"
// 2023/08/26 17:17:49 {"num": [11,22,33]}
// 2023/08/26 17:17:49 [11,22,33]

Ast.Node支持鏈式調用。故我們可以從root node節點,根據path路徑向下搜索指定的元素。

index和key混用

user := root.GetByPath("statuses", 3, "user")  // === root.Get("status").Index(3).Get("user")

根據path進行修改數據

func base() {
 data := `{"name": "z3","info":{"num": [11,22,33]}}`

 // no path return all json string
 root, err := sonic.GetFromString(data)
 if err != nil {
  log.Panic(err)
 }

 // according to path
 if path, err := root.GetByPath("name").Raw(); err != nil {
  log.Panic(err)
 } else {
  log.Println(path)
 }

 // indexOrget (同時提供index和key進行索引和key的匹配)
 if path, err := root.IndexOrGet(1, "info").Raw(); err != nil {
  log.Panic(err)
 } else {
  log.Println(path)
 }

 // index
 if path, err := root.Index(1).Index(0).Raw(); err != nil {
  log.Panic(err)
 } else {
  log.Println(path)
 }

 // set
    // ast提供了很多go類型轉換node的函數
 if _, err := root.Index(1).SetByIndex(0, ast.NewArray([]ast.Node{
  ast.NewNumber("101"),
  ast.NewNumber("202"),
 })); err != nil {
  log.Panic(err)
 }

 raw, _ := root.Raw()
 log.Println(raw)
}

// print
// 2023/08/26 17:23:55 "z3"
// 2023/08/26 17:23:55 {"num": [11,22,33]}
// 2023/08/26 17:23:55 [11,22,33]
// 2023/08/26 17:23:55 {"name":"z3","info":{"num":[101,202]}}

序列化

func base() {
 
 data := `{"name": "z3","info":{"num": [11,22,33]}}`

 // no path return all json string
 root, err := sonic.GetFromString(data)
 if err != nil {
  log.Panic(err)
 }
 bts, _ := root.MarshalJSON()
 log.Println("Ast.Node(Marshal): ", string(bts))

 btes, _ := json.Marshal(&root)
 log.Println("encoding/json (Marshal): ", string(btes))

}

// print
// 2023/08/26 17:39:06 Ast.Node(Marshal):  {"name": "z3","info":{"num": [11,22,33]}}    
// 2023/08/26 17:39:06 encoding/json (Marshal):  {"name":"z3","info":{"num":[11,22,33]}}

?: 使用json.Marshal() (必須傳遞指向節點的指針)

API

Ast.Node提供了許多有特色的API,感興趣的朋友可以去試一下。

  • 合法性檢查:Check(), Error(), Valid(), Exist()
  • 索引:Index(), Get(), IndexPair(), IndexOrGet(), GetByPath()
  • 轉換至 go 內置類型:Int64(), Float64(), String(), Number(), Bool(), Map[UseNumber|UseNode](), Array[UseNumber|UseNode](), Interface[UseNumber|UseNode]()
  • go 類型打包:NewRaw(), NewNumber(), NewNull(), NewBool(), NewString(), NewObject(), NewArray()
  • 迭代:Values(), Properties(), ForEach(), SortKeys()
  • 修改:Set(), SetByIndex(), Add()

最佳實踐

預熱

由于 Sonic 使用 golang-asm 作為 JIT 匯編器,這個庫并不適用于運行時編譯,第一次運行一個大型模式可能會導致請求超時甚至進程內存溢出。為了更好地穩定性,我們建議在運行大型模式或在內存有限的應用中,在使用 Marshal()/Unmarshal() 前運行 Pretouch()。

拷貝字符串

當解碼 沒有轉義字符的字符串時, sonic 會從原始的 JSON 緩沖區內引用而不是復制到新的一個緩沖區中。這對 CPU 的性能方面很有幫助,但是可能因此在解碼后對象仍在使用的時候將整個 JSON 緩沖區保留在內存中。實踐中我們發現,通過引用 JSON 緩沖區引入的額外內存通常是解碼后對象的 20% 至 80% ,一旦應用長期保留這些對象(如緩存以備重用),服務器所使用的內存可能會增加。我們提供了選項 decoder.CopyString() 供用戶選擇,不引用 JSON 緩沖區。這可能在一定程度上降低 CPU 性能

func base() {
    // 在sonic.Config中進行配置
 snc := sonic.Config{
  CopyString: true,
 }.Froze()
}

傳遞字符串還是字節數組

為了和 encoding/json 保持一致,我們提供了傳遞 []byte 作為參數的 API ,但考慮到安全性,字符串到字節的復制是同時進行的,這在原始 JSON 非常大時可能會導致性能損失。因此,你可以使用 UnmarshalString() 和 GetFromString() 來傳遞字符串,只要你的原始數據是字符串,或零拷貝類型轉換對于你的字節數組是安全的。我們也提供了 MarshalString() 的 API ,以便對編碼的 JSON 字節數組進行零拷貝類型轉換,因為 sonic 輸出的字節始終是重復并且唯一的,所以這樣是安全的。

零拷貝類型轉換是一種技術,它允許你在不進行實際數據復制的情況下,將一種數據類型轉換為另一種數據類型。這種轉換通過操作原始內存塊的指針和切片來實現,避免了額外的數據復制,從而提高性能并減少內存開銷.

需要注意的是,零拷貝類型轉換雖然可以提高性能,但也可能引入一些安全和可維護性的問題,特別是當直接操作指針或內存映射時。

性能優化

在 完全解析的場景下, Unmarshal() 表現得比 Get()+Node.Interface() 更好。

func base() {
 data := `{"name": "z3","info":{"num": [11,22,33]}}`

 // complete parsing
 m := map[string]interface{}{}
 sonic.Unmarshal([]byte(data), &m)

}

但是如果你只有特定 JSON的部分模式,你可以將 Get() 和 Unmarshal() 結合使用:

func base() {
 data := `{"name": "z3","info":{"num": [11,22,33]}}`

 // complete parsing
 m := map[string]interface{}{}
 sonic.Unmarshal([]byte(data), &m)

 // partial parsing
 clear(m)
 node, err := sonic.GetFromString(data, "info", "num", 1)
 if err != nil {
  panic(err)
 }
 log.Println(node.Raw())
}

原文鏈接

https://juejin.cn/post/7271429136659791907

相關資料

[1]https://en.wikipedia.org/wiki/Jit: https://en.wikipedia.org%2Fwiki%2FJit

[2]https://github.com/chenzhuoyu/asm2asm: https://github.com%2Fchenzhuoyu%2Fasm2asm

本文轉載自微信公眾號「 程序員升級打怪之旅」,作者「 Shyunn&王中陽Go」,可以通過以下二維碼關注。

轉載本文請聯系「 程序員升級打怪之旅」公眾號。

責任編輯:武曉燕 來源: 程序員升職加薪之旅
相關推薦

2021-08-01 00:08:06

JsonGo標準庫

2023-09-21 22:02:22

Go語言高級特性

2009-11-11 10:43:49

Go語言Google

2023-02-09 15:28:19

鴻蒙編譯速度

2025-11-05 03:00:55

2025-11-17 01:41:00

2018-04-19 14:54:12

2024-07-11 08:50:05

Go語言errors

2024-05-10 08:36:40

Go語言對象

2024-02-28 23:07:42

GolangBase64編碼

2021-04-07 09:02:49

Go 語言變量與常量

2021-07-30 07:28:15

WorkerPoolGo語言

2021-04-13 07:58:42

Go語言函數

2012-12-24 14:53:44

ios

2021-04-20 09:00:48

Go 語言結構體type

2010-05-11 18:14:52

Mysql數據庫編碼

2024-07-31 10:22:49

Go語言編碼

2024-02-26 19:38:20

GitHubGo庫Golang

2014-04-24 10:48:27

Go語言基礎實現

2023-04-02 23:13:07

Go語言bufio
點贊
收藏

51CTO技術棧公眾號

欧洲成人午夜免费大片| 欧美日韩视频专区在线播放| 国产一区二区高清不卡| 国产免费久久久久| 成人在线视频你懂的| 香蕉影视欧美成人| 欧美日韩国产三区| 国产农村妇女毛片精品久久| 韩国亚洲精品| 亚洲女同精品视频| 亚洲天堂国产视频| sm在线播放| 中文字幕乱码久久午夜不卡| 3d蒂法精品啪啪一区二区免费| 国产主播在线观看| 牲欧美videos精品| 91麻豆精品国产91久久久久| www..com日韩| 亚洲av无码乱码在线观看性色| 亚洲综合99| 色诱女教师一区二区三区| 免费黄视频在线观看| 国精产品一区二区三区有限公司| 亚洲免费观看高清完整版在线观看熊 | 日韩欧美中文在线视频| 丁香花在线电影| 中文字幕第一区二区| 国产成人精品自拍| 国产又黄又粗又硬| 亚洲一区区二区| 久久精品99无色码中文字幕| 中文成人无字幕乱码精品区| 91国产精品| 欧美视频在线视频| 少妇大叫太大太粗太爽了a片小说| 国模精品一区二区| 国产成人在线免费| 国产精品吴梦梦| 九九九在线观看| 亚洲视频免费| 美乳少妇欧美精品| 午夜黄色福利视频| 免费av一区二区三区四区| 欧美va亚洲va| 日本中文字幕在线不卡| 在线女人免费视频| 亚洲妇熟xx妇色黄| 中文字幕一区二区三区5566| 精品电影在线| 成人中文字幕合集| 91影院未满十八岁禁止入内| chinese国产精品| 国产精品尤物| 欧美激情免费看| 欧美激情图片小说| av一区二区高清| 国产丝袜一区二区三区| 一起草在线视频| 97久久综合区小说区图片区| 91精品麻豆日日躁夜夜躁| 手机视频在线观看| 国产乱子精品一区二区在线观看| 色综合天天综合网天天看片| 一区二区传媒有限公司| 国产精品电影| 懂色av影视一区二区三区| 久久成人福利视频| av理论在线观看| 亚洲另类色综合网站| 亚洲国产成人不卡| 国产女人在线观看| 中文字幕一区视频| 免费在线精品视频| 91福利国产在线观看菠萝蜜| 亚洲精品免费在线观看| 中文字幕剧情在线观看一区| 欧美被日视频| 亚洲精品乱码久久久久久久久| 日本老太婆做爰视频| fc2ppv国产精品久久| 一区二区三区四区高清精品免费观看| 最新欧美日韩亚洲| 亚洲国产精品精华素| 一区二区三区精品在线观看| 男女视频网站在线观看| 日韩精品美女| 色综合av在线| 男人的天堂最新网址| 免费观看亚洲天堂| 亚洲成人xxx| 国产婷婷在线观看| 国产精品视频一区二区三区四蜜臂| 亚洲一区二区国产| 青青草激情视频| 1024日韩| 97国产精品久久| 国产成人自拍偷拍| 国产麻豆视频精品| 精品国产乱码久久久久久108| 日本人妖在线| 亚洲色图欧美激情| 成熟丰满熟妇高潮xxxxx视频| 日韩伦理在线一区| 色婷婷综合视频在线观看| 亚洲免费999| 91久久偷偷做嫩草影院电| 日韩电影在线观看永久视频免费网站| 久久婷婷五月综合| 欧美激情成人在线| 人人澡人人澡人人看欧美| 亚洲专区第一页| 成人sese在线| 中文字幕av导航| 国精产品一区一区三区mba下载| 欧美性xxxxx极品| 亚洲在线观看网站| 日韩av影院| 精品国产一区二区三区久久狼黑人| 麻豆changesxxx国产| 日本 国产 欧美色综合| 国产亚洲欧美一区二区| 日本高清www免费视频| 蜜桃视频在线观看一区| 麻豆精品传媒视频| 成av人片在线观看www| 欧美一级黄色大片| 一区二区三区在线播放视频| 久久久久99| 国精产品一区二区| 福利成人导航| 日韩精品最新网址| 中文字幕另类日韩欧美亚洲嫩草| 蜜臀av一区二区| 欧美日韩综合网| 中文字幕在线免费观看视频| 精品奇米国产一区二区三区| 四虎精品免费视频| 精品一区二区精品| ijzzijzzij亚洲大全| 青青草国产一区二区三区| 亚洲一级免费视频| 国产精品第6页| 国产欧美日韩精品一区| 狠狠操精品视频| 欧美女优在线视频| 国产v综合ⅴ日韩v欧美大片| 国产精品视频一区二区久久| 日本高清不卡一区| 亚洲色图 激情小说| 青青草91视频| 亚洲一卡二卡三卡四卡无卡网站在线看| 性欧美videohd高精| 亚洲片在线观看| 成人一二三四区| 中国av一区二区三区| 538任你躁在线精品免费| 日韩精品一卡| 91久久精品国产91久久性色| a级网站在线播放| 精品国产乱码久久久久久牛牛 | 欧美巨乳在线| 在线视频综合导航| 亚洲视频重口味| 国产精品亚洲专一区二区三区| mm131午夜| 激情小说亚洲色图| 国产成+人+综合+亚洲欧美丁香花| 国产高清免费在线播放| 欧美老女人在线| 天天干中文字幕| kk眼镜猥琐国模调教系列一区二区| 无码精品a∨在线观看中文| 精品高清久久| 亚洲va欧美va国产综合久久| 免费男女羞羞的视频网站在线观看 | 日本三级黄色网址| 午夜久久黄色| 国产 日韩 欧美在线| 欧美一级二级三级区| 欧美一区午夜视频在线观看| 国产一级片视频| 久久综合999| 黄大色黄女片18第一次| 欧美91精品| 久久国产精品 国产精品| 成人h视频在线观看| 日本精品一二三| 精品动漫3d一区二区三区免费| 蜜桃麻豆91| 日韩在线电影| 91精品国产91久久| 97视频在线观看网站| 欧美成人一区二区| 99精品在线播放| 中文字幕制服丝袜一区二区三区| 亚洲一二三四五| 日本午夜一本久久久综合| 国产高清免费在线| 精品人人人人| 国产啪精品视频网站| 岛国在线视频网站| 久久精品国产成人精品| 你懂的视频在线观看| 日韩精品一区二区三区在线播放| 天天操天天干天天摸| 亚洲一区二区三区不卡国产欧美| 天天舔天天操天天干| 成人美女视频在线观看18| 日本激情综合网| 亚洲永久在线| 亚洲熟妇无码av在线播放| 久久国产成人午夜av影院宅| 精品国产电影| 一区二区三区视频播放| 国产综合在线观看视频| 无人区在线高清完整免费版 一区二| 欧美美女15p| 黄色成年人视频在线观看| 尤物九九久久国产精品的特点| 亚洲欧美丝袜中文综合| 欧美成人一级视频| 国产极品999| 欧美日韩国产美| 精人妻无码一区二区三区| 无吗不卡中文字幕| 精品亚洲永久免费| 亚洲欧美韩国综合色| 日本免费网站视频| 日本一区二区不卡视频| 国产 欧美 在线| 久久综合九色综合欧美98| 日本久久久久久久久久| 国产乱码一区二区三区| 天天操精品视频| 毛片不卡一区二区| 欧美一级黄色影院| 久久国产高清| 日本999视频| 丝袜亚洲精品中文字幕一区| 免费黄色福利视频| 久热精品在线| 妞干网在线免费视频| 性欧美长视频| 成年人视频在线免费| 久久午夜精品一区二区| 国产在线观看福利| 天使萌一区二区三区免费观看| 无码aⅴ精品一区二区三区浪潮 | 亚洲 欧洲 日韩| 日韩精品免费一区二区在线观看 | 午夜综合激情| 欧美少妇性生活视频| 久久亚洲精品伦理| 亚洲国产精品三区| 精品写真视频在线观看 | 日韩欧美另类中文字幕| 91精品天堂| 欧美大片网址| 日韩精品资源| 97偷自拍亚洲综合二区| 欧美做受777cos| 亚洲精品日韩久久| 亚洲成人福利在线观看| 韩国v欧美v日本v亚洲v| 熟妇女人妻丰满少妇中文字幕| 成人小视频免费观看| 在线观看国产网站| 国产精品免费av| 久久久久久久久精| 欧美日韩亚洲精品一区二区三区| 69av视频在线观看| 555夜色666亚洲国产免| 手机看片福利永久| 一二美女精品欧洲| 69xxx在线| 国产成人激情视频| 99久久这里有精品| 久久亚洲高清| 国产精品精品国产一区二区| 真人抽搐一进一出视频| 久久精品卡一| 不卡的一区二区| 久久精品亚洲精品国产欧美kt∨| 少妇高潮在线观看| 欧美色视频日本版| 国产又黄又猛又爽| 精品视频在线播放| 国产在线观看91| 欧美亚洲激情在线| 欧美日韩黄网站| 欧美精品国产精品久久久| 91精品蜜臀一区二区三区在线| 成人一对一视频| 精品影院一区二区久久久| 日b视频在线观看| 亚洲私人影院在线观看| 日本黄色一级视频| 精品久久久久99| 在线免费看a| 欧美在线激情网| 日韩区欧美区| 五码日韩精品一区二区三区视频| 影音先锋中文字幕一区| 加勒比av中文字幕| 久久精品男人的天堂| 久久久国产精品黄毛片| 欧美日韩国产美| 久蕉在线视频| 91国产一区在线| 亚洲视频一起| 桥本有菜av在线| 天堂影院一区二区| 亚洲精品视频大全| 午夜久久久久久电影| www.av网站| 久久亚洲精品网站| 久久不卡日韩美女| 日本一区二区三区免费看| 亚洲美女黄色| 欧美激情一区二区三区p站| 亚洲视频一二三| 国产精品视频无码| www.99久久热国产日韩欧美.com| gogo亚洲高清大胆美女人体| 精品伦精品一区二区三区视频| 欧美日韩福利| 国产精品成人免费一区久久羞羞| 亚洲三级久久久| 国产又粗又黄又爽| 色婷婷久久av| 国产一区影院| 一区二区不卡在线观看| 热久久国产精品| 国产精品麻豆免费版现看视频| 色94色欧美sute亚洲线路一久 | 日韩在线视频一区| h1515四虎成人| 先锋影音一区二区三区| 日韩精品亚洲一区| 国产精品av久久久久久无| 色屁屁一区二区| 久久精品蜜桃| 国产精品专区一| 99精品美女| 青娱乐国产精品视频| 亚洲综合视频网| 乱色精品无码一区二区国产盗| 久久久久久久影院| 日韩影视在线观看| 成年人在线看片| 中文字幕乱码久久午夜不卡 | 精品一区二区在线免费观看| www.av免费| 日韩精品一区二区三区在线观看| 人妖欧美1区| 久久久精品国产一区二区三区| 久久九九精品| 成年人免费视频播放| 欧美一区日韩一区| a毛片不卡免费看片| 欧美不卡三区| 久草在线在线精品观看| 欧美日韩国产精品一区二区三区| 精品福利在线导航| 在线观看网站免费入口在线观看国内| 日本一区二区三区视频免费看| 美腿丝袜亚洲综合| 九九视频免费在线观看| 日韩精品在线免费观看| 国产欧美自拍| 国产免费一区二区视频| xfplay精品久久| 国产毛片毛片毛片毛片| 久久久久久一区二区三区| 欧美人与牛zoz0性行为| 超碰中文字幕在线观看| 欧美日韩另类字幕中文| 2021av在线| 国产精品一区二区三区不卡 | 国产成人久久久| 国产精品久久久久蜜臀| 亚洲国产综合视频| 91麻豆精品国产| 欧美大片免费| 视色,视色影院,视色影库,视色网 日韩精品福利片午夜免费观看 | 国产欧美一区| 中文字幕亚洲日本| 欧美性videosxxxxx| hd国产人妖ts另类视频| 亚洲人成77777| 99国产精品久久久久久久久久| 91久久精品无码一区二区| 91精品国产91久久久| 99视频精品视频高清免费| 人妻少妇精品视频一区二区三区 | 亚洲男人天堂av在线| 亚洲成人精品一区| 麻豆tv入口在线看| 欧美精品亚洲精品| 高清不卡在线观看|