2014-09-18 52 views
0

在HFT交易應用程序中,我需要從udp多播套接字接收數據。唯一的要求是延遲 - 這非常重要,我可以「花費」一個CPU內核。無論旋轉或其他什麼都可以。這是我目前在Windows中:以最低的延遲從linux的多播套接字接收數據

void Receiver::ThreadMethod() { 
    //UINT32 seq; 
    sockaddr_in Sender; 
    int SenderAddrSize = sizeof(Sender); 

    while (stayConnected) { 
     int res=recvfrom(socketId,buf,sizeof(char) * RECEIVE_BUFFER_SIZE,0, (SOCKADDR *)& Sender, &SenderAddrSize); 
     if (res == SOCKET_ERROR) { 
      printf("recvfrom failed, WSAGetLastError: %d\n", WSAGetLastError()); 
      continue; 
     } 
     //seq = *(UINT32*)buf; 
     //printf("%12s:seq=%6d:len=%4d\n", inet_ntoa(Sender.sin_addr), seq, res); 
     unsigned char* buf2 = reinterpret_cast<unsigned char*>(buf); 
     feed->ProcessMessage(res, buf2); 
    } 
} 

recvfrom塊,所以這將是有可能很慢(或我錯了?)。我應該重寫這個Linux版本,並實現最佳的延遲。我需要每個線程只處理一個套接字,所以我認爲我不應該使用epoll,因爲它設計了更多處理多個套接字。我應該使用什麼?

UPD我找到了類似的問題Low-latency read of UDP port

+1

目前尚不清楚爲什麼你認爲阻塞recvfrom()調用會很慢。確實如果沒有收到數據包,它將不會長時間返回,但是如果/當收到數據包時它應該立即返回。您擔心的是上下文切換開銷嗎? – 2014-09-18 19:50:46

+0

順便說一句,如果你想保證低延遲,你可以看看Xenomai的Linux實時擴展,因爲這是他們提供的。 – 2014-09-18 19:51:48

+0

@JeremyFriesner阻止永遠是昂貴的,這就是爲什麼人們「旋轉」 – javapowered 2014-09-18 20:00:11

回答

0

在UNIX中,你應該使用fcntl設置您的插座非阻塞:

fcntl(socket, F_SETFL, O_NONBLOCK); 

此外,如果客戶需要處理多個插座(例如聚合多個提要),您應該使用一個select調用來一次處理多個文件描述符,並查看哪個套接字有可用的數據(如果有的話)(除此之外,這將避免在所有套接字中循環)

至於延遲,其他因素(如NIC類型和配置),內核設置(可能有一個繞過內核的NIC)將對延遲(待測量)產生相當大的影響。

+0

據我所知,在低延遲情況下最好使用「一個線程 - 一個插座」。還要注意我在兩個套接字上都收到了相同的數據。使用兩個線程可以並行接收兩個數據包,這應該會稍稍改善延遲。 – javapowered 2014-09-18 20:02:14

+0

網卡和其他一切都是輝煌的配置和在這個星球上最快,只有軟件尚未寫入。 – javapowered 2014-09-18 20:03:55

+0

@javapowered不,它不是「一個線程一個套接字」,大多數處理程序在一個或兩個CPU上旋轉選擇,但這一切都取決於您的可用硬件。 (無論如何多個步驟可以併發訪問NIC +上下文切換成本來運行它們)。跳這有助於。 – quantdev 2014-09-18 20:14:26