Article Discussion
Backyard Hotrodding C++
Summary: Ever feel the need for speed? Real speed? If you're careful, you can get it without making a mess of things.
11 posts on 1 page.      
« Previous 1 Next »
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: September 15, 2006 2:35 PM by Walter
Bill
Posts: 1 / Nickname: bop / Registered: January 17, 2002 8:28 PM
Backyard Hotrodding C++
May 23, 2006 2:00 PM      
Ever feel the need for speed in C++? Real speed? If you're careful, you can get it without making a mess of things.

Read this The C++ Source article:

http://www.artima.com/cppsource/backyard.html

What do you think of the author's ideas?
Bruno
Posts: 2 / Nickname: br1 / Registered: November 7, 2003 2:50 PM
Re: Backyard Hotrodding C++
May 23, 2006 2:52 PM      
Nice article. I guess, it's true that sometimes you have to leave safety. :)

I have two comments:

About Vptr Jamming, I think you can avoid the problem of finding the vptr by introducing an object with just a vptr at the top of the hierarchy:

struct Empty {
virtual ~Empty() {}
};

struct Collection : Empty
{
virtual void foo() = 0;

void toSingle();
void toMulti();
};

struct SingleThreadedCollection : Collection
{
static SingleThreadedCollection tmp;

void foo()
{
std::cout << "st\n";
}
};

struct MultiThreadedCollection : Collection
{
static MultiThreadedCollection tmp;
void foo()
{
std::cout << "mt\n";
}
};

SingleThreadedCollection SingleThreadedCollection::tmp;
MultiThreadedCollection MultiThreadedCollection::tmp;

void Collection::toSingle()
{
Empty* st = &SingleThreadedCollection::tmp;
Empty* me = this;
memcpy(me, st, sizeof Empty);
}



My second comment is about RTTI Sniping. I realize dynamic_cast is slower, but what about typeid?

Bruno
Steve
Posts: 2 / Nickname: sbmassey / Registered: May 23, 2006 3:21 PM
Re: Backyard Hotrodding C++
May 23, 2006 7:32 PM      
The Counterfit this solution seems a bit unnecessary. What is the advantage of using reinterpret_cast's rather than just inheriting Implementation from Foo?
Walter
Posts: 5 / Nickname: walterb / Registered: July 22, 2004 8:48 AM
Re: Backyard Hotrodding C++
May 23, 2006 10:42 PM      
> The Counterfit this solution seems a bit unnecessary.
> What is the advantage of using reinterpret_cast's rather
> r than just inheriting Implementation from Foo?

The problem is that C++ makes it easy to create derived classes, but not so easy to insert a base class - especially if you (for many reasons) cannot change the implementation class.
E.
Posts: 2 / Nickname: en / Registered: February 17, 2003 9:36 PM
Re: Backyard Hotrodding C++
May 24, 2006 3:29 AM      
Hmmm... This is really nice to know... ;-D

"...He worked for Boeing for 3 years on the development of the 757 stabilizer trim system..."
Adi
Posts: 1 / Nickname: adish / Registered: April 20, 2005 11:01 AM
Re: Backyard Hotrodding C++
May 24, 2006 11:06 PM      
Interesting stuff!
I think that with some clever additional compile time constraints and assertions, some of these techniques might even be made usable in more "normal" contexts. no?
Achilleas
Posts: 98 / Nickname: achilleas / Registered: February 3, 2005 2:57 AM
Re: Backyard Hotrodding C++
May 25, 2006 2:04 AM      
Walter Bright is a bright fellow who wrote the D programming language. Although I like D, it is not widely adopted, and it seems to me it will never be. It seems the embedded/realtime world is satisfied with C++ while the business world is satisfied with Java.

Anyway here is another trick that one can do to hide the implementation details of a class. It requires a little bit more work, but it is more efficient than the one presented in the article.

Here is the interface of the class:


#ifndef FOO_HPP
#define FOO_HPP

