Tuesday, May 27, 2008

c++: virtual functions in contructors

There is a limitation on virtual function calls in constructors. If you call a virtual function in the constructor of the base class that was overridden in derived class you will be surprised. The function of base class will be called:

class A
{
    public:
        A() {function();}
        virtual void function() {cout << "A" << endl;}
};

class B : public A
{
    public:
        B() {function();}
        virtual void function() {cout << "B" << endl;}
};

int
main(int argc,
    char **argv)
{

    B b;

    return 0;
}
This code produces
A
B
output. The explanation is pretty simple, when constructor of the base class is called the derived object has not been constructed. This way c++ protects us. You don't have access to the derived class object from the the base class constructor. Only when initialization of base class was had been finished virtual table is being refreshed.

Friday, May 23, 2008

c++: reuse memory for objects

It happens when you are creating and deleting objects heavily. Like this:

    for (int i=0;i<1000000;++i)
    {   
        A *a = new A;

        //do something with 'a'

        delete a;
    }
Yup, it happens and sometimes it's a best solution. If you can't use stack memory because A is pretty big and you used almost all of the stack memory before or used a recursion. But this is extremely slow. You obtain memory fragmentation and invoke memory manager to get free chunk of memory and than free it. c++ specification allows you to reuse memory:
#include <new>

int
main(int argc, char **argv)
{
    char *memory = new char[sizeof(A)];
    void *place = memory;
    
    for (int i=0;i<1000000;++i)
    {
        A *a = new(place) A;

        //do something with 'a'

        a->~A();
    }   
}
In the code sample above A in the loop is always put into the 'memory'. The executable will request for the chunk of memory once before the loop. Depending on the code this may be more than 10 times faster. While using new() developer have to call destructor explicitly and include 'new' header manually. Anyway, if you can put A in the loop into the stack, try to do it. It the fastest and the safest way:
    for (int i=0;i<1000000;++i)
    {   
        A a;

        //do something with 'a'
    }   

Thursday, May 22, 2008

c++: default initializers

In c++.03 you are unable to call explicitly one constructor within another:

class A
{
    public:
        A(int x, int y) : x(x), y(y) {}
        A(int x) { A(x, 0); }

        int x, y;
}
This will produce compilation errors. As a workaround developers usually use an initialization function that can be called within the constructor:
class A
{
    public:
        A(int x, int y) : {init(x, y);}
        A(int x) {init(x,0);}

        int x, y;

    protected:
        void init(int a, int b) {x = a; y = b;}
}
The idea I got today is to make an abstraction of class data in base struct, derive class from the struct and initialize struct data with it's constructor. This will make things clear and will allow to separate data from its manipulation:
struct A
{
        A(int x, int y) : x(x), y(y) {}

        int x, y;
};

class B : public A
{
    public:
        B() : A(0, 0) {}
        B(int x) : A(x, 0) {}
};

c++: constructor arguments

Names of constructor arguments which will initialize class members can have the same name as class members:

class A
{
    public:
        A(int x) : x(x) {} 

        int x;
};
I used to make a prefix for constructor arguments as thought compiler will produce an error message. Yeah, now source code can be cleaner. Be aware that next code won't work:
class A
{
    public:
        A(int x) {x = x;} 

        int x;
};
Here x in constructor's body is the argument of the contructor. You will have an unexpected value of A::x each time as it not initialized. As a workaround:
class A
{
    public:
        A(int x) {this->x = x;}

        int x;
};
Here x in constructor's body is argument of constructor and this->x is A::x.

Wednesday, May 7, 2008

bash: completion

Almost everybody uses bash. It's awesome with it simplicity and power. Recently I've been introduced to bash completion in conjunction with ssh. The author proposed to use bash completion to expand list of known hosts(~/.ssh/known_hosts) for ssh. He suggested to fetch the list and feed it to 'complete' built-in bash command:

