|
| 1 | +Build Instructions: |
| 2 | + |
| 3 | +[acme@doppio ~]$ git-clone git://git.kernel.org/pub/scm/linux/kernel/git/acme/libautocork |
| 4 | +[acme@doppio ~]$ cd libautocork/ |
| 5 | +[acme@doppio libautocork]$ make |
| 6 | +gcc -O2 -g -Wall -fPIC -c -o libautocork.o libautocork.c |
| 7 | +gcc -O2 -g -Wall -fPIC -shared -o libautocork.so libautocork.o -ldl |
| 8 | +gcc -O2 -g -Wall -fPIC tcp_nodelay_client.c -o tcp_nodelay_client -lrt |
| 9 | +gcc -O2 -g -Wall -fPIC tcp_nodelay_server.c -o tcp_nodelay_server |
| 10 | +[acme@doppio libautocork]$ |
| 11 | + |
| 12 | + To use it: |
| 13 | + |
| 14 | +LD_PRELOAD=./libautocork.o your_application |
| 15 | + |
| 16 | + Using it with the test application in this tarball: |
| 17 | + |
| 18 | +1. start the server: |
| 19 | + |
| 20 | +[acme@doppio libautocork]$ ./tcp_nodelay_server 5001 10000 |
| 21 | +server: waiting for connection |
| 22 | + |
| 23 | +2. start the client without using libautocork and using nodelay: |
| 24 | + |
| 25 | +[acme@doppio libautocork]$ ./tcp_nodelay_client --verbose --no_delay localhost |
| 26 | +10000 packets (15 buffers) sent in 1776.608398 ms: 168.861069 bytes/ms using TCP_NODELAY |
| 27 | + |
| 28 | +3. Now lets try using libautocork with the same parameters used, i.e. |
| 29 | + reproducing an application that uses TCP_NODELAY and will have it |
| 30 | + turned into TCP_CORK by libautocork: |
| 31 | + |
| 32 | +[acme@doppio libautocork]$ LD_PRELOAD=./libautocork.so ./tcp_nodelay_client --verbose --no_delay localhost |
| 33 | +10000 packets (15 buffers) sent in 481.941132 ms: 622.482666 bytes/ms using TCP_NODELAY |
| 34 | + |
| 35 | +It is important to use './' or the full path, as the linux library |
| 36 | +loader will try to find it on the LD_LIBRARY_PATH list of paths or in |
| 37 | +what is in /etc/ld.so.conf, and as the current directory ('.') normally |
| 38 | +isn't you could get something confusing as: |
| 39 | + |
| 40 | +[acme@doppio libautocork]$ LD_PRELOAD=libautocork.so ./tcp_nodelay_client --verbose --no_delay localhost |
| 41 | +ERROR: ld.so: object 'libautocork.so' from LD_PRELOAD cannot be preloaded: ignored. |
| 42 | +10000 packets (15 buffers) sent in 1780.601074 ms: 168.482437 bytes/ms using TCP_NODELAY |
| 43 | +[acme@doppio libautocork]$ |
| 44 | + |
| 45 | +So using libautocork on a unmodified binary that uses TCP_NODELAY and |
| 46 | +sends 15 buffers and then wait for one buffer we get througput from |
| 47 | +168.861069 bytes/ms up to 622.482666 bytes/ms for 10000 packets. |
| 48 | + |
| 49 | +The test case can be used to do lots of other tests with TCP_CORK, |
| 50 | +TCP_NODELAY, sending packets built entirely in userspace (1 buffer), a |
| 51 | +header + a payload (2 buffers), etc: |
| 52 | + |
| 53 | +[acme@doppio libautocork]$ ./tcp_nodelay_client --help |
| 54 | +Usage: tcp_nodelay_client [OPTION...] [SERVER] |
| 55 | + |
| 56 | + -c, --cork use TCP_CORK |
| 57 | + -H, --header_plus_payload send logical packets header + payload |
| 58 | + -n, --no_delay use TCP_NODELAY |
| 59 | + -N, --nr_logical_packets=NR send NR logical packets [DEFAULT=10000] |
| 60 | + -p, --port=PORT connect to PORT [DEFAULT=5001] |
| 61 | + -s, --single_request send logical packets as a single request |
| 62 | + -v, --verbose be verbose |
| 63 | + -?, --help Give this help list |
| 64 | + --usage Give a short usage message |
| 65 | + |
| 66 | +Mandatory or optional arguments to long options are also mandatory or |
| 67 | +optional for any corresponding short options. |
| 68 | +[acme@doppio libautocork]$ |
| 69 | + |
| 70 | +The server also helps understanding what really happens in terms of |
| 71 | +number of times the read syscall returns with partial buffers, for |
| 72 | +instance, for the above sessions: |
| 73 | + |
| 74 | +[acme@doppio libautocork]$ ./tcp_nodelay_server 5001 10000 |
| 75 | +server: waiting for connection |
| 76 | +server: accept from localhost.localdomain |
| 77 | +server: received 119281 buffers |
| 78 | +server: waiting for connection |
| 79 | +server: accept from localhost.localdomain |
| 80 | +server: received 10000 buffers |
| 81 | +server: waiting for connection |
| 82 | +server: accept from localhost.localdomain |
| 83 | +server: received 121347 buffers |
| 84 | +server: waiting for connection |
| 85 | + |
| 86 | +The second one was the one with libautocork, so instead of receiving 120 |
| 87 | +thousand buffers (the number of real network packets is about the same) |
| 88 | +it received 10000 buffers (that is exactly the number of networking |
| 89 | +packets sans connection establishment and teardown) , the number of |
| 90 | +logical packets sent. |
| 91 | + |
| 92 | +To make sure that libautocork is being used you can take a look at the |
| 93 | +process shared memory library map: |
| 94 | + |
| 95 | +[acme@doppio libautocork]$ /sbin/pidof tcp_nodelay_server |
| 96 | +19091 |
| 97 | +[acme@doppio libautocork]$ grep libautocork.so /proc/19091/smaps |
| 98 | +2aaaaaaad000-2aaaaaaaf000 r-xp 00000000 fd:00 197010 /home/acme/libautocork/libautocork.so |
| 99 | +2aaaaaaaf000-2aaaaacaf000 ---p 00002000 fd:00 197010 /home/acme/libautocork/libautocork.so |
| 100 | +2aaaaacaf000-2aaaaacb0000 rw-p 00002000 fd:00 197010 /home/acme/libautocork/libautocork.so |
| 101 | +[acme@doppio libautocork]$ |
| 102 | + |
| 103 | +You can also use an environment variable: |
| 104 | + |
| 105 | +[acme@doppio libautocork]$ export AUTOCORK_DEBUG=1 |
| 106 | +[acme@doppio libautocork]$ LD_PRELOAD=./libautocork.so ./tcp_nodelay_client --verbose --no_delay localhost |
| 107 | +libautocork: turning TCP_CORK ON fd 3 |
| 108 | +10000 packets (15 buffers) sent in 491.302338 ms: 610.621948 bytes/ms using TCP_NODELAY |
| 109 | +[acme@doppio libautocork]$ |
| 110 | + |
| 111 | +Use a value of 2 to get more verbose output, such as when libautocork |
| 112 | +pushes pending frames, aka autocorks: |
| 113 | + |
| 114 | +[acme@doppio libautocork]$ export AUTOCORK_DEBUG=2 |
| 115 | +[acme@doppio libautocork]$ LD_PRELOAD=./libautocork.so |
| 116 | +./tcp_nodelay_client --verbose --no_delay localhost 2>&1 | head -10 |
| 117 | +libautocork: turning TCP_CORK ON fd 3 |
| 118 | +libautocork: autocorking fd 3 on read |
| 119 | +libautocork: autocorking fd 3 on read |
| 120 | +libautocork: autocorking fd 3 on read |
| 121 | +libautocork: autocorking fd 3 on read |
| 122 | +libautocork: autocorking fd 3 on read |
| 123 | +libautocork: autocorking fd 3 on read |
| 124 | +libautocork: autocorking fd 3 on read |
| 125 | +libautocork: autocorking fd 3 on read |
| 126 | +libautocork: autocorking fd 3 on read |
| 127 | +[acme@doppio libautocork]$ |
| 128 | + |
| 129 | +The autocorking is made on one of the following standard C library calls: |
| 130 | + |
| 131 | +read, readv, recv, recvmsg, recvfrom, select, pselect, poll and ppoll |
| 132 | + |
| 133 | +But only when data was sent on an file descriptor where |
| 134 | +setsockopt(TCP_NODELAY) was done. |
| 135 | + |
| 136 | +TODO: work on the cheapest possible timer to use to avoid having the socket |
| 137 | +autocorked when the application doesn't use one of the library calls that |
| 138 | +pushes the data. |
0 commit comments