国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

奇技淫巧C++之懶惰計算

2019-11-17 05:28:35
字體:
供稿:網(wǎng)友

  考慮這樣一個表達(dá)式語句:

String result = str_you + “said: ” + str_he + “ said: @#$% ” + str_i + “said: over!”;
  對于這樣一個語句,程序如何求值呢?假設(shè)str_you是一個典型std::string類型,這個語句需要做5 次Operator+運(yùn)算,多個string臨時對象,還極有可能的,多次的內(nèi)存分配操作。

  假如你的team leader對你說了類似話,兄弟,他是對你的代碼性能不滿呢。當(dāng)然,聰明如你,一定會在上司找到你之前就發(fā)現(xiàn)了這里是個性能瓶頸,并且告訴他你正著手解決它呢。

  辦法是多種多樣的,最正確的辦法當(dāng)然首先是看看設(shè)計上是否存在缺陷,并且可以修復(fù)以改善性能問題。假設(shè),任何部分都很正確(我知道這不可能,一定有被你稱為菜鳥的同事干了蠢事,不是嗎?),責(zé)任只好落到你的肩上。打算怎么辦?

  我不知道你會怎么做,也許你會換一個更快的string,或者簡單調(diào)整一下語句:

string result;
result.reserve(1000);
result += str_you; result += “said: ”;
result += str_he; result += “ said: @#$% ”;
result += str_i; result += “said: over!”;
  假如只有一兩個性能熱點,我打賭,我會這樣先嘗試一下。我認(rèn)為這是一個很好的開始,我們已經(jīng)熟悉到導(dǎo)致瓶頸的原因并且試圖消除它。你也可以這么做。 寫這篇文章,當(dāng)然意味著還有別的方法,而且和懶惰計算有關(guān)。因為我們不能修改basic_string::的operator+,因此,先把表達(dá)式變形:

Acce() + str_you + “said: ” + str_he + “ said: @#$% ” + str_i + “said: over!”;

  因為operator+從左向右結(jié)合,可以采用我們加速過的運(yùn)算過程。先看最簡單的情況,和string相加。

template<typename Left, typename Right>
strUCt Accelerate{
 operator string () const;
 Left& left;
 Right& right;
};

template<typename Left, typename Right>
inline Accelerate< Accelerate< Left >, Right>

operator+(Accelerate< Left >& lsh, const Right& rsh)
{
 return Accelerate< Accelerate< Left >, Right>(lsh, rsh);
}
  顯然,Accelerate是輕量級的,現(xiàn)在考慮怎么實現(xiàn)operator string () const呢?我的計劃是,首先計算出字符串的總長度,然后開一個足夠大的空間來復(fù)制字符串,避免反復(fù)分配內(nèi)存:

operator string () const{
 string str;
 str.reserve(length(left) + length(right));
 append(str, left);
 append(str, right);
 return str;
};
  第一步,看看怎么實現(xiàn)length:

struct Empty{};
template<typename T>

inline size_t length(const T& t){
 return t.size();
}

template<typename Left, typename Right>

inline size_t length(const Accelerate<Left, Right>& t){
 return length(t.left) + length(t.right);
}

template<>

inline size_t length(const Accelerate<Empty, Empty>& t){
 return 0;
}
  第二步,看看怎么實現(xiàn)append:

Template<typename Left, typename Right>
inline append(string& str, const Accelerate& t ){
 append(str, t.left);
 append(str,t.right);
}

Template< >

inline append(string&, const Accelerate<Empty, Empty>& ){}

inline append(string& str, const string& rsh){
 copy(rsh.begin(), rsh.end(), back_inserter(str));
}
  現(xiàn)在,我們整個計算的框架算是完成了,不過可真夠復(fù)雜的。注重觀察,實際上,Accelerate利用多重繼續(xù),把表達(dá)式轉(zhuǎn)換成一個二叉樹,葉結(jié)點就是實際的字符串。對于Acce有如下定義:

typedef Accelerate<Empty, Empty> Acce;

  上面的過程針對string,實際上可以推廣到其他的字符串形式,我們只需要重載特定的函數(shù):length,append:


size_t length(const char* str)
{
 return strlen(str);
}

Template<int SIZE>

size_t length(const char[SIZE] str)
{
 return SIZE – 1; //注重,形如length(”text”)這樣的代碼,重載決議將使用這個重載版本。
}
  至于append,也是類似的手法:

inline void append(string& str, const char* src){
 while(*src != ‘/0’) str.push_back(*src++);
}
  性能分析:

string str;
str.reserve(length(left) + length(right));
  這里,采用str是沒有必要的,在性能要害的場合,這里完全可以用內(nèi)存塊取代,可以改善性能。另外,length的計算,對于string和char [SIZE]這兩種形式,都是常數(shù)時間,后一種更是可以在編譯期優(yōu)化掉,無需計算。但是,對于char*這種形勢,strlen導(dǎo)致一次線性掃描。在 append的過程中,再一次線性掃描同一個數(shù)據(jù)來源,這是可以繼續(xù)優(yōu)化的地方。但是在這里繼續(xù)剖析的話,就弱化了我們懶惰計算的主旨了。在這里,只是展 示懶惰計算的威力。實際上,懶惰計算在ORM環(huán)境下也是經(jīng)常用到的,當(dāng)然也包括數(shù)據(jù)庫操作,和從文件加載對象這樣的操作。 為 了獲得某個數(shù)據(jù),必須進(jìn)行事先的若干處理才能獲得,假設(shè)事先處理的相對成本比較高,那么就可以考慮懶惰計算,在真正需要獲得數(shù)據(jù)的時候,才實施計算,另外 可以在實施計算時,可以有更多的信息,從而實施各種優(yōu)化手段。例如,ORM操作中,并不及時載入對象,當(dāng)對象真正需要時,批量載入多個Lazy的對象,從 而優(yōu)化IO也是一例。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 集安市| 南充市| 武邑县| 苏尼特右旗| 凉城县| 综艺| 玉溪市| 湟源县| 宁乡县| 娱乐| 长沙市| 读书| 哈尔滨市| 建湖县| 三都| 贵德县| 象山县| 广汉市| 衢州市| 蚌埠市| 德钦县| 通化县| 五常市| 阳城县| 安阳县| 旺苍县| 大姚县| 墨玉县| 浦北县| 彭山县| 砀山县| 波密县| 嘉鱼县| 东源县| 临沭县| 平阳县| 怀远县| 庐江县| 阿拉尔市| 大宁县| 宜川县|