complete -W "`cat ~/.ssh/known_hosts \
| cut -d ' ' -f1 | cut -d ',' -f1 | cut -d ']' -f1 \
| sed 's/\[//' | sort`" ssh
This command will provide a fixed list. If you eventually have gone to the new host the new hostname will be lost for the completion. I've made some investigation and have found out that you can provide a function for 'complete' that will be called each time the completion requested. Here is a function:
function _ssh_comp()
{
CUR="${COMP_WORDS[COMP_CWORD]}";
COMPREPLY=( $(compgen -W "$(gawk 'BEGIN {i=0}\
{split($1,nodes,",");\
gsub("([[]|[]]:?[0-9]*)","",nodes[1]);\
hosts[i++]=nodes[1]}\
END {for (j in hosts) {print hosts[j]}}' ~/.ssh/known_hosts)" -- ${CUR}) );
return 0;
}
From the bash reference:
We can read the description of COMPREPLY
An array variable from which Bash reads the possible completions generated by a shell function invoked by the programmable completion facility
We can also see how we found the current word using the array COMP_WORDS to find both the current and the previous word by looking them up
An array variable consisting of the individual words in the current command line. This variable is available only in shell functions invoked by the programmable completion facilities.
COMP_CWORD
An index into ${COMP_WORDS} of the word containing the current cursor position. This variable is available only in shell functions invoked by the programmable completion facilities
Then you should tell 'complete' to use this function:
complete -o default -F _ssh_comp ssh
I typed 'ssh 1' then pressed and here we go:
$ssh 192.168.229.1
192.168.229.128  192.168.229.130  192.168.229.132  192.168.229.134  192.168.229.137  192.168.229.140  192.168.229.145  
192.168.229.129  192.168.229.131  192.168.229.133  192.168.229.136  192.168.229.138  192.168.229.144  192.168.229.146

Wednesday, April 30, 2008

c/c++: switch vs. array of functions

As I promised I made some tests to compare switch statement and a map to functions. As I expected a map to functions works faster. Furthermore it doesn't depend on the amount of 'switch' conditions. I made a synthetic test:

unsigned long func(unsigned long acc)
{
    return acc*acc;
}

#define SWITCH

typedef unsigned long (*fd)(unsigned long);

int main(int argc, char **argv)
{
    unsigned long i, acc = 0;

    #ifndef SWITCH
        fd f[15] = {func,func,func,func,func,func,func,func,func,func,func,func,func,func,func};
    #endif

    for (i=0;i<1000000000;++i)
    {   
        #ifdef SWITCH
            switch (i%15)
            {
                case 0:
                    acc = func(acc + i); break;
                case 1:
                    acc = func(acc + i); break;
                case 2:
                    acc = func(acc + i); break;
                case 3:
                    acc = func(acc + i); break;
                case 4:
                    acc = func(acc + i); break;
                case 5:
                    acc = func(acc + i); break;
                case 6:
                    acc = func(acc + i); break;
                case 7:
                    acc = func(acc + i); break;
                case 8:
                    acc = func(acc + i); break;
                case 9:
                    acc = func(acc + i); break;
                case 10: 
                    acc = func(acc + i); break;
                case 11: 
                    acc = func(acc + i); break;
                case 12: 
                    acc = func(acc + i); break;
                case 13: 
                    acc = func(acc + i); break;
                case 14:
                    acc = func(acc + i); break;
            }
        #else
            acc = f[i%15](acc + i);
        #endif
    }

    return 0;
}
Times w/o switch:
$for i in 1 2 3; do time ./a.out; done

real 0m11.114s
user 0m10.973s
sys 0m0.010s

real 0m10.968s
user 0m10.966s
sys 0m0.007s

real 0m10.904s
user 0m10.899s
sys 0m0.003s
and w/ switch
$for i in 1 2 3; do time ./a.out; done

real 0m12.378s
user 0m12.399s
sys 0m0.000s

real 0m12.410s
user 0m12.413s
sys 0m0.013s

real 0m12.417s
user 0m12.423s
sys 0m0.010s
A map to functions wins ~1 sec. That's not that much but if you are building a state machine with a lot of states it's better to use mapping rather than switch.

c++: friend classes in namespaces

You can declare friend class w/o declaration of it:

class A{friend class B;}
Here compiler doesn't have to know what is class B. But things go worth if you have class A defined in namespace N and class B in namespace M, or in other words A and B are in different namespaces. If you leave the things and you don't want to include header with declaration of class B, compiler will argue that class M::B doesn't have an access to private/protected members of N::A. You can't simply do
namespace N{ class A{friend class M::B;} };
Here compiler will raise an error that there is no B in namespace M, or even no such namespace 'M' if it hasn't achieved it during parsing. The solution here is to do a declaration of empty class B in namespace M:
namespace M{class B;}; namespace N{ class A{friend class M::B;} };
This will work and your compiler will be happy ;)

Wednesday, April 23, 2008

python: switch emulation

