Saturday, April 29, 2006

static Objects/Variables considered loosers because they finish last

Encapsulation is one of the cornerstones of good OOP; it keeps objects from interfering with another and generally reduces complexity and dependencies. The static keyword on the other hand, is a memory trap waiting to happen, if your not careful. Normally when an object is created its constructor is called and all its members constructors are called. Eventually, when it goes out of scope, their destructors are called. When you declare a static object, it sticks around; the destructor isn't called until the end of the program. This may be okay if done on a small scale with small objects but if you're not aware of the ramifications, and you use static objects with large amounts of memory, you may be consuming alot more memory then you need to be. Note, the scope of the object is still limited but its memory usage is not.

Friday, April 28, 2006

The Value of intelligent Code

Artificial intelligence is often used by many as a black box term to describe unquantifiable intelligence in a peice of software. It was touted as a revolutionary concept that would change everything. These days it doesn't get nearly as much attention. This isn't the concept I'm talking about.

Ideally, the code you write would be intelligent enough to know when its not working right; it would be able to tell you what was wrong without to much ambiguity. The reality of the matter is: software projects have gotten so huge that its increasingly difficult to debug them, especially when shared libraries are involved and your making calls between those libraries. The code won't speak up for itself, not without a good software developer.

Intelligent code should check itself for errors through conditional statements both through asserts and conditional code checking. This code would check and double check values; it would check preconditions on entry, runtime conditions at runtime and postconditions at the exit. All this checking may very well add alot of overhead; macros can ameliorate this condition.

In the end, the time you save by writing a few conditional checks here and there will save you much debugging and development time.

Thursday, April 27, 2006

Polymorphism

Polymorphism does make use of inheritance but it means so much more; the ramifications of polymorphism go much further then inheritance. Polymorphism allows for objects to have dynamic behavior based on subclasses.

To use polymorphism in C++ you need to use pointers or references and virtual methods. In C++ an object may have a static type and a dynamic type associated with it. The static type is the type associated at compile time; the dynamic type is associated at run time. For example: SomeClass *obj; This shows that obj is a pointer of type SomeClass. At runtime the obj may assigned to point to subclasses of SomeClass thus allowing for dynamic functionality. If a subclass's method is not declared virtual then the base class method will be called. Its important to make the destructor of a subclass virtual so that both the base class and subclass's destructor are called.

You dont want to declare methods as virtual needlessly. There is a cost associated with virtual methods; everytime a virtual method is called a look up table must be accessed to determine the objects functionality thus adding overhead.

Pascal Aschwanden

Wednesday, April 26, 2006

Constructor/Destructor ordering

The order in which constructors and desctructors were called were relevant in the bug I was solving this morning, so I figured a good review was in order. This tutorial was verifed in C++. For any given class the constructors for that class are called before the actual class constructor. The super class constructors of a class are called before the derived class. Destructors are called in exact reverse order of constructors. Examine the following example with it's output. You'll see that Base class constructors are called before the derived classe's constructor; every class member's constructor gets to go before the containing class.

class B
{
public:
B() { printf("class B constructor\n");}
~B() { printf("class B destructor\n");}
};
class C
{
public:
C() { printf("class C constructor\n");}
~C() { printf("class C destructor\n");}
};
class SuperA
{
public:
SuperA() { printf("SuperA constructor.\n"); }
~SuperA() { printf("SuperA destructor.\n"); }
private:
C c;
};

class A: SuperA
{
public:
A() { printf("class A constructor.\n"); }
~A() { printf("class A destructor.\n"); }
private:
B b;
};

int main()
{
A myA;
return 0;
}

Output:
class C constructor
SuperA constructor.
class B constructor
class A constructor.
class A destructor.
class B destructor
SuperA destructor.
class C destructor

Pascal Aschwanden

Sunday, April 23, 2006

Linux kernel process scheduling

The linux scheduling works by dividing the CPU time into periods called epochs. Every process has a time period known as the time quantum; this is the maximum time a process may have durring a particular epoch. Once all processes have used up their whole time quantum a new epoch will start and the time quantums will be recalculated.

