January 23, 2006

Nagle's algorithm 與 PCManX

Cisco 的文件 [Managing System Performance] 這麼提到:
    Limit TCP Transactions

    When using a standard TCP implementation to send keystrokes between machines, TCP tends to send one packet for each keystroke typed, which can use up bandwidth and contribute to congestion on larger networks.

    John Nagle's algorithm (RFC 896) helps alleviate the small-packet problem in TCP. The first character typed after connection establishment is sent in a single packet, but TCP holds any additional characters typed until the receiver acknowledges the previous packet. Then the second, larger packet is sent, and additional typed characters are saved until the acknowledgment comes back. The effect is to accumulate characters into larger chunks, and pace them out to the network at a rate matching the round-trip time of the given connection. This method is usually good for all TCP-based traffic. However, do not enable the Nagle slow packet avoidance algorithm if you have XRemote users on X Window sessions.
不過以前讀的時候沒有很仔細思考,剛剛閱讀 [Boost socket performance on Linux] 時,才想到 [PCManX] 的確有改進空間,於是著手修改,ChangeLog 如下:
    * src/view/telnetcon.cpp (CTelnetCon::ConnectAsync): Disable the Nagle (TCP No Delay) algorithm. Nagle algorithm works well to minimize small packets by concatenating them into larger ones. However, for telnet application, the experience would be less than desirable if the user were required to fill a segment with typed characters before the packet was sent.
[Nagle's algorithm] 也就是 [RFC896],是 John Nagle 提出用以縮減網路傳輸過程中的封包數量,這一過程稱為 nagling,對於 traffic control 有顯著效益,不過對於 telnet 這類小封包資料傳遞的應用程式來說,如果 disable Nagle algorithm,可提昇反應速度,在 socket programming 中,這個 flag 通常是 TCP_NODELAY 。

除了 [PCManX],在 X Window System 的實做中,也需要 disable Nagle algorithm。在 Ubuntu Dapper 安裝 xtrans-dev (X transport library) 後,會有以下檔案: (按:為什麼 -dev 的套件中,會有 source code?)
    jserv@venux:~$ dpkg -L xtrans-dev
    /usr/include/X11/Xtrans/transport.c
    /usr/include/X11/Xtrans/Xtrans.c
    /usr/include/X11/Xtrans/Xtrans.h
    /usr/include/X11/Xtrans/Xtransdnet.c
    /usr/include/X11/Xtrans/Xtransint.h
    /usr/include/X11/Xtrans/Xtranslcl.c
    /usr/include/X11/Xtrans/Xtransos2.c
    /usr/include/X11/Xtrans/Xtranssock.c
    /usr/include/X11/Xtrans/Xtranstli.c
    /usr/include/X11/Xtrans/Xtransutil.c
    
與平台相關的部份是 Xtranssock.c ,其內部實做如下:
    static XtransConnInfo
    TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
    {
      ...
        XtransConnInfo      newciptr;
        struct sockaddr_in  sockname;
        int                 namelen = sizeof(sockname);
        if ((newciptr = (XtransConnInfo) xcalloc (
            1, sizeof(struct _XtransConnInfo))) == NULL)
        {
            *status = TRANS_ACCEPT_BAD_MALLOC;
            return NULL;
        }
    
        if ((newciptr->fd = accept (
            ciptr->fd,
            (struct sockaddr *) &sockname, 
            (void *)&namelen)) < 0)
        {
            xfree (newciptr);
            *status = TRANS_ACCEPT_FAILED;
            return NULL;
        }
    
    #ifdef TCP_NODELAY
        {
            /*
             * turn off TCP coalescence for INET sockets
             */
    
            int tmp = 1;
            setsockopt (newciptr->fd, 
                IPPROTO_TCP, TCP_NODELAY,
                (char *) &tmp, sizeof (int));
        }
    #endif
    
[[200 OK]: A Port80 Software Blog] 有篇 [TCP_NODELAY: To Nagle or Not To Nagle?] 可作為參考。
由 jserv 發表於 January 23, 2006 04:38 AM
迴響

所以[Boost socket performance on Linux]中的第一個技巧原因說明==> If the user were required to fill a segment with typed characters before the packet was sent, the experience would be less than desirable. 其實這句話並不真確,說的好像客戶端程式不會在未填滿segment前送出似的,不過Nagle演算法會造成以小packet傳輸為主的應用程式有較長的延遲倒是無庸置疑(因為要等ACK)

reborn2266 發表於 February 7, 2006 01:45 PM
發表迴響









記住我的資訊?