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

使用C++的StringBuilder提升4350%的性能

開發 后端
經常出現客戶端打電話抱怨說:你們的程序慢如蝸牛。你開始檢查可能的疑點:文件IO,數據庫訪問速度,甚至查看web服務。 但是這些可能的疑點都很正常,一點問題都沒有。

介紹

經常出現客戶端打電話抱怨說:你們的程序慢如蝸牛。你開始檢查可能的疑點:文件IO,數據庫訪問速度,甚至查看web服務。 但是這些可能的疑點都很正常,一點問題都沒有。

你使用最順手的性能分析工具分析,發現瓶頸在于一個小函數,這個函數的作用是將一個長的字符串鏈表寫到一文件中。

你對這個函數做了如下優化:將所有的小字符串連接成一個長的字符串,執行一次文件寫入操作,避免成千上萬次的小字符串寫文件操作。

這個優化只做對了一半。

你先測試大字符串寫文件的速度,發現快如閃電。然后你再測試所有字符串拼接的速度。

好幾年。

怎么回事?你會怎么克服這個問題呢?

你或許知道.net程序員可以使用StringBuilder來解決此問題。這也是本文的起點。

背景

如果google一下“C++ StringBuilder”,你會得到不少答案。有些會建議(你)使用std::accumulate,這可以完成幾乎所有你要實現的:

#include <iostream>// for std::cout, std::endl
#include <string>  // for std::string
#include <vector>  // for std::vector
#include <numeric> // for std::accumulate
int main() {
	using namespace std;
	vector<string> vec = { "hello", " ", "world" };
	string s = accumulate(vec.begin(), vec.end(), s);
	cout << s << endl; // prints 'hello world' to standard output. 
	return 0;
}

目前為止一切都好:當你有超過幾個字符串連接時,問題就出現了,并且內存再分配也開始積累。

std::string在函數reserver()中為解決方案提供基礎。這也正是我們的意圖所在:一次分配,隨意連接。

字符串連接可能會因為繁重、遲鈍的工具而嚴重影響性能。由于上次存在的隱患,這個特殊的怪胎給我制造麻煩,我便放棄了Indigo(我想嘗試一些C++11里的令人耳目一新的特性),并寫了一個StringBuilder類的部分實現:

// Subset of http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.aspx
template <typename chr>
class StringBuilder {
	typedef std::basic_string<chr> string_t;
 	typedef std::list<string_t> container_t; // Reasons not to use vector below. 
	typedef typename string_t::size_type size_type; // Reuse the size type in the string.
	container_t m_Data;
	size_type m_totalSize;
	void append(const string_t &src) {
		m_Data.push_back(src);
		m_totalSize += src.size();
	}
	// No copy constructor, no assignement.
	StringBuilder(const StringBuilder &);
	StringBuilder & operator = (const StringBuilder &);
public:
	StringBuilder(const string_t &src) {
		if (!src.empty()) {
			m_Data.push_back(src);
		}
		m_totalSize = src.size();
	}
	StringBuilder() {
		m_totalSize = 0;
	}
	// TODO: Constructor that takes an array of strings.

	StringBuilder & Append(const string_t &src) {
		append(src);
		return *this; // allow chaining.
	}
        // This one lets you add any STL container to the string builder. 
	template<class inputIterator>
	StringBuilder & Add(const inputIterator &first, const inputIterator &afterLast) {
		// std::for_each and a lambda look like overkill here.
                // <b>Not</b> using std::copy, since we want to update m_totalSize too.
		for (inputIterator f = first; f != afterLast; ++f) {
			append(*f);
		}
		return *this; // allow chaining.
	}
	StringBuilder & AppendLine(const string_t &src) {
		static chr lineFeed[] { 10, 0 }; // C++ 11. Feel the love!
		m_Data.push_back(src + lineFeed);
		m_totalSize += 1 + src.size();
		return *this; // allow chaining.
	}
	StringBuilder & AppendLine() {
		static chr lineFeed[] { 10, 0 }; 
		m_Data.push_back(lineFeed);
		++m_totalSize;
		return *this; // allow chaining.
	}

