大家好,我是東北碼農。記錄一下工作中事。
前幾天,運維同事給我反饋了一個問題:
通過監控發現,線上的一個服務,業務執行緒時不時會出現卡頓,卡頓大約持續幾秒。
我們做金融系統後臺開發的,對效能要求很嚴格的,當然要查一查啦。
1、問題調查
1.1、top 日誌
top中有記憶體和cpu資訊,可以判斷出卡頓時記憶體使用暴漲,但cpu使用沒有下降。
應該是做了非常耗cpu和記憶體的操作,而不是等待什麼。
1.2、程式碼分析
通過top的分析,結合程式碼分析,發現業務程式碼中有vector操作,每收到一個包都會建立索引。虛擬碼如下
vector<uint64_t> idx_;
void on_recv(pkg *h)
{
idx_.push_back(h->seq);
}
應該是vector動態擴容時,造成的卡頓。下面來驗證一下。
2、vector
std::vector is a sequence container that encapsulates dynamic size arrays.vector的底層實現是陣列,在使用時採取動態擴容方式。
2.1、vector的size和capacity
vector有size和capacity兩個屬性,size是實際數量,capacity是容器當前容量。下面是cppreference中的解釋:
- size:returns the number of elements。
- capacity:returns the number of elements that can be held in currently allocated storage。
2.2、擴容
下面寫程式碼,觀察一下vector何時會擴容,以及擴容時的開銷。虛擬碼如下:在擴容時列印容量變化,以及耗時。
void test_vector()
{
vector<uint64_t> idxs;
uint64_t last_cap = 0;
for(int i = 0 ;i < 1200000000;i++)
{
auto begin = get_ns();
idxs.push_back(i);
auto cost = get_ns() - begin;
auto cap = idxs.capacity();
if(last_cap != cap || cost > 100*1000*1000)
{
printf("last_cap=%ju,cap=%ju,cost=%ju\n",last_cap,cap,cost/1000000);
last_cap = cap;
}
}
}
輸出如下:
last_cap=0,cap=1,cost=0
last_cap=1,cap=2,cost=0
last_cap=2,cap=4,cost=0
last_cap=4,cap=8,cost=0
last_cap=8,cap=16,cost=0
last_cap=16,cap=32,cost=0
last_cap=32,cap=64,cost=0
last_cap=64,cap=128,cost=0
last_cap=128,cap=256,cost=0
last_cap=256,cap=512,cost=0
last_cap=512,cap=1024,cost=0
last_cap=1024,cap=2048,cost=0
last_cap=2048,cap=4096,cost=0
last_cap=4096,cap=8192,cost=0
last_cap=8192,cap=16384,cost=0
last_cap=16384,cap=32768,cost=0
last_cap=32768,cap=65536,cost=0
last_cap=65536,cap=131072,cost=0
last_cap=131072,cap=262144,cost=0
last_cap=262144,cap=524288,cost=1
last_cap=524288,cap=1048576,cost=1
last_cap=1048576,cap=2097152,cost=3
last_cap=2097152,cap=4194304,cost=6
last_cap=4194304,cap=8388608,cost=13
last_cap=8388608,cap=16777216,cost=25
last_cap=16777216,cap=33554432,cost=51
last_cap=33554432,cap=67108864,cost=102
last_cap=67108864,cap=134217728,cost=204
last_cap=134217728,cap=268435456,cost=407
last_cap=268435456,cap=536870912,cost=818
last_cap=536870912,cap=1073741824,cost=1633
last_cap=1073741824,cap=2147483648,cost=3372
可以看出,vector在2的n次冪都會擴容。重要節點是
- capacity :1.3億~2.6億-時間約400ms
- capacity :2.6億~5.3億-時間約800ms
- capacity :5.3億~10.7億-時間約1600ms
3、問題解決
問題找到了,解決就容易了。
vector有reserve介面,可以在程式啟動時就擴容好,防止執行時動態擴容造成卡頓。
其實程式在啟動時,已經呼叫reserve提前擴容了,但是近期國際局勢不穩定,造成訂單量飆升,所以reserve的量不足,需要重新估計一下。
- reserve:reserves storage
東北碼農,全網同名,歡迎大家使用常用聊天軟體關注、評論交流~
如果大家覺得有用,求點贊、轉發~
謝謝你~