class foo {
public:
//the default constructor
foo();

//the copy constructor
foo(const foo &f);

//the destructor
virtual ~foo();

//the assignment operator
foo &operator = (const foo &f);

//get content
int value() const;

//set content
void set_value(int v);

private:
unsigned char content[4];
};

#endif //FOO_HPP


Here is the implementation file foo.cpp:


#include "foo.hpp"
#include <stdexcept>
#include <iostream>

//macros for making the conversion easier
#define self ((_foo *)this)
#define rhs ((_foo *)&f)

//the implementation; it must have the same layout as the interface
struct _foo {
int value;
virtual ~_foo() {
}
};

//the default constructor
foo::foo() {
self->value = 0;
}

//the copy constructor
foo::foo(const foo &f) {
self->value = rhs->value;
}

//the destructor
foo::~foo() {
std::cout << self->value << std::endl;
}

//the assignment operator
foo &foo::operator = (const foo &f) {
self->value = rhs->value;
return *this;
}

//a method that returns data
int foo::value() const {
return self->value;
}

//a method that sets data
void foo::set_value(int v) {
self->value = v;
}

//a class that ensures size of interface == size of implementation
template <class A, class B> struct assert_size {
assert_size() {
if (sizeof(A) != sizeof(B)) throw std::logic_error("implementation size different from interface size");
}
};

//ensure size of interface == size of implementation
static assert_size<foo, _foo> assert_size_of_foo;


and here is usage of the class:


#include "foo.hpp"
#include <iostream>
using namespace std;

void test() {
foo f;
f.set_value(10);
cout << f.value() << endl;
f.set_value(20);
}

int main() {
test();
getchar();
return 0;
}


The result is:


10
20
Ion
Posts: 8 / Nickname: igaztanaga / Registered: January 3, 2006 9:57 PM
Re: Backyard Hotrodding C++
May 25, 2006 4:16 AM      
> class foo {
> //...
> private:
> unsigned char content[4];
> };
>
> #endif //FOO_HPP

This implementation hiding won't work for any type since you must align internal memory to meet the requirements of the implementation. if "content" is nota aligned to 4 bytes in some 32 systems this will crash.

Another option is to use something similar to boost::aligned_storage with the required alignment or use the most restringet alignment.
Achilleas
Posts: 98 / Nickname: achilleas / Registered: February 3, 2005 2:57 AM
Re: Backyard Hotrodding C++
May 25, 2006 6:38 AM      
> This implementation hiding won't work for any type since
> you must align internal memory to meet the requirements of
> the implementation.

As long as the implementation has the same size and vtable with the interface, there is no problem.

The class 'assert_size' ensures the interface and implementation have the same size.
Gregor
Posts: 6 / Nickname: gregor / Registered: August 3, 2005 4:18 AM
Re: Backyard Hotrodding C++
May 28, 2006 8:14 AM      
Pointer dehydration/hydration is much faster than traditional serialization - but you still have to dehydrate/hydrate all pointers - even if you didn't need them in one session. Therefore it could be called "lightweight serialization".

Even faster (at least in some scenarios) is "on-demand hydration/no dehydration".
I used this technique to implement an XML database.
Loading persisent data (a database page) involves no hydration at all. Whenever you want an item from the database page, you get a pointer (start of page + offset) that is created on demand. All data that is written to those items is relative to the start of page. Therefore you don't need any dehydration at all.

This technique is more complicated to implement, of course - and is only justified when performance has to pushed to its limits.
Walter
Posts: 12 / Nickname: wkaras / Registered: December 22, 2003 2:53 PM
Re: Backyard Hotrodding C++
September 15, 2006 2:35 PM      
Another approach to easy container persistence is to make the container templates generic enough so that array indexes can be used for links instead of pointers. For example:

http://www.geocities.com/wkaras/gen_cpp/avl_tree.html
11 posts on 1 page.
« Previous 1 Next »