You know that python doesn't have switch statement. Guido says he doesn't want overload language python with statements to make it as much expressive as possible. But you can emulate 'switch' not only with 'if ... elif ... else' but with dictionary. Look:

{
    'one': lambda: 1,
    'two': lambda: 2
}.get('one', lambda: 0)()
You can create reusable 'switch' by creating dictionary that maps to callable objects and use it to call them by key. Also such 'switch' is mutable. This can be useful in some circumstances.

Monday, April 21, 2008

c/c++: arrays and pointers

Sometime programmers don't make a difference between pointers to memory and arrays. They pass easily array to function that wants pointer. It's dangerous if it changes the pointer target(reallocates memory for example):

void function(int *a)
{
        delete [] a;
        a = new int[3000];
}
This will cause Segmentation fault if you pass an array to the function. The reason is that you can't do some pointer routines with arrays. The other difference in the type of &array. For int array[1];: array, &array and &(array[0]) are the same. Almost. An array is just a sequence of variables. But there is a rule, that c++ looks arrays as if they were pointers. It means that if you write array, compiler takes it as &array[0]. The value of &array and array is the same (address of the first element). But their type is different. Here &array has type "pointer to the array of T". If you add one to &array, it will point to the address of the place right after the last element of the array(just like you skipped the array).

Wednesday, April 2, 2008

ext3: symlinks

Everybody uses symlinks in linux. Very interesting thing about the internals of symlinks I have recently discovered. Symlink may store path to original location in two ways. Symlink is represented as usual inode in ext3 filesystem. Its definition is in ext3_inode structure. The length of the string is given in i_size. If path to original location including terminating '\0' symbol is less than size of the i_block(EXT3_N_BLOCKS * 4 bytes = 60 bytes usually) array then the path is stored in the i_block. Otherwise i_blocks will be 1 and i_block[0] will point to a block containing the target name. When the string has to be contained in i_block[0], fs driver has to resolve the block and read its contents. This reduces performance a bit. You should be aware that lots of symlinks that point to the full path may get some extra cycles of your cpu. Solution: use relative paths for symlinks.

Friday, March 28, 2008

python: non-defined function arguments

You know that you can get named arguments of the routine that are not in function definition with **kw parameter:

def func(**kw):
     for k,v in kw.items(): print "%s: %s" % (k,v)
kw is a dict here where key is parameter name and value is parameter value. So if you call
func(a=1, b=2)
your kw will be
{'a': 1, 'b': 2}
>>> func(a=1, b=2)
a: 1
b: 2
The same is for the unnamed arguments:
def func(*a):
     for v in a: print v
a is a list of arguments here
func(1, 2)
will produce tuple a
(1, 2)
>>> func(1, 2)
(1, 2)
Nice I should say. Let's view the other side. You have function
def func(a=1, b=2):
     print a, b
and you have a dict
kw = {'a': 3, 'b': 4}
Now you just can use some py magic
func(**kw)
You will get a=3 and b=4:
func(**kw)
3 4
And for the unnamed arguments
def func(a, b):
     print a, b
If you define a list of 2 values
a = (1, 2)
and pass it to the func
func(*a)
you will get a=1 and b=2
func(*a)
1 2
Some extra py magic for these tricks:
def func(a=1, b=2): pass
func(**{'a': 3, 'b': 4})
def func(a, b): pass
func(*(1, 2))

Monday, March 17, 2008

c/c++: dlclose

What should you know about dlclose? You should remember that it actually doesn't close the library. It decrements the reference counter. When the counter reaches zero value and no other libraries use symbols in it, then the library is unloaded. The next example will work:

    void *handle1 = dlopen("./obj", RTLD_LAZY);
    void *handle2 = dlopen("./obj", RTLD_LAZY);

    print p1 = (print)dlsym(handle1, "print");
    p1();
    dlclose(handle1);
    
    p1();

Saturday, March 15, 2008

dlopen: performance

When you use dynamic library loading you probably open library each time you want to load routine. As for loading/unloading routines on demand you should open library every time to ensure that library is loaded and you can access routine you are interested. This will heavily reduce performance and memory usage. Probably you can control whether library was opened or not but this requires more code from you. In glibc from 2.2 had appeared 2 very useful flags to cover this situation: dlopen now may get RTLD_NOLOAD and RTLD_NODELETE flags. With RTLD_NOLOAD you can check if library was loaded and with RTLD_NODELETE you say dlclose not to unload library. I've made some tests. W/o RTLD_NOLOAD and RTLD_NODELETE flags:

        void *handle;
        int i; 
        for (i=0;i<1000000;++i)
        {
                handle = dlopen("/usr/lib/libdl.so", RTLD_LAZY);
                if (handle == NULL)
                        break;
                dlclose(handle);
        }
