- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在阅读 Qt 的信号与槽 [1] 时注意到它声称信号和槽的开销比任何新操作或删除操作都要低得多。所以我做了一个测试:
#include <cmath>
#include <QtCore/QAtomicInt>
#include <QtCore/QCoreApplication>
#include <QtCore/QElapsedTimer>
#include <QtCore/QMetaObject>
#include <QtCore/QMetaMethod>
#include <QtCore/QObject>
#include <QtCore/QRunnable>
#include <QtCore/QTextStream>
#include <QtCore/QThread>
#include <QtCore/QThreadPool>
#include <QtCore/QTimer>
#include <QtCore/QVector>
using std::pow;
constexpr int const maxThreadCount(16);
constexpr int const maxIteration(100000);
constexpr int const maxPiDigit(1000);
void calcPi()
{
double sum(0);
for (int k(0); k < maxPiDigit; ++k) {
double a(4.0 / (k * 8 + 1));
double b(2.0 / (k * 8 + 4));
double c(1.0 / (k * 8 + 5));
double d(1.0 / (k * 8 + 6));
sum += pow(16, -k) * (a - b - c -d);
}
QTextStream out(stdout);
out << sum << endl;
}
class CalcPiWithQObject : public QObject
{
Q_OBJECT
public:
CalcPiWithQObject(QObject *parent = NULL);
public slots:
void start();
signals:
void finished();
}; // CalcPiWithQObject
CalcPiWithQObject::CalcPiWithQObject(QObject *parent):
QObject(parent)
{}
void CalcPiWithQObject::start()
{
calcPi();
finished();
}
class CalcPiWithQRunnable : public QRunnable
{
private:
static QAtomicInt count_;
public:
CalcPiWithQRunnable(QThreadPool *parent);
void run() override;
private:
QThreadPool *parent_;
}; // CalcPiWithQRunnable
QAtomicInt CalcPiWithQRunnable::count_(maxThreadCount);
CalcPiWithQRunnable::CalcPiWithQRunnable(QThreadPool *parent):
QRunnable(),
parent_(parent)
{
setAutoDelete(false);
}
void CalcPiWithQRunnable::run()
{
calcPi();
if (count_.fetchAndAddOrdered(1) < maxIteration) {
parent_->start(new CalcPiWithQRunnable(parent_));
}
delete this;
}
class PiTest : public QObject
{
Q_OBJECT
public:
PiTest(QObject *parent = NULL);
public slots:
void start();
void nextQObjectCall();
private:
QVector<QThread *> threads_;
QVector<CalcPiWithQObject *> calc_;
QThreadPool *threadPool_;
QElapsedTimer timer_;
int threadCount_;
int jobCount_;
}; // PiTest
PiTest::PiTest(QObject *parent):
QObject(parent),
threads_(maxThreadCount),
calc_(maxThreadCount),
threadPool_(new QThreadPool(this)),
threadCount_(maxThreadCount),
jobCount_(maxThreadCount)
{
threadPool_->setMaxThreadCount(maxThreadCount);
for (int i(0); i < maxThreadCount; ++i) {
threads_[i] = new QThread();
calc_[i] = new CalcPiWithQObject();
calc_[i]->moveToThread(threads_[i]);
QObject::connect(calc_[i], &CalcPiWithQObject::finished,
this, &PiTest::nextQObjectCall,
Qt::QueuedConnection);
QObject::connect(threads_[i], &QThread::started,
calc_[i], &CalcPiWithQObject::start,
Qt::QueuedConnection);
}
}
void PiTest::start()
{
timer_.start();
for (int i(0); i < maxThreadCount; ++i) {
threadPool_->start(new CalcPiWithQRunnable(threadPool_));
}
threadPool_->waitForDone();
int timePassed(timer_.elapsed());
QTextStream out(stdout);
out << "QThreadPool: " << timePassed << endl;
timer_.restart();
for (int i(0); i < maxThreadCount; ++i) {
threads_[i]->start();
}
}
static QMetaMethod nextCall(PiTest::staticMetaObject.method(PiTest::staticMetaObject.indexOfMethod("start")));
void PiTest::nextQObjectCall()
{
jobCount_++;
if (jobCount_ < maxIteration) {
nextCall.invoke(sender(), Qt::QueuedConnection);
QMetaObject::invokeMethod(sender(), "start",
Qt::QueuedConnection);
return;
}
threadCount_--;
if (threadCount_ == 0) {
for (int i(0); i < maxThreadCount; ++i) {
threads_[i]->quit();
}
int timePassed(timer_.elapsed());
QTextStream out(stdout);
out << "QThread: " << timePassed << endl;
qApp->quit();
}
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
PiTest *bench(new PiTest(qApp));
QTimer::singleShot(0, bench, SLOT(start()));
return qApp->exec();
}
#include "main_moc.cpp"
我在闲置的 20 核计算机上运行了测试:
/usr/lib64/qt5/bin/moc -o main_moc.cpp main.cpp
clang++ -std=c++11 -fPIE -O2 -march=native -I/usr/include/qt5/ -L/usr/lib64/qt5 -lQt5Core -o bench main.cpp
./bench > test.out
grep QThread test.out
结果如下:
QThreadPool: 4803
QThread: 9285
我尝试了不同的参数,使用更长的圆周率计算和更少的作业,反之亦然,但结果大致相同。 QThread+signal/slots 总是落后。对于更大数量的作业,QThreadPool+new/delete 可以轻松胜过 QThread 高达 10 倍。
我对我的基准代码感到有些尴尬。我在这里误解了什么吗?如果信号/槽比新建/删除快,我的基准测试有什么问题?
谢谢。
最佳答案
信号性能因连接类型而异。当你创建线程间连接时,连接是排队的,并使用事件循环来调度自己,而Qt中的事件循环不仅相当慢,而且上次我检查它没有提供任何方法来增加它的更新速度。
这使得跨线程的信号非常慢,我遇到过细粒度并发的情况,多线程导致性能下降而不是性能提升。
只是为了让您了解直接连接和排队连接之间的区别:
#define COUNT 5000
class Ping : public QObject {
Q_OBJECT
Q_SIGNAL void pong(uint);
public slots: void ping(uint c) { if (c < COUNT) emit pong(++c); else qDebug() << t.nsecsElapsed(); }
};
//...
QObject::connect(&p1, SIGNAL(pong(uint)), &p2, SLOT(ping(uint)), Qt::DirectConnection);
QObject::connect(&p2, SIGNAL(pong(uint)), &p1, SLOT(ping(uint)), Qt::DirectConnection);
//...
p1.ping(0);
结果:
Direct connection (in same thread) - 570504 nsec
Queued connection (in same thread) - 29670333 nsec
Queued connection (different threads) - 53343054 nsec
如您所见,线程间连接几乎比直接连接慢 100 倍。而且我怀疑您链接到的文档是指直接连接。
总而言之,我认为您的测试一团糟。你真的应该精简它,让它变得简单,并专注于你提出的问题。
最后,直接连接可能比新建/删除更快,但排队连接肯定不是,它们要慢得多,这绝对是不同性能背后的关键因素。您链接到的文档中的声明与 QThread + worker
vs QRunnable + thread pool
性能绝对无关。最后,在两种情况下,您使用两种动态内存分配/取消分配和排队连接。
关于c++ - 为什么我的信号槽比 QThreadPool+new+delete 慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29357255/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!