	// TODO: AppendFormat implementation. Not relevant for the article. 

    // Like C# StringBuilder.ToString()
    // Note the use of reserve() to avoid reallocations. 
	string_t ToString() const {
		string_t result;
		// The whole point of the exercise!
		// If the container has a lot of strings, reallocation (each time the result grows) will take a serious toll,
		// both in performance and chances of failure.
		// I measured (in code I cannot publish) fractions of a second using 'reserve', and almost two minutes using +=.
		result.reserve(m_totalSize + 1);
	//	result = std::accumulate(m_Data.begin(), m_Data.end(), result); // This would lose the advantage of 'reserve'
		for (auto iter = m_Data.begin(); iter != m_Data.end(); ++iter) { 
			result += *iter;
		}
		return result;
	}

	// like javascript Array.join()
	string_t Join(const string_t &delim) const {
		if (delim.empty()) {
			return ToString();
		}
		string_t result;
		if (m_Data.empty()) {
			return result;
		}
		// Hope we don't overflow the size type.
		size_type st = (delim.size() * (m_Data.size() - 1)) + m_totalSize + 1;
		result.reserve(st);
                // If you need reasons to love C++11, here is one.
		struct adder {
			string_t m_Joiner;
			adder(const string_t &s): m_Joiner(s) {
				// This constructor is NOT empty.
			}
                        // This functor runs under accumulate() without reallocations, if 'l' has reserved enough memory. 
			string_t operator()(string_t &l, const string_t &r) {
				l += m_Joiner;
				l += r;
				return l;
			}
		} adr(delim);
		auto iter = m_Data.begin(); 
                // Skip the delimiter before the first element in the container.
		result += *iter; 
		return std::accumulate(++iter, m_Data.end(), result, adr);
	}

}; // class StringBuilder

有趣的部分

函數ToString()使用std::string::reserve()來實現最小化再分配。下面你可以看到一個性能測試的結果。

函數join()使用std::accumulate(),和一個已經為***操作數預留內存的自定義函數。

你可能會問,為什么StringBuilder::m_Data用std::list而不是std::vector?除非你有一個用其他容器的好理由,通常都是使用std::vector。

好吧,我(這樣做)有兩個原因:

1. 字符串總是會附加到一個容器的末尾。std::list允許在不需要內存再分配的情況下這樣做;因為vector是使用一個連續的內存塊實現的,每用一個就可能導致內存再分配。

2. std::list對順序存取相當有利,而且在m_Data上所做的唯一存取操作也是順序的。

你可以建議同時測試這兩種實現的性能和內存占用情況,然后選擇其中一個。

性能評估

為了測試性能,我從Wikipedia獲取一個網頁,并將其中一部分內容寫死到一個string的vector中。

隨后,我編寫兩個測試函數,***個在兩個循環中使用標準函數clock()并調用std::accumulate()和StringBuilder::ToString(),然后打印結果。

void TestPerformance(const StringBuilder<wchar_t> &tested, const std::vector<std::wstring> &tested2) {
	const int loops = 500;
	clock_t start = clock(); // Give up some accuracy in exchange for platform independence.
	for (int i = 0; i < loops; ++i) {
		std::wstring accumulator;
		std::accumulate(tested2.begin(), tested2.end(), accumulator);
	}
	double secsAccumulate = (double) (clock() - start) / CLOCKS_PER_SEC;

	start = clock();
	for (int i = 0; i < loops; ++i) {
		std::wstring result2 = tested.ToString();
	}
	double secsBuilder = (double) (clock() - start) / CLOCKS_PER_SEC;
	using std::cout;
	using std::endl;
	cout << "Accumulate took " << secsAccumulate << " seconds, and ToString() took " << secsBuilder << " seconds."
			<< " The relative speed improvement was " << ((secsAccumulate / secsBuilder) - 1) * 100 << "%"
			<< endl;
}

第二個則使用更精確的Posix函數clock_gettime(),并測試StringBuilder::Join()。

