【前言】基於solarflare的onload模式加速,官方文檔給出TCPDirect模式可以實現從300ns到30ns的延遲縮減。我們需要測試在我們的交易模型框架中他的延時,有人給出了tcpdirect加速大約會比onload模式快300ns左右,不是倍數關系,是一個數量差。雖未達如此高速交易,但量化交易,分秒必爭。但是tcpdirect有一個缺點就是必須使用它的接口,不像onload只需要安裝好加速環境,使用onload模式就可以了。TCPDirect需要拿到源碼,並重寫底層。
我們實現一個類epoll-socket,TCPDirect使用了muxer,實現叫做zocket,進行RTT測試。
一、server端
對應epoll,我們使用muxer實現,和epoll接口類似。
1、注意后面要釋放掉創建的zf_muxer_free(muxer);
2、因為我們使用內核旁路技術,不要使用zf_recv()函數,雖然他有返回接收數據的大小,但是他是基於copy的,使用zf_zc_recv()。
3、每次在使用接口有數據交換或者使用硬件時,要使用zf_reactor_perform(stack);,因為我們的zocket是運行在一個初始化的stack上的,每次都要用此接口來進行“初始化”,文檔這樣寫的,我也不清楚。
4、其他的和epoll不同之處要悉心,比如無需綁定,用zft_listen()綁定,zf_zc_recv和zf_send的存儲的數據結構也不相同,下面有我的兩種數據的轉換存儲方式,因為在服務器端需要進行一個轉存;
5、測試時間的核心程序:
ZF_TRY(zf_muxer_add(muxer, zft_to_waitable(zock), &evs[i])); //初始化stack zf_reactor_perform(stack); rd1.zcr.iovcnt = 1; HP_TIMING_NOW(t0); zft_zc_recv(zock, &rd1.zcr, 0); if( rd1.zcr.iovcnt == 0 ) continue; if( first_recv ) { first_recv = 0; siov.iov_len = rd1.zcr.iov[0].iov_len; memcpy(buf, ((char*)rd1.zcr.iov[0].iov_base),siov.iov_len); } for( int i = 0 ; i < rd1.zcr.iovcnt; ++i ) { len3=zft_send(zock, &siov, 1, 0); } HP_TIMING_NOW(t1); //c++11的元組,編譯時候可能要加上-std=c++11 time_v.push_back(std::make_tuple(len3,t1, t0, (t1 - t0))); cout<<"服務器發送:"<<len3<<"數據:"<<buf<<endl; zft_zc_recv_done(zock, &rd1.zcr);
二、客戶端
1、初始化的stack可能會用完,要加上ZF_TRY(zft_send_space(tcp,&send_size));,send_size是一個傳出參數,返回tcp連接的棧剩余空間,小於目標大小的時候要判斷,然后重新分配,我們僅是實現測試,足夠我用;
2、測試結果,就在客戶端。我們需要發送和其他模式下同樣的數據,到server,然后返回,client再收到所用的時間。
3、發送和接受和server一樣注意,此處無需裝換;
4、輸出結果的代碼,使用tuple。mongodb那種nosql可以用這種數據組織方式存儲。
std::vector<std::tuple<int, u64_t, u64_t, int>>::iterator it; for (it = time_v.begin(); it != time_v.end(); ++it) { cout << "len=" << std::get<0>(*it) << " --- recv time = " << std::get<1>(*it) << ", send time = " << std::get<2>(*it) << ", gap = " << std::get<3>(*it) << endl; if (it != time_v.begin()) { sum += std::get<3>(*it); ++num; } }
#第一個時間是jiffies,要除以本機的cpu主頻
std::cout << "avg gap = " << (sum / (num*1.0) ) << endl;
std::cout << "avg gap(ns) = " << (sum / (num*3.4)) << endl;
(關於jiffies和cpu頻率的關系:https://www.cnblogs.com/by-dream/p/5143192.html 相除就是時間)
使用tcpdirect在char類型511字節數據上,進行RTT測試,循環1000次的平均用時3444納秒(3.5微秒)左右。
具體和普通socket、使用onload加速的對比:
當然,這只是個別。我大約測了10次,平均值大約如此。
三、收獲心得
1、學會了初步的gdb- 對於coredump情況調試方法,學會了一些分析錯誤的思路。
2、tcpdump抓包分析,wireshark分析。