为什么在我的测试scala 2.11比c++ qt 5.3快

Why in my test scala 2.11 faster than c++ qt 5.3?

本文关键字:qt c++ 我的 测试 scala 为什么      更新时间:2023-10-16

据我所知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 msec

Qt代码: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;
}