I am going to write a program that can let us to call function with string in C++. However, I wrote a program with same behavior in PHP, but PHP only took 4 seconds and finish executing, however, C++ took 27~28 seconds to finish. I wonder why PHP much faster than C++, and how to optimize the C++ code.
PS I am using Qt API, so the class name with prefix 'Q' such as QHash, QObject are classes from Qt.
Here are my code:
class header definition:
// function_dispatcher.h
#ifndef FUNCTIONDISPATCHER_H
#define FUNCTIONDISPATCHER_H
#include <QObject>
#include <QHash>
#include <functional>
class FunctionDispatcher : public QObject
{
Q_OBJECT
public:
FunctionDispatcher(QObject* parent = 0);
int functionDispatcher(QString functionName, int dataA, int dataB);
int function1(int a, int b);
int function2(int a, int b);
int function3(int a, int b);
int function4(int a, int b);
int function5(int a, int b);
int function6(int a, int b);
int function7(int a, int b);
int function8(int a, int b);
int function9(int a, int b);
int function10(int a, int b);
void functionTable();
private:
QHash<QString, std::function<int(int, int)>> m_functionsTable;
};
#endif // FUNCTIONDISPATCHER_H
class body definition:
#include "functiondispatcher.h"
#include <QDebug>
#include <functional>
#define ADD_FUNCTION(_functionName, _function) m_functionsTable.insert(_functionName, std::bind(_function, this, std::placeholders::_1, std::placeholders::_2));
FunctionDispatcher::FunctionDispatcher(QObject *parent)
: QObject(parent)
{
functionTable();
}
int FunctionDispatcher::functionDispatcher(QString functionName, int dataA, int dataB)
{
std::function<int(int, int)> func = m_functionsTable.value(functionName);
int result = 0;
try {
result = func(dataA, dataB);
}
catch(const std::bad_function_call& e) {
qDebug() << e.what();
}
return result;
}
int FunctionDispatcher::function1(int a, int b)
{
return a + b;
}
int FunctionDispatcher::function2(int a, int b)
{
return a * b;
}
int FunctionDispatcher::function3(int a, int b)
{
return a / b;
}
int FunctionDispatcher::function4(int a, int b)
{
return (a+12) * b;
}
int FunctionDispatcher::function5(int a, int b)
{
return (a+1) * b;
}
int FunctionDispatcher::function6(int a, int b)
{
return (a+2221) * b;
}
int FunctionDispatcher::function7(int a, int b)
{
return (a+31) * b;
}
int FunctionDispatcher::function8(int a, int b)
{
return (a+11) * b;
}
int FunctionDispatcher::function9(int a, int b)
{
return (a+141) * b;
}
int FunctionDispatcher::function10(int a, int b)
{
return (a+12) * b;
}
void FunctionDispatcher::functionTable()
{
ADD_FUNCTION("function1", &FunctionDispatcher::function1);
ADD_FUNCTION("function2", &FunctionDispatcher::function2);
ADD_FUNCTION("function3", &FunctionDispatcher::function3);
ADD_FUNCTION("function4", &FunctionDispatcher::function4);
ADD_FUNCTION("function5", &FunctionDispatcher::function5);
ADD_FUNCTION("function6", &FunctionDispatcher::function6);
ADD_FUNCTION("function7", &FunctionDispatcher::function7);
ADD_FUNCTION("function8", &FunctionDispatcher::function8);
ADD_FUNCTION("function9", &FunctionDispatcher::function9);
ADD_FUNCTION("function10", &FunctionDispatcher::function10);
}
and main function here:
#include <QCoreApplication>
#include "functiondispatcher.h"
#include <ctime>
#include <QDebug>
#include <iostream>
int main(int argc, char *argv[])
{
time_t t1 = time(NULL);
for (int i = 0; i < 10000000; i ++) {
FunctionDispatcher *f = new FunctionDispatcher();
f->functionDispatcher("function1", i, i + 1);
f->functionDispatcher("function2", i, i + 1);
f->functionDispatcher("function3", i, i + 1);
f->functionDispatcher("function4", i, i + 1);
f->functionDispatcher("function5", i, i + 1);
f->functionDispatcher("function6", i, i + 1);
f->functionDispatcher("function7", i, i + 1);
f->functionDispatcher("function8", i, i + 1);
f->functionDispatcher("function9", i, i + 1);
f->functionDispatcher("function10", i, i + 1);
delete f;
}
time_t t2 = time(NULL);
qDebug() << t2 - t1;
}
<?php
class Dispatcher
{
public function function1($a, $b)
{
return $a + $b;
}
public function function2($a, $b)
{
return $a * $b;
}
public function function3($a, $b)
{
return $a / $b;
}
public function function4($a, $b)
{
return ($a + 1) * ($b + 1);
}
public function function5($a, $b)
{
return $a / $b;
}
public function function6($a, $b)
{
return $a / $b;
}
public function function7($a, $b)
{
return $a / $b;
}
public function function8($a, $b)
{
return $a / $b;
}
public function function9($a, $b)
{
return $a / $b;
}
public function function10($a, $b)
{
return $a / $b;
}
}
$time1 = time();
for ($i = 0; $i <= 10000000; $i ++)
{
$function = new Dispatcher();
$function->{"function1"}($i, $i + 1);
$function->{"function2"}($i, $i + 1);
$function->{"function3"}($i, $i + 1);
$function->{"function4"}($i, $i + 1);
$function->{"function5"}($i, $i + 1);
$function->{"function6"}($i, $i + 1);
$function->{"function7"}($i, $i + 1);
$function->{"function8"}($i, $i + 1);
$function->{"function9"}($i, $i + 1);
$function->{"function10"}($i, $i + 1);
}
$time2 = time();
echo $time2 - $time1;
DO NOT use std::function
. Use function pointer instead.
std::function
is a wrapper of ANY Callable
target including functions, functor, lambda expression etc. It is so heavy and you don't need it in your situation .
Then make sure you turn on the -O2
(or even -O3
) option when compiling.
Probably you should use const references at some places.
int FunctionDispatcher::functionDispatcher(const QString& functionName, int dataA, int dataB)
{
const std::function<int(int, int)>& func = m_functionsTable.value(functionName);
int result = 0;
try {
result = func(dataA, dataB);
}
catch(const std::bad_function_call& e) {
qDebug() << e.what();
}
return result;
}
might perhaps already increase performance a lot. Call by value is usually much slower in C++ than to do it with references. Also, your local func variable doesn't need to be a copy.
My final solution is:
I split Dispatcher
from Controller and build functionsTable
only one time, and I use function pointer point to call function.
#include <iostream>
#include <ctime>
#include <map>
class Controller
{
public:
int function1(int a, int b) {return a + b;}
int function2(int a, int b) {return a + b;}
int function3(int a, int b) {return a * b;}
int function4(int a, int b) {return a + 50 + b/2;}
int function5(int a, int b) {return a + b;}
int function6(int a, int b) {return a / 2 + b;}
int function7(int a, int b) {return a + b * 19;}
int function8(int a, int b) {return a + b * 20;}
int function9(int a, int b) {return a + b + 100;}
int function10(int a, int b) {return a / b;}
};
typedef int (Controller::*function)(int a, int b);
class Dispatcher
{
public:
Dispatcher()
{
m_functionsTable.insert(std::pair<std::string, function>("function1", &Controller::function1));
m_functionsTable.insert(std::pair<std::string, function>("function2", &Controller::function2));
m_functionsTable.insert(std::pair<std::string, function>("function3", &Controller::function3));
m_functionsTable.insert(std::pair<std::string, function>("function4", &Controller::function4));
m_functionsTable.insert(std::pair<std::string, function>("function5", &Controller::function5));
m_functionsTable.insert(std::pair<std::string, function>("function6", &Controller::function6));
m_functionsTable.insert(std::pair<std::string, function>("function7", &Controller::function7));
m_functionsTable.insert(std::pair<std::string, function>("function8", &Controller::function8));
m_functionsTable.insert(std::pair<std::string, function>("function9", &Controller::function9));
m_functionsTable.insert(std::pair<std::string, function>("function10", &Controller::function10));
}
int FunctionDispatcher(std::string functionName, int a, int b) {
Controller c;
function f = m_functionsTable.find(functionName)->second;
return (c.*(function)f)(a, b);
}
private:
std::map<std::string, function> m_functionsTable;
};
int main()
{
time_t t1 = time(NULL);
Dispatcher d;
for (int i = 0; i < 10000000; i ++) {
d.FunctionDispatcher("function1", i, i + 1);
d.FunctionDispatcher("function2", i, i + 1);
d.FunctionDispatcher("function3", i, i + 1);
d.FunctionDispatcher("function4", i, i + 1);
d.FunctionDispatcher("function5", i, i + 1);
d.FunctionDispatcher("function6", i, i + 1);
d.FunctionDispatcher("function7", i, i + 1);
d.FunctionDispatcher("function8", i, i + 1);
d.FunctionDispatcher("function9", i, i + 1);
d.FunctionDispatcher("function10", i, i + 1);
}
time_t t2 = time(NULL);
std::cout << t2 - t1 << std::endl;
}
This solution took 3 seconds to run the program.
If I increase the loop from 10 million times to 100 million times, it only took 21 second, but PHP took 41 seconds.
My execution environment:
I upload the code to "ideone", and it shown that the program only took 5 seconds. link here: https://ideone.com/7DUXYG
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.