#ifdef __USE_POSIX199309

// Thanks to <a href="http://www.guyrutenberg.com/2007/09/22/profiling-code-using-clock_gettime/">Guy Rutenberg</a>.
timespec diff(timespec start, timespec end) {
	timespec temp;
	if ((end.tv_nsec-start.tv_nsec)<0) {
		temp.tv_sec = end.tv_sec-start.tv_sec-1;
		temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
	} else {
		temp.tv_sec = end.tv_sec-start.tv_sec;
		temp.tv_nsec = end.tv_nsec-start.tv_nsec;
	}
	return temp;
}

void AccurateTestPerformance(const StringBuilder<wchar_t> &tested, const std::vector<std::wstring> &tested2) {
	const int loops = 500;
	timespec time1, time2;
	// Don't forget to add -lrt to the g++ linker command line.
	////////////////
	// Test std::accumulate()
	////////////////
	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time1);
	for (int i = 0; i < loops; ++i) {
		std::wstring accumulator;
		std::accumulate(tested2.begin(), tested2.end(), accumulator);
	}
	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time2);
	using std::cout;
	using std::endl;
	timespec tsAccumulate =diff(time1,time2);
	cout << tsAccumulate.tv_sec << ":" <<  tsAccumulate.tv_nsec << endl;
	////////////////
	// Test ToString()
	////////////////
	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time1);
	for (int i = 0; i < loops; ++i) {
		std::wstring result2 = tested.ToString();
	}
	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time2);
	timespec tsToString =diff(time1,time2);
	cout << tsToString.tv_sec << ":" << tsToString.tv_nsec << endl;
	////////////////
	// Test join()
	////////////////
	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time1);
	for (int i = 0; i < loops; ++i) {
		std::wstring result3 = tested.Join(L",");
	}
	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time2);
	timespec tsJoin =diff(time1,time2);
	cout << tsJoin.tv_sec << ":" << tsJoin.tv_nsec << endl;

	////////////////
	// Show results
	////////////////
	double secsAccumulate = tsAccumulate.tv_sec + tsAccumulate.tv_nsec / 1000000000.0;
	double secsBuilder = tsToString.tv_sec + tsToString.tv_nsec / 1000000000.0;
        double secsJoin = tsJoin.tv_sec + tsJoin.tv_nsec / 1000000000.0;
	cout << "Accurate performance test:" << endl << "    Accumulate took " << secsAccumulate << " seconds, and ToString() took " << secsBuilder << " seconds." << endl
			<< "    The relative speed improvement was " << ((secsAccumulate / secsBuilder) - 1) * 100 << "%" << endl <<
             "     Join took " << secsJoin << " seconds."
			<< endl;
}
#endif // def __USE_POSIX199309

***,通過一個main函數調用以上實現的兩個函數,將結果顯示在控制臺,然后執行性能測試:一個用于調試配置。

07091432_n2mt

t另一個用于發行版本:

07091434_6ucm

看到這百分比沒?垃圾郵件的發送量都不能達到這個級別!

代碼使用

在使用這段代碼前, 考慮使用ostring流。正如你在下面看到Jeff先生評論的一樣,它比這篇文章中的代碼更快些。

你可能想使用這段代碼,如果:

  • 你正在編寫由具有C#經驗的程序員維護的代碼,并且你想提供一個他們所熟悉接口的代碼。
  • 你正在編寫將來會轉換成.net的、你想指出一個可能路徑的代碼。
  • 由于某些原因,你不想包含<sstream>。幾年之后,一些流的IO實現變得很繁瑣,而且現在的代碼仍然不能完全擺脫他們的干擾。

要使用這段代碼,只有按照main函數實現的那樣就可以了:創建一個StringBuilder的實例,用Append()、AppendLine()和Add()給它賦值,然后調用ToString函數檢索結果。

就像下面這樣:

int main() {
	////////////////////////////////////
	// 8-bit characters (ANSI)
	////////////////////////////////////
	StringBuilder<char> ansi;
	ansi.Append("Hello").Append(" ").AppendLine("World");
	std::cout << ansi.ToString();

	////////////////////////////////////
	// Wide characters (Unicode)
	////////////////////////////////////
	// http://en.wikipedia.org/wiki/Cargo_cult
	std::vector<std::wstring> cargoCult
	{
		L"A", L" cargo", L" cult", L" is", L" a", L" kind", L" of", L" Melanesian", L" millenarian", L" movement",
// many more lines here...
L" applied", L" retroactively", L" to", L" movements", L" in", L" a", L" much", L" earlier", L" era.\n"
	};
	StringBuilder<wchar_t> wide;
	wide.Add(cargoCult.begin(), cargoCult.end()).AppendLine();
        // use ToString(), just like .net
	std::wcout << wide.ToString() << std::endl;
	// javascript-like join.
	std::wcout << wide.Join(L" _\n") << std::endl;

	////////////////////////////////////
	// Performance tests
	////////////////////////////////////
	TestPerformance(wide, cargoCult);
#ifdef __USE_POSIX199309
	AccurateTestPerformance(wide, cargoCult);
#endif // def __USE_POSIX199309
	return 0;
}

任何情況下,當連接超過幾個字符串時,當心std::accumulate函數。

現在稍等一下!

你可能會問:你是在試著說服我們提前優化嗎?

不是的。我贊同提前優化是糟糕的。這種優化并不是提前的:是及時的。這是基于經驗的優化:我發現自己過去一直在和這種特殊的怪胎搏斗。基于經驗的優化(不在同一個地方摔倒兩次)并不是提前優化。

當我們優化性能時,“慣犯”會包括磁盤I-O操作、網絡訪問(數據庫、web服務)和內層循環;對于這些,我們應該添加內存分配和性能糟糕的 Keyser Söze。

鳴謝

首先,我要為這段代碼在Linux系統上做的精準分析感謝Rutenberg。

多虧了Wikipedia,讓“在指尖的信息”的夢想得以實現。

***,感謝你花時間閱讀這篇文章。希望你喜歡它:不論如何,請分享您的意見。

責任編輯:張燕妮 來源: oschina
相關推薦

2013-09-11 16:11:57

C++StringBuild

2023-09-26 12:02:34

C++循環

2024-01-31 23:51:22

C++移動語義代碼

2024-04-18 11:07:30

C++語言

2021-06-10 09:40:12

C++性能優化Linux

2010-01-26 15:51:06

C++變量

2025-08-11 01:00:00

2014-04-17 10:37:43

C++.NET Native

2023-05-12 13:21:12

JMHJava程序

2020-01-21 22:25:00

機器學習人工智能計算機

2015-01-06 09:59:03

2021-10-14 07:55:17

提示技巧C#

2023-09-25 13:28:14

C++Lambda

2024-05-16 11:04:06

C#異步編程編程

2015-01-21 15:40:44

GoRuby

2015-11-10 09:25:05

HTTP2提升性能

2024-04-07 09:59:42

C++并發編程開發

2022-08-22 15:32:59

C++C代碼

2023-12-18 10:11:36

C++17C++代碼

2013-05-22 09:38:03

GoGo語言Go性能
點贊
收藏

51CTO技術棧公眾號