Real-time scheduling for OS

With real time scheduling you have a notion of dispatch latency, this is the time it takes between when a process is scheduled and when it actually is executed. The interrupt handlers can't be interrupted so they form the worst case dispatch time. If the OS is pre-emptible then it can be interrupted between any step of a system call, with some exceptions like interrupt handlers. The disadvantage of a pre-emptible OS (like Solaris) is that it has to protect all its data structures with mutex and semaphores to prevent resource conflicts. Non-preemptilbe OSs can not be interrupted in the middle of a system call so they dont have this problem.

Another option besides making the OS pre-emptible, insert preemption points in long duration system calls.

Multilevel feedback queue scheduling

This form of process scheduling gives priority to shorter jobs. For example, processes that last less then 8 ms may be put into queue 0, process that are between 8 and 16 ms will be put into queue 2, quue three may get all the process that are longer then 16 ms. The result is, it leaves I/O bound processes in the higher level of the queue and cpu bound processes in the lower levels of the queue. The MFQS is the most general scheduling algorithm.

multi-level feedback queues are specified by the following parameters:
- number of queues
- scheduling algo for each queue
- method used to upgrade or demote a process from level to another

Saturday, April 22, 2006

Linux multi-threading

Software multi-threading facilitates concurrency in applications; this is of particular importance to applications that may have blocking calls like I/O. The advantage of user-level multi-threading over multiple processes is that it allows for switching of tasks without incurring a kernel level context switch; one thread can switch to another without having to make a kernel level call. This is especially important to servers that must be able to handle multiple requests at any given time. The disadvantage is, if the OS is single threaded, a thread makes a system call, then all other threads from that process must wait until the system call finishes because the process scheduling happens at the process level; the kernel doesn't see the individual user-level threads.

Kernel-level threading mitigates this problem because the kernel is aware of each thread an threats them as separate processes as far as scheduling is concerned. But, kernel-level threads will cause scheduling bias towards the processes that have more threads. A process with 100 threads will get 100 times more scheduling time, on average, then a process with one thread.

The threads of a multi-threaded application all share the same memory so care must be taken to avoid memory corruption and access to resources thus requiring semaphores and mutexs. One multi-threaded process uses fewer resources than multiple redundant processes including memory, open files and CPU scheduling.

Pascal Aschwanden

Saturday, April 15, 2006

A few essential Unix utilities

There are a few essential unix commands every developer should know. I have used these utilities on a number of occassions and found them to be quite useful. There are dozens, even hundreds of utilities available in unix but these four provide the most often used functionality needed to operate in a linux environment besides the obvious basics (ls, cd, mkdir, etc). I will just cover the basic uses of these commands, providing the most frequent usage. Note, some of these usages will only work on some versions of the command. For example, there are some differences on the way the details work between Linux and Solaris.

find - find the files your looking for, searches recursively
grep - search for strings and get their corresponding lines
awk - search for strings and permutate output (allows many more functionalties)
sed - stream editor, can be used for search and replace

Usage: find [searchfrom] -name [name of file]
Usage: find [searchfrom] -atime [-n/+n/n]

Example:
find . -name filename // find all files named filename in current working directory and down
find directory1 -name file* // find all files named file* in directory1 and down
find . -atime -3 // find all files accessed less then three days ago from current working directory and down
find . -atime +3 // find all files accessed less then three days ago from current working directory and down

An important difference between find and grep, grep does not search recursively unless you specify -r. Such as:
grep -rI [pattern] filename

Awk is a great way to parse through log files, flat files to extract tabular information like below; this will print the second word from each row that contains the word SearchString.
awk '/SearchString/ { print $2 }' < input_file

Sed allows you to search and replace from the commandline like so:
sed 's/search/replace/' file1 > file2

The above four can be combined with various other unix commands through a pipeline for some very powerful usages. But, thats a topic for another blog entry.

Pascal Aschwanden