c++11標準庫的regex比boost庫的regex之間的效能差距接近5倍,這是為什麼?stackflow上也找到一篇post《c++11 regex slower than python》,大家在7年前就有討論了,但是沒有一個答案。裡面有人給出boost快5倍的例子。
今天就此做一個小小的profile 進行分析對比。
環境:devtoolset-7 on atlarch centos 7,
編譯連結:O2優化,boost169 on dnf。
測試內容:100次 regex_search,因為不是benchmark,所以少量100次。測試程式碼放在結尾。
量化單位:self 欄指令週期,call欄次數。
現在開始分析profile,每張圖上面是boost::regex-profile,下面是std::regex-profile。
上圖,ld.so可以看作一個程式的基本開銷,二者是相當的,所以除去。
測試程式名稱是zbuffer,即@MAIN主映像,regex程式碼內聯在這個模組。
主要模組的profile對比
模組名 | boost | std |
@MAIN | 329608 | 3966488 |
libstdc++ | 577719 | 1527035 |
libc | 137741 | 913459 |
libboost_regex | 117581 | 57632 |
主要差距存在前倆, boost約90w,std約450w,接近5倍。
可以直觀看出,boost庫在@MAIN內聯的程式碼,加上庫的執行程式碼,效能消耗十分少,不到50w,比std::regex程式在libc上消耗的還少的多。std::regex究竟做什麼了。
第二張圖是主模組的profile對比,std::regex主要消耗在前8項,主要有_Execute,new,delete。
std::regex的_Execute佔了120W,new+delete佔了180W。
拋開new+delete操作的巨大損耗,std::regex的_Execute的消耗依舊比boost::regex全部消耗高出1倍。
第三張圖是libstdc++的profile對比,
boost基本沒多少new的操作,std::regex卻又大量動態型別操作,損耗50w。這損耗量,boost::regex已經足夠完成工作了。
第四張圖是libboost_regex的profile。
因為,std::regex測試程式也連結了libboost_regex.so,正好可以觀察std::regex又在什麼破事情是損耗。boost在這個模組上的消耗時實實在在的,10w+。std::regex測試程式在libstdc++庫的std::string::_S_construct被libboost_regex庫接替,反過來看,std::regex的std::string多了3400+次的操作。
最後一張圖是libc的profile
boost::regex與std::regex的profile對比完結。
測試程式碼來自網路
int veces = 100; int count = 0; zlab_allocator<>::inst(); using namespace std; regex expres ("([^-]*)-([^-]*)-(\\d\\d\\d:\\d\\d)---(.*)\\n", regex_constants::ECMAScript); std::string text ("some-random-text-453:10--- etc etc blah\n"); smatch macha; auto start = std::chrono::system_clock::now(); for (int ii = 0; ii < veces; ii ++) count += regex_search (text, macha, expres); auto milli = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - start).count(); std::cout << count << "/" << veces << " matches " << milli << " ms --> " << (milli / (float) veces) << " ms per regex_search" << std::endl;
profile檔案放在我的github.com/bbqz007。