为什么在我的测试scala 2.11比c++ qt 5.3快
Why in my test scala 2.11 faster than c++ qt 5.3?
据我所知c++有很好的性能。Scala没有。我写简单的任务。创建一个100mb的数组,在循环中初始化它,并将它写入磁盘,10次。
Qt (5.3 clang)代码:
QTime myTimer;
myTimer.start();
int size = 100*1024*1024;
for (int i = 0;i <= 10;i++)
{
char *mem = new char[size];
for(int j = 0;j <= size - 1;j++)
mem[j] = j % 250;
for(int j = size - 1;j >= 0;j--)
mem[j] = j % 251;
QFile file("/tmp/" + QString::number(i) + ".dat");
file.open(QIODevice::WriteOnly);
file.write(mem, size);
file.flush();
file.close();
qDebug() << i;
}
// do something..
int nMilliseconds = myTimer.elapsed();
qDebug() << nMilliseconds;
Scala(2.11)代码:
var ms = System.currentTimeMillis
val size = 100*1024*1024
for (i <- 0 to 10){
val mem = new Array[Byte](size)
for(j <- 0 to size - 1)
mem(j) = (j % 250).asInstanceOf[Byte]
for(j <- size - 1 to 0)
mem(j) = (j % 251).asInstanceOf[Byte]
val file = new File("/tmp/" + i.toString + ".dat")
using(new FileOutputStream(file)){
stream =>
stream.write(mem)
stream.flush
}
println(i)
}
ms = System.currentTimeMillis - ms
println(ms)
MacBook Pro i7 8Gb 256gb SSD
Scala代码:5127 msecQt代码:10408 msec
为什么scala比c++ qt快2倍?
正如我所怀疑的,您正在测量的东西并不存在,或者,更确切地说,不是您认为的东西您正在测量的东西。
要检查代码本身的开销是什么,您需要写入/dev/null
,并且需要对各个部分进行计时,以查看真正花费时间的部分。对于下面的代码,下面是我得到的输出:
initialization took 2666 ms
buffered QFile writes to /dev/null took 0 ms
unbuffered QFile writes to /dev/null took 0 ms
fwrites to /dev/null took 5 ms
buffered temporary QFile writes took 115 ms
unbuffered temporary QFile writes took 102 ms
fwrites to temporary file took 118 ms
这是一致的。在这个特定的平台上,使用C库的fwrite
实际上比使用QFile慢。我的临时存储很快,顺便说一句。
唉,这是在版本构建上。让我们看看它在调试构建中的样子:
initialization took 6524 ms
buffered QFile writes to /dev/null took 0 ms
unbuffered QFile writes to /dev/null took 0 ms
fwrites to /dev/null took 5 ms
buffered temporary QFile writes took 109 ms
unbuffered temporary QFile writes took 121 ms
fwrites to temporary file took 123 ms
这是你的减速。您测试了一个调试构建,它比您的硬件所能做的要慢2倍。JVM在初始化时在热路径上运行JIT。这就是为什么Scala中的初始化执行得与c++相当的原因,正如预期的那样。
这是OS X 10.9.4,苹果LLVM版本5.1 (clang-503.0.40)(基于LLVM 3.4svn),目标:x86_64-apple-darwin13.3.0,在3.7GHz第三代i7 CPU上使用Qt 5.3.1发布构建。
基准代码如下。由于QFile
是一个真正的c++类并正确地实现了RAII,因此执行显式的flush()
和close()
调用是没有意义的。c++的全部意义在于你不需要记住这些愚蠢的东西。
#include <QElapsedTimer>
#include <QTemporaryFile>
#include <QByteArray>
#include <QFile>
#include <QTextStream>
#include <cstdio>
QTextStream out(stdout);
template <typename F> void time(const char * task, F fun)
{
QElapsedTimer timer;
timer.start();
int const N = 10;
for (int i = 0; i < N; ++i) fun();
out << task << " took " << timer.elapsed() << " ms" << endl;
}
QByteArray newData() {
const int size = 100*1024*1024;
QByteArray buf(size, Qt::Uninitialized);
// CoW isn't free, using mem takes ~1/3 less time than using buf[x].
char * const mem = buf.data();
for (int j = 0; j <= size - 1; j++)
mem[j] = j % 250;
for (int j = size - 1;j >= 0; j--)
mem[j] = j % 251;
return buf;
}
void qFileWrite(const QByteArray & data, const char * name,
QIODevice::OpenMode modeExtras = 0)
{
QFile f(QString::fromLocal8Bit(name));
if (! f.open(QIODevice::WriteOnly | modeExtras)) abort();
if (f.write(data) != data.size()) abort();
}
void cWrite(const QByteArray & data, const char * name)
{
std::FILE * f = fopen(name, "wb");
if (!f) abort();
if (fwrite(data.data(), 1, data.size(), f) != data.size()) abort();
if (fclose(f) == EOF) abort();
}
QByteArray tempFileName() {
QTemporaryFile f; f.setAutoRemove(false); if (!f.open()) abort();
return f.fileName().toLocal8Bit();
}
int main()
{
time("initialization", newData);
QByteArray const data = newData();
time("buffered QFile writes to /dev/null", [&]{
qFileWrite(data, "/dev/null");
});
time("unbuffered QFile writes to /dev/null", [&]{
qFileWrite(data, "/dev/null", QIODevice::Unbuffered);
});
time("fwrites to /dev/null", [&]{
cWrite(data, "/dev/null");
});
time("buffered temporary QFile writes", [&]{
qFileWrite(data, tempFileName());
});
time("unbuffered temporary QFile writes", [&]{
qFileWrite(data, tempFileName(), QIODevice::Unbuffered);
});
time("fwrites to temporary file", [&]{
cWrite(data, tempFileName());
});
return 0;
}
相关文章:
- Qt VTK交互风格的信号到小部件
- QT在错误的班级中寻找空位
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 如何在Qt窗口小部件中使用QStringView(或QStringRef)
- 如何在Qt C++中更改光标
- 如何在MS Visual Studio 2019中运行QT UI
- QT通过C++添加映射QML项目
- libssh 的函数在构建 libssh 时无法在 Qt 和 cmake 错误中找到
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 使用Qt C++计算类似Git的SHA1哈希
- Qt focusObjectChanged example?
- 如何在cpp文件之间切换窗口?在Qt中
- Qt和C++:将QLineEdit添加到QTabWidget中
- 从数据库实时显示QT c++中的数据
- Qt Quick-如何仅从c++代码与qml属性交互
- 无法使用Qt Creator在Windows中构建yaml-cpp
- 如何在Qt中取消捕获字符串
- Qt SQLite没有查询或参数计数不匹配
- Qt SQlite无法创建表