Paavo Helde
12/8/2008 7:02:00 PM
sccr13plyr@gmail.com kirjutas:
> Hello,
>
> I do not know if this forum is the right place to post this message.
> If it is not, please let me know a better place to get my question
> addressed. I am an old C programmer that became a self-taught C++
> programmer. So, the following may simply be my ignorance of the C++
> language.
>
> I am at a site that has an older application written in C that has
> over time been migrated to C++. This is a high performance
> application that processes a 100 million records a day that are then
> broken down into component transactions. We have a set of algorithms
> that process these transactions and have a lot of duplicate logic.
> We want to add functionality, simplify the code, and keep the
> performance.
>
> I prototyped out the following:
>
> #include <stdio.h> // streams can be discussed another time... ;)
>
> class BaseAlgorithm
> {
> public: virtual ~BaseAlgorithm (){}
Virtual destructor might be needed if you allocate objects dynamically.
However, dynamic allocation is relatively slow, if you do this a lot, it
might affect performance.
>
> public: inline void Display (const int id, const char* output)
No need to repeat "public:" here. Also "inline" is implicit for in-class
defined member functions, no need to write it out here, and anyway
compilers decide by themselves nowadays what to inline.
> {
> (void) printf ("Algorithm: %d - %s\n", id, output);
(void) is not needed.
> }
> };
>
> template<int id, bool checkPrice, bool specificCode, bool currTran>
> class GenericAlgorithm : public BaseAlgorithm
> {
> private: static const int algorithmId_ = id;
> private: static const bool checkPriceChanged_ = checkPrice;
> private: static const bool specificCode_ = specificCode;
> private: static const bool currentTransOnly_ = currTran;
These static members are not needed, what's wrong with using template
parameters directly? Also, no need to repeat "private" before each
declaration.
>
> public: GenericAlgorithm (){}
Such a constructor is not needed, C++ makes the default ctor
automatically when needed.
> public: virtual ~GenericAlgorithm (){}
> public: inline void GenericLogic (int* data, int* env, char*
> retInfo)
"inline" superfluous again
> {
> if (data == NULL)
> if (env == NULL)
> if (retInfo == NULL)
> {
> //
> }
>
> if (checkPriceChanged_)
> {
> if (specificCode_)
> {
> if (currentTransOnly_)
> {
> char v1[1000][1000];
> v1[999][999] = 'd';
> if (v1[999][999] == 'd')
> {
> }
>
> Display (algorithmId_, "Check Price,
> Specific Code, Current Tran");
> }
> else
> {
> Display (algorithmId_, "Check Price,
> Specific Code, All Trans");
> }
> }
> else
> {
> if (currentTransOnly_)
> {
> Display (algorithmId_, "Check Price, All
> Code, Current Tran");
> }
> else
> {
> Display (algorithmId_, "Check Price, All
> Code, All Tran");
> }
> }
> }
> else
> {
> if (specificCode_)
> {
> if (currentTransOnly_)
> {
> Display (algorithmId_, "Ignore Price,
> Specific Code, Current Tran");
> }
> else
> {
> Display (algorithmId_, "Ignore Price,
> Specific Code, All Trans");
> }
> }
> else
> {
> if (currentTransOnly_)
> {
> Display (algorithmId_, "Ignore Price, All
> Code, Current Tran");
> }
> else
> {
> Display (algorithmId_, "Ignore Price, All
> Code, All Trans");
> }
> }
> }
> }
> };
>
> #include <stdlib.h>
>
> int main (void)
"void" not needed
> {
> GenericAlgorithm<159, true, true, true> test;
> test.GenericLogic (NULL, NULL, NULL);
>
> GenericAlgorithm<246, true, false, false> *oldTest = new
> GenericAlgorithm<246, true, false, false>;
> oldTest->GenericLogic (NULL, NULL, NULL);
Memory leak here, *oldTest is not released.
>
> return EXIT_SUCCESS;
nitpick: the above line is also not needed ;-)
> }
>
> This approach would collapse the three algorithms into one body of
> logic in GenericLogic. By using constants, my desire is to have the
> compiler create two separate versions of GenericLogic (one for each of
> the new class declarations in main), removing code (and comparisons)
> that would never need to be used.
Using constants certainly does not guarantee this, even if some compiler
happens to generate different code. In principle I think it should be
easier for the compiler to optimize out the branches if there were no
static variables, as the task would be simpler then.
>
> Should I expect that the compiler is actually removing unreachable
> code? Would this be compiler specific or I should be utilizing a
> different C++ language construct?
If the branch taking speed appears to be important, then you can apply
(maybe partial) template specialization. This can become quite verbose
though. Or maybe a policy-based design suits your needs better, look it
up.
> Also, the pointer declaration and
> initialization becomes a little bulky, something I can do there?
typedefs?
In general, though, if you are doing this not for education and just for
speeding the program up, then you should start from profiling your app
and finding out the bottlenecks. I would be quite surprised if branching
on a boolean parameter would show up in the results. Such branching might
affect something only in a very tight loop, and in this case the
branching should just be lifted out of the loop, no template trickery
needed.
hth
Paavo