亚洲码在线观看| 午夜婷婷国产麻豆精品| 国产日韩欧美影视| 国产麻豆视频在线观看| 成人爽a毛片免费啪啪红桃视频| 亚洲一区二区综合| 日韩欧美精品一区二区| 国产老女人乱淫免费| 欧美fxxxxxx另类| 亚洲精品视频久久| 国产人妖在线观看| 国产福利一区二区三区在线播放| 亚洲成av人片在线观看| 在线观看一区二区三区三州| 亚洲欧美丝袜中文综合| 国产在线精品一区二区不卡了| 国外成人在线播放| 久久精品在线观看视频| 亚洲第一论坛sis| 欧美一区二区三级| 中文字幕视频在线免费观看| 91在线三级| 国产精品久久久久久久久搜平片| 精品国产免费久久久久久尖叫| 国产一区二区小视频| 西西人体一区二区| 久久久视频精品| 欧美激情精品久久久久久免费| 久久99国内| 亚洲国产私拍精品国模在线观看| 亚洲午夜精品一区| 日本一区免费网站| 欧美午夜女人视频在线| 很污的网站在线观看| 免费av在线播放| 亚洲国产高清在线| 欧美精品一区二区视频| 欧美一区二区在线观看视频| 国产精品99久久久久久宅男| 91精品久久久久久久久不口人| 日韩精品成人免费观看视频| 国产精品日本| 久久人人爽人人| 久久久久久av无码免费网站| 综合精品久久| 久久成人亚洲精品| 精品国产视频一区二区三区 | 午夜精品一区二区三区四区| 日韩av地址| 99精品欧美一区二区三区综合在线| 999在线观看免费大全电视剧| 国产日韩免费视频| 久草精品在线观看| 91精品在线影院| 国产欧美综合视频| 国产精品一区二区无线| 91av免费看| www.桃色av嫩草.com| 国产成都精品91一区二区三| y111111国产精品久久婷婷| 国产高潮流白浆喷水视频| 国产成人精品综合在线观看| 国产精品入口免费| 亚洲欧美丝袜中文综合| 国产网站一区二区| 亚洲欧美成人一区| 国产成人无吗| 午夜婷婷国产麻豆精品| 免费在线观看毛片网站| www.成人在线视频| 欧美一区二区在线观看| 91成人在线观看喷潮蘑菇| 另类图片第一页| 亚洲人成网站免费播放| 国产精品理论在线| 欧美在线网址| 欧美性受xxx| 中国老头性行为xxxx| 紧缚奴在线一区二区三区| 99在线热播| 亚洲aⅴ在线观看| 国产欧美一区视频| gogogo免费高清日本写真| 国产精品一品| 在线观看91视频| 伊人色在线视频| 美日韩黄色大片| 亚洲欧美制服第一页| 日本美女黄色一级片| 狠狠综合久久av一区二区老牛| 18一19gay欧美视频网站| 欧美高清69hd| 丁香婷婷综合网| 日韩在线观看电影完整版高清免费| 黄a在线观看| 欧美日韩亚洲激情| 国产乱女淫av麻豆国产| 精品网站aaa| 中文字幕在线看视频国产欧美| 精品99久久久久成人网站免费| 午夜在线精品偷拍| 99在线免费观看视频| www.中文字幕久久久| 亚洲一区在线看| 日韩一级理论片| 超碰成人97| www.欧美三级电影.com| aaa人片在线| 久久99国内精品| 欧美日韩亚洲一区二区三区在线观看 | 亚洲最大在线视频| 久久高清无码视频| 激情欧美日韩一区二区| 欧日韩一区二区三区| 国产探花视频在线观看| 欧美日韩久久一区二区| 久久久国产精品无码| 亚洲视频电影在线| 国产精品极品美女粉嫩高清在线| 亚洲欧美激情在线观看| 亚洲欧洲国产日本综合| 青青在线视频免费| 琪琪久久久久日韩精品| 欧美激情精品久久久久久变态| 在线观看亚洲国产| 久久久久9999亚洲精品| 黄色一级片在线看| 一区二区三区在线资源| 久久久成人精品视频| 日本三级一区二区三区| 久久这里只精品最新地址| 妞干网视频在线观看| 亚洲人成777| 在线精品高清中文字幕| 69亚洲精品久久久蜜桃小说| 成人18视频在线播放| 国产免费裸体视频| 日本成人手机在线| 欧美成人亚洲成人| 国产熟女一区二区三区五月婷| 国产精品拍天天在线| 天堂中文视频在线| 欧美一二区在线观看| 日韩av手机在线看| 免费黄色片在线观看| 色综合天天天天做夜夜夜夜做| 国产亚洲色婷婷久久99精品91| 99日韩精品| 精品蜜桃一区二区三区| 九色porny自拍视频在线观看| 亚洲国产精品久久久久久| 国产精品99re| 97久久超碰精品国产| 国产黄色一级网站| 杨幂一区二区三区免费看视频| 91av在线网站| 免费成人av电影| 日本黄色一区二区| 国产精品www爽爽爽| 麻豆成人久久精品二区三区小说| 一区二区冒白浆视频| 婷婷精品久久久久久久久久不卡| www.久久久久| 亚洲欧美激情在线观看| 欧美日韩激情小视频| a级片在线观看| 美腿丝袜亚洲一区| 妞干网在线播放| 欧美日韩另类图片| 国产精品久久av| 成人免费看片| 亚洲精品国产拍免费91在线| 国产寡妇亲子伦一区二区三区四区| 国产日韩精品久久久| 超碰人人草人人| 激情久久久久久| 欧美另类高清视频在线| 黄色成人在线观看网站| 精品自在线视频| 日夜干在线视频| 欧美日韩国产高清一区二区三区 | 亚洲天堂最新地址| 国产曰批免费观看久久久| 中国丰满熟妇xxxx性| 精品盗摄女厕tp美女嘘嘘| 91精品视频一区| av剧情在线观看| 中文字幕久热精品在线视频 | 亚洲精品第一| 国模精品视频一区二区| av在线中文| 亚洲成avwww人| 中文字幕人妻一区二区在线视频| 一区二区不卡在线视频 午夜欧美不卡在| 欧美一区二区三区成人精品| 久久草av在线| 日本在线观看a| 综合久久精品| 午夜一区二区三区| 精品人人人人| 亚洲一区二区日本| 日韩免费电影| 久久久久久欧美| 麻豆影视国产在线观看| 亚洲人av在线影院| 亚洲毛片欧洲毛片国产一品色| 欧美视频自拍偷拍| 日本三级小视频| 一区二区三区日韩欧美精品| 成人在线观看免费高清| 91麻豆国产福利在线观看| 古装做爰无遮挡三级聊斋艳谭| 日韩成人一区二区三区在线观看| 免费的一级黄色片| 91精品国产91久久久久久密臀| 欧美性xxxx69| 人体久久天天| 国产a一区二区| 97久久中文字幕| 国产精品va在线| 日本蜜桃在线观看视频| 久久青草精品视频免费观看| 老司机午夜在线视频| 在线成人激情黄色| 激情福利在线| 精品视频在线播放色网色视频| 丰满人妻一区二区| 日韩视频在线永久播放| 国产强伦人妻毛片| 91超碰这里只有精品国产| 波多野结衣绝顶大高潮| 一道本成人在线| 欧美一区二区激情视频| 午夜成人免费电影| 国产精品成人网站| 午夜伦理一区二区| 日本在线视频中文字幕| 亚洲国产综合人成综合网站| 久久午夜无码鲁丝片| 亚洲免费三区一区二区| 中文字幕五月天| 亚洲精选视频免费看| 婷婷激情四射网| 亚洲精品一二三四区| 久久久精品少妇| 椎名由奈av一区二区三区| 91香蕉一区二区三区在线观看| 日韩一区有码在线| 麻豆视频在线免费看| 亚洲黄一区二区三区| 激情视频在线播放| 亚洲成人av福利| 天天做天天爱夜夜爽| 色综合天天综合网天天狠天天| 欧产日产国产69| 欧洲精品视频在线观看| 亚洲影院一区二区三区| 91精品国产色综合久久久蜜香臀| 国产精品人妻一区二区三区| 91精品国产麻豆国产自产在线 | 99a精品视频在线观看| 成人资源av| 亚洲另类av| 性刺激综合网| 最新国产精品久久久| 久久久久久久9| 亚洲欧美日韩视频二区| 亚洲三级视频网站| 国产精品原创巨作av| 国产成人av无码精品| 久久综合九色欧美综合狠狠| 天天操天天摸天天舔| 一级精品视频在线观看宜春院 | sm捆绑调教视频| 亚洲午夜久久久久久久久电影网 | 黄色一级片中国| 红桃视频成人在线观看| 国产精品51麻豆cm传媒| 日韩亚洲欧美成人一区| 凸凹人妻人人澡人人添| 在线中文字幕日韩| 欧洲黄色一区| 国产va免费精品高清在线观看| 性欧美video另类hd尤物| 国产精品免费一区二区| 欧美一区二区三区高清视频| 伊人网在线免费| 视频一区二区三区入口| xxxx在线免费观看| 久久伊99综合婷婷久久伊| 亚洲怡红院在线观看| 欧美日韩中文字幕在线| 国产精品无码久久av| 亚洲精品美女在线观看播放| 黄色网址视频在线观看| 欧美在线一区二区视频| 国内精品视频| 日本高清不卡一区二区三| 欧美日韩精选| 三年中国国语在线播放免费| 成人黄色a**站在线观看| 国产福利在线导航| 精品免费在线视频| 精品欧美在线观看| 色妞欧美日韩在线| 蜜桃视频在线观看免费视频| 亚洲在线一区二区| 青青一区二区三区| 激情综合网婷婷| 成人高清伦理免费影院在线观看| 三上悠亚在线观看视频| 一本到三区不卡视频| 少妇精品视频一区二区| 麻豆国产精品va在线观看不卡 | 成人免费在线| 国产伊人精品在线| 国产精品视频一区二区三区四蜜臂| 日韩一级性生活片| 国产成人精品免费一区二区| 欧美性猛交xxxx乱大交少妇| 91久久精品一区二区| 天天干,夜夜操| 久久久免费在线观看| 亚洲精品一区二区三区中文字幕| 亚洲精品一区二| 蜜臀久久久久久久| 91精品国自产在线| 日本久久一区二区三区| 欧美精品a∨在线观看不卡| 欧美乱妇高清无乱码| 成人黄色理论片| 自拍另类欧美| 狠狠色丁香九九婷婷综合五月 | 亚洲成av人片在线观看| 亚洲精品成人区在线观看| 久久99久国产精品黄毛片入口| 91麻豆精品| 中文字幕精品在线播放| 国产综合久久久久影院| www.av视频| 精品国产乱码久久久久久影片| 污污的视频在线观看| 成人女人免费毛片| 亚洲午夜av| 亚洲熟女乱综合一区二区三区| 亚洲成人自拍一区| 少妇荡乳情欲办公室456视频| 午夜精品久久久久久久久久久久 | 亚洲s码欧洲m码国产av| 亚洲欧美国产另类| 欧美不卡高清一区二区三区| 亚洲电影网站| 韩国女主播成人在线观看| 日韩女优一区二区| 精品国产乱码久久久久久1区2区| 狂野欧美激情性xxxx欧美| 久久国产精品 国产精品| 亚洲综合社区| 娇小11一12╳yⅹ╳毛片| 日韩一区二区三区四区五区六区| 精品精品导航| 欧美二级三级| 久久国内精品视频| 九九热精品在线观看| 日韩精品999| 韩日精品一区| www婷婷av久久久影片| av午夜一区麻豆| 亚洲综合成人av| 久久99久久99精品免观看粉嫩| 网友自拍区视频精品| 欧美特级aaa| 一区二区三区精密机械公司| 五十路在线观看| 国产精品人成电影在线观看| 中文精品久久| 国产亚洲无码精品| 欧美日韩午夜在线视频| 欧美aaaaaaa| 欧美亚洲免费在线| 国产精品一区二区果冻传媒| 欧美三日本三级少妇99| 色哟哟入口国产精品| 国产一区丝袜| www.亚洲高清| 精品国产电影一区| 久草中文在线| 欧美高清视频一区| 国产mv日韩mv欧美| 中国a一片一级一片| 欧美精品电影在线| 日韩黄色大片网站| 国产麻豆剧传媒精品国产av| 欧美日韩国产美女| 免费在线小视频| 精品一区二区三区无码视频| 中文文精品字幕一区二区| 色婷婷综合视频| 91在线视频精品| 日本中文一区二区三区|