Tuesday, September 27, 2011

C++ RAII - Resource acquisition is initialization.

RAII - Resource Acquisition is initialization is one of the powerful idioms in C++, which makes code exception-safe and maintainable. The idiom makes use of the feature of C++ that destructor for stack allocated objects would be called at the end of scope. Generally, resources can be allocated and deallocated at any point in implementation, which could be acceptable in all-goes-well scenarios. If exception had been thrown during execution of code, after resource allocation, but before release, then huge possibility is there to have the resource not released properly.

At the end of scope, in C++, all the stack allocated objects will be destructed for sure, even exception is thrown. RAII Idiom makes use of this feature by wrapping the resource in a class. In constructor, resource would be allocated and in destructor, release would happen. This is exception-safe. This calls for cleaning up all the resources at single place, destructor, instead of sprinkling this logic everywhere.

Let me give a simple example to illustrate this concept using File Stream example. Consider a function which takes two arguments, a string and file name; Let us assume the functionality of this is to write the string into file. One may code as given below.

fstream stream;
stream.open(fileName, ios::binary | ios::out | ios::app);

if(stream.is_open())
{
stream << str; // Assume there is an exception here ...
}

stream.close();

If there is some exception thrown at some point while writing, stream.close() won't get called at all. One solution is to solve this is adding a try/ catch around the writing part, which may lead to unessential maintenance issues. Program wouldn't be easily readable also. Let us rewrite the same using RAII as below.

class SmartFile
{
public:
SmartFile(string fileName)
{
cout << "Stream Opening" << endl;
stream.open(fileName, ios::binary | ios::out | ios::app);
}
~SmartFile()
{
cout << "Stream Closing" << endl; stream.close();
}
void WriteString(string str)
{
if(stream.is_open())
{
cout << "File Writing" << endl; stream << str;
}
else
{
cout << "Write Error" << endl;
}
}
private:
fstream stream;
};

void WriteStringToFile(string str, string fileName)
{
SmartFile file(fileName);
file.WriteString(str);
}

The above function using RAII class SmartFile which is reliable, exception-safe. You can try the below given code to understand the same.

void WriteStringToFile(string str, string fileName)
{
SmartFile file(fileName);
throw 10;
file.WriteString(str);
}
Even though the above code throws an error code abnormally, SmartFile's destructor will be called.

RAII is being used in Smart Pointers, Synchronization based lock classes, etc. In a nutshell, this idiom necessitates to have all resources allocations in constructor and all deallocation logic in destructor to make the code exception-safe and maintainable.

Thanks for Reading.

Saturday, September 24, 2011

Nagle's Algorithm - Intuitive understanding.

In TCP / IP stack, at every layer some header information would be added up to make sure the information is identifiable at the corresponding layer in the destination node. For instance, at TCP Layer, TCP header would be added, which contains essential information to make sure TCP segments reach properly at the destination and congestion control is provided, etc. Without TCP header, these functionalities would be handled at the upper layer, say application layer which mainly deals with real data being sent.

Layered architecture imposes disparate responsibilities for layers. App layer deals with semantics of data. Transport deals with transport of data in a reliable way. IP to pass packets to the next hop, etc. So, real data will be treated in different ways in different layers. In Transport layer, TCP, data unit is Segment, In IP the same is Packet. This leads to varying level of treatments of the same information.

Applications can't determine how data would be transmitted to the destination. This in several cases wouldn't be a problem. For instance, file transfer would send large amount of data to TCP layer and TCP would transfer the same to the destination in FIFO, first in first out, order. TCP would internally divide the real file into several chunks whose size matches, MSS, Maximum segment size. This behavior is neat since chunks will be sent in FIFO and chunk size depends on several optimal network parameters like destination node's capability, network channel's bandwidth, etc. As long as file is being transmitted in a reliable way, this approach or algorithm is optimal. Only overhead in segment based transfer is TCP header along with IP header which would be 40 bytes in general. If MSS is 1000 bytes, this overhead is acceptable, since always segment size will be of MSS. Let us consider a Telnet session in which command data will be less than Header size. In this scenario, overhead is unacceptable as it is far bigger than real data being passed. If the real data being sent is 1 byte, then it overhead is of 4000%. In low bandwidth environment, this is a bottleneck.

The Nagle's algorithm solves this issue by buffering, called Nagling, the data to be sent. Algorithm is very intuitive. If the buffered data is enough to fit in a segment of size MSS, then it would be sent across; If all the sent data are already acknowledged, no need to buffer the current data at all.

Let us see how this algorithm works.

The issue discussed is not at all a problem in High bandwidth environments and data should be passed however low is the size of data. In several real time systems, this is an essential behaviour. In high bandwidth environments, most probably all data sent across would be acknowledged immediately. So, Nagling wouldn't happen.

In Low bandwidth environments, the data would be accumulated by TCP until the segment size of MSS, and send across. This would help to avoid overhead what we had discussed. The real issue with Nagling comes up where real time low data traffic should be sent in Low bandwidth environments. In this scenario, data transfer wouldn't happen immediately but buffered, which would lead to irritating user experience.

One more issue with Nagling is "Delayed ACK"s from the sender side which would delay the acknowledgements of Segments for certain time to optimize the network utilization.

Delayed ACKs' idea invalidates the Nagling optimization heuristic, since the latter depends on getting ACK to decide the buffering. Delayed ACK would make the Nagling happen always independent of network bandwidth but Nagling should happen only in Low bandwidth network. Nagle Algo's heuristic is not applicable in case Delayed ACK is enabled in Destination.

Almost all TCP implementations would allow to disable Nagling using TCP_NODELAY option, even though it is not suggested. In application level, the issues of Nagling could be resolved in several ways as explained in WikiPedia page,

Thanks for Reading.

Friday, September 9, 2011

Wubi installer - Neat way to install linux in Windows System

After I had decided to install Linux on my Windows system, I had few options like Debian and Ubuntu. When I tried Debian, the one I had got from "Linux for you" Magazine, I suffered a lot to make it work along with Windows. I had to allocate a different partition for Debian OS and take care of dual boot, etc. Even though I worked in Linux in my college days, I found a lot of hurdles in this process. After that, I had come across the Wubi installer for Ubuntu which makes installation along with existing Windows OS seamless. Believe me, I didn't find any difficulty with installation. It installs in Windows machine as if it were another windows application. It configures itself with boot options. No need to worry about any configurations at all.

Installer can be downloaded from http://www.ubuntu.com/download/ubuntu/windows-installer.

Even though Wubi claims this particular way of installation may lead to disk access performance hurt, I couldn't find any difficulty at all. This is far better than having linux running in Virtual machine inside Windows OS, an another way to seamlessly work with Windows. This version of Ubuntu is having amazing UI, I would say, comparable with MAC. UI is really intuitive. I just tried IDLE for Python. I would dare say, Linux version of IDLE is far superior than Windows'. I feel like programming a lot now. I will come with some more findings on this.

Thanks a lot for reading.