This gave me
for i in 1 2 3; do time ./test; done
real 0m0.567s
user 0m0.568s
sys 0m0.000s

real 0m0.566s
user 0m0.556s
sys 0m0.000s

real 0m0.562s
user 0m0.556s
sys 0m0.000s
Pretty slow, I should say. And w/ RTLD_NOLOAD and RTLD_NODELETE flags:
        void *handle;
        int i; 
        for (i=0;i<1000000;++i)
        {
                handle = dlopen("/usr/lib/libdl.so", RTLD_LAZY|RTLD_NOLOAD|RTLD_NODELETE);
                if (handle == NULL)
                        handle = dlopen("/usr/lib/libdl.so", RTLD_LAZY|RTLD_NODELETE);
                if (handle == NULL)
                        break;
                dlclose(handle);
        }
This one gave me
for i in 1 2 3; do time ./test; done
real 0m0.542s
user 0m0.536s
sys 0m0.000s

real 0m0.570s
user 0m0.572s
sys 0m0.000s

real 0m0.554s
user 0m0.528s
sys 0m0.004s
The same. libdl is pretty small. Let's try something bigger. Tests results for /lib/libc-2.7.so: w/o RTLD_NOLOAD and RTLD_NODELETE flags:
for i in 1 2 3; do time ./test; done
real 0m0.656s
user 0m0.656s
sys 0m0.000s

real 0m0.649s
user 0m0.644s
sys 0m0.000s

real 0m0.647s
user 0m0.644s
sys 0m0.000s
w/ RTLD_NOLOAD and RTLD_NODELETE flags:
real 0m0.611s
user 0m0.612s
sys 0m0.000s

real 0m0.610s
user 0m0.600s
sys 0m0.000s

real 0m0.608s
user 0m0.604s
sys 0m0.000s
We have won ~0.040s. Not bad. And another one for /usr/lib/libdb_cxx-4.5.so[note, I have changed circumstances: loop ran only 1000 times]: w/o RTLD_NOLOAD and RTLD_NODELETE flags:
for i in 1 2 3; do time ./test; done
real 0m1.270s
user 0m1.016s
sys 0m0.244s

real 0m1.290s
user 0m1.084s
sys 0m0.188s

real 0m1.269s
user 0m1.036s
sys 0m0.236s
w/ RTLD_NOLOAD and RTLD_NODELETE flags:
for i in 1 2 3; do time ./test; done
real 0m0.003s
user 0m0.004s
sys 0m0.000s

real 0m0.003s
user 0m0.004s
sys 0m0.000s

real 0m0.003s
user 0m0.000s
sys 0m0.000s
Yay! They differ for more than 1.2 seconds. That's because /usr/lib/libdb_cxx-4.5.so had to load some extra libraries.
  • ldd /usr/lib/libdl.so
     linux-gate.so.1 =>  (0xb7fa2000)
     libc.so.6 => /lib/libc.so.6 (0xb7e53000)
     /lib/ld-linux.so.2 (0xb7fa3000)
  • ldd /lib/libc-2.7.so
     /lib/ld-linux.so.2 (0xb7f7f000)
     linux-gate.so.1 =>  (0xb7f7e000)
  • ldd /usr/lib/libdb_cxx-4.5.so
     linux-gate.so.1 =>  (0xb7f3b000)
     libpthread.so.0 => /lib/libpthread.so.0 (0xb7dcb000)
     libstdc++.so.6 => /usr/lib/gcc/i686-pc-linux-gnu/4.2.3/libstdc++.so.6 (0xb7ce0000)
     libm.so.6 => /lib/libm.so.6 (0xb7cbb000)
     libc.so.6 => /lib/libc.so.6 (0xb7b86000)
     libgcc_s.so.1 => /usr/lib/gcc/i686-pc-linux-gnu/4.2.3/libgcc_s.so.1 (0xb7b79000)
     /lib/ld-linux.so.2 (0x80000000)
Now we can see the difference. If your library has references to external library dlopen loads them each time if you haven't specified RTLD_NOLOAD and RTLD_NODELETE flags. I had better use RTLD_NOLOAD and RTLD_NODELETE. It requires some extra code from you and one extra open handle for the program instance per library. But it will produce much faster code. Be aware ;)