編寫正常運行的程序很容易,但一旦數據量大起來,對代碼的性能就須要認真考慮了。對於服務器來講,若是客戶端一次訪問,就須要話費幾百毫秒,那麼一旦每秒的訪問次數多起來,後續的請求就會形成很明顯的延遲。嚴重影響用戶體驗。最近作後端服務也遇到了一些須要優化的問題,數據量大了後,有明顯延遲。 性能優化的前提是良好的構架設計:若是架構自己的設計就存在問題,在怎麼優化也所能提高的空間也是很小。根據二八原則,大部分性能應該消耗在不多的地方,因此優化的關注點就在於那20%最耗時的代碼塊,解決了這個問題,總體性能就會有很大的提高。 代碼層面的優化通常涉及到一下方面: ##1.併發模型的選擇 對於不一樣的功能須要用不一樣的併發模型,適合單線程仍是多線程,以及線程池這些都會影響到性能,對於服務器,模塊是io密集型仍是計算密集型。例如若是一次請求是須要作不少的計算,那麼用線程池是合理的可以簡化編程,可是若是一次請求主要時間是等待io,那麼線程池是沒法提高吞吐量的。 ##2.數據的存儲 ###容器的選擇 數據對象的存儲方式取決於對數據的使用方式,就拿C++容器來講,若是要存儲物品信息,通常系統中更多的是根據物品id來獲取物品信息,那麼久須要用key-value來存取,但map是紅黑樹,unorder_map是哈希表,哈希表的查詢時間是O(1),而對於map,插入、刪除都是O(logN),最壞和平均都是。 ###存取方式 是存指針仍是存數據,這個須要根據具體問題,具體分析,儘可能高效。 ##3.算法 算法的存在就是爲了高效的解決一些複雜問題,以減小時間或者空間複雜度。一個排序就有不少種選擇,冒泡,選擇,快排,堆排序,堆排序,歸併等。通常來講快排的總體效率比較高,那是針對於基本無序的序列,若是隻是後來的元素無序,前面基本有序,這時候簡單的使用快排就會形成下降性能。 ##4.代碼質量 ###使用引用 在C++中儘可能採用引用傳遞或者指針傳遞,這樣不會產生參數拷貝,若是傳入參數是一個複雜的數據結構,就能明顯的提高性能。同理獲取數據時也要用引用。 ###減小反作用 例如C++是不進行邊界檢查的,對於map的獲取value,若是該key不在map中,map會插入一個key,value爲默認值算法
std::map<int,int> i_map; int value = i_map[123];
map是紅黑樹實現的,紅黑樹最終是一平衡樹,這個插入操做會致使原來的樹不平衡,內部就須要翻轉達到平衡,這就會形成性能消耗。 ###同一變量的屢次獲取:編程
std::vector<int> v_int; ... for (int i = 0; i < v_int.size(); i++)
怎麼寫出高質量的C++代碼,推薦一本書 《高質量C++/C編程指南》。 ###同步鎖 服務器編程會涉及到多線程,一旦涉及多線程,多線程中不少涉及到競爭資源的非原子操做都須要進行加鎖,加鎖的方式有不少種有信號量,互斥器,條件變量,讀寫鎖。絕大多數狀況使用互斥器就能夠足夠實現大多數功能,並且相對於其餘鎖性能影響較小。但在使用mutex時也須要注意。後端