[英]Execution time of c++ code on Linux for the first time is extremly slow
我相信很多人都經歷過。 第一次在Linux上執行c ++代碼總是要花費更長的時間。
就像調用::clock_gettime(CLOCK_REALTIME, &ts);
第一次比我的Linux機器上的第三次慢大約五倍。
第一次分配內存比第二次慢100倍。
我嘗試了預分配並在應用程序中使用了mlockall
,但是即使如此,一個函數的第一次執行比第二個函數慢約160倍,第二個函數慢於第三個函數。
該函數的偽代碼如下。 msg
在堆上分配。 但是它不包含在時間測量中。 msg2
是POD,因此在slow_for_the_first_time
根本沒有內存分配。
void slow_for_the_first_time(Message * msg) {
Msg2 msg2;
//set msg2 using msg
.... }
只是想知道,是什么原因導致第一次執行的緩慢? 有沒有避免的方法?
erenon的答案很有幫助。 我認為可能是因為Msg2是在so庫中定義的。
在使用LD_BIND_NOW = 1之前,第一個執行時間約為8000納秒,第二個執行時間約為500納秒,第三個執行時間約為200納秒。
現在,第一個執行時間約為2000納秒,而第二個和第三個執行時間保持不變。 因此它仍然比第三次執行慢10倍,應該有其他因素影響第一次執行時間。
一些有趣的發現。
在slow_for_the_first_time
之前的以下調用方法可以將第一次執行時間再減少1微秒
void dummySet(Msg2& msg2)
{
//set all fields of msg2. msg2 has about 30 fields it won't work if only set one field of msg2.
}
另一個值得一提的是,第一次執行的速度絕對與msg
無關,因為下面代碼中的第二個slow_for_the_first_time
char buffer[sizeof(Message)];
memset(buffer, 0, sizeof(buffer));
slow_for_the_first_time((Message*)buffer);//calling the method with a dummy buffer.
.....
slow_for_the_first_time(msg);//calling the method for the second time with a real msg.
在下面的代碼中與第二個slow_for_the_first_time
一樣快
slow_for_the_first_time(msg);//the first time takes around 2000 nanoseconds
.....
slow_for_the_first_time(msg);//the second time takes around 500 nanoseconds.
首次引用動態鏈接的符號時,需要在一組動態加載的符號中進行查找。 要查看這是否確實是問題所在,請執行以下操作:
$ LD_BIND_NOW=1 ./your_program
如果GOT和PLT中的每個條目, LD_BIND_NOW
都會指示鏈接器修復地址:這將使啟動速度稍慢,但也可能解決交換中的“首次呼叫速度慢”的問題。
如果證明是問題所在,則可以嘗試靜態鏈接庫或預鏈接。
除了他們的答案中提到的惰性鏈接erenon之外,還有其他兩個因素會導致首次運行時執行緩慢:冷緩存和冷分支預測。
總體而言,后續調用的加速來自:
總體而言,代碼在首次執行時往往會變慢。 如果這是一個問題,則解決方案是:
LD_BIND_NOW
,在啟動時鏈接;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.