Thursday, May 30, 2013

Tweaking tcp port - Improving performance of network intensive applications over high latency network

Building an application over a low latency network could give you very good performance, but sometimes over a high latency network, read() or write() system calls could be a cause of bottleneck for the applications performance.

Consider a network intensive application running on server A. This server continuously generates log and sends it over the network to another server B . Now, server B may be slow (low computation power) or the network may have high error/ latency, due to which the write buffer of A gets saturated. As a result server A stalls (write buffer of A is filled, but B is not ready to read the data yet).

By default in the linux kernel, each tcp port is configured with around 64-80KB read/write buffer.

This can be seen using the command :

$sudo su
#sysctl -a | grep net | grep mem

...
net.ipv4.tcp_mem = 93132        124179  186264
net.ipv4.tcp_wmem = 4096        16384   3973728
net.ipv4.tcp_rmem = 4096        87380   3973728
...

The numbers represent the minumum, default and maximum memory allocated to every tcp port  that is created on a machine.

For solving our current problem, all we need to do is increase the default port size to a larger value. Increasing the memory associated with a port can be done as follows:

#sysctl -w net.ipv4.tcp_rmem='4096        3000000   3973728'
#sysctl -w net.ipv4.tcp_rmem='4096        3000000   3973728'

NOTE: This change gets reflected on every port that is created on the server. Hence, one should be careful not to increase the default port size to a very large value, as each new connection would result in higher memory usage.





 

Thursday, May 2, 2013

Templates in C [Macros!]

Today I faced this problem of writing a generalized function in C that would accept a "configurable" type of argument. i.e. the function should be able to accept any kind of argument that I pass to it, and it should be able to do something with it (say print the value of the argument passed).

What I wanted could easily be done in C++ using TEMPLATES; create a function with a signature

void foo(class Template <T> x){
     cout << "x" << "\n";
     return ;
}

This cannot be done in C, as it is a middle level language (yes I said it! if you do not agree, go learn C++ STL :P ).

Now, there is NO (absolutely NO) way you can do function/operator overloading in C, hence we resort to finding workarounds... say what? macros biaatch!


MACROS - a coders nemesis -

Why:
1. Its difficult to write  a macro.
2. Its even more difficult to read a program with macros, you practically end up expanding the whole macros in your notebook / as comments in your code.
3. CSCOPE /CTAGS dont work on MACROS. you end up using grep instead to find out the exact place where the macro gets expanded.


Then Why do we still use it:
1. Makes ur code compact.
2. 1st reason is enough.

Without further ado, i present to you using macros to compactify (i just made that word up) your code.

consider the program :

int main(){
     callPrint_int(1);
     callPrint_float(4.2);
     callPrint_char('b');
     return 0;


1. Program without a macro:

callPrint_int(int x){
     cout << x;
}


callPrint_float(float x){
     cout << x;


callPrint_char(char x){
    cout << x;
}

2. Program with a macro: 

#define callPRINT(T) \
    void callPRINT_##T(T x) { cout << x ; }

callPRINT(int);
callPRINT(float);  
callPRINT(char);
  
each of the above three lines give you basically functions in part 1. but look at how compact your code becomes. isn't she a beauty :P.