使用QJSEngine在Qt内部执行Javascript的速度

Speed of Javascript executed inside Qt with QJSEngine

本文关键字:Javascript 速度 执行 内部 QJSEngine Qt 使用      更新时间:2023-10-16

背景:我在一个需要以下内容的项目中工作:用户可以编写命令,用主程序的内部变量(用Qt/C++编写的GUI(执行一些数学运算。

我的方法是一个文本框,用户可以在其中用JavaScript编写命令/脚本,然后Qt评估代码。为此,我使用QJSEngine

问题:JavaScript的计算速度很慢。

例如,我们只有一个GUI,其中包含两个文本框(QTextEdit(和一个按钮。在一个文本框中,用户编写JavaScript代码,当按下按钮时,会对其进行评估,结果显示在另一个文本盒中。

作为糟糕性能的一个例子,当用户编写这些琐碎的JavaScript代码时,计算机会花大约3秒的时间来显示答案:

var X = [];
for (var i=0 ; i < 934600 ; ++i )
{
   X[i] = i;
}
X[120]

另一方面,如果在Qt/C++中执行相同的操作,则为"瞬时":

QVector<double> myVec;
for(int i=0; i < 934600; ++i)
{
  myVec.append(i);
}
qDebug() << myVec.value(120);

我知道JavaScript是一种解释语言,但这种性能正常吗?

这里有一个小的Qt示例程序(pr_Parser(来显示这个问题。我已经在Qt Creator 4.0.1中测试过了。Qt 5.7 MSVC2013 64位。

谢谢。

pr_parser.pro

QT       += core gui qml    
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets    
TARGET = pr_Parser
TEMPLATE = app    
CONFIG += c++11    
SOURCES += main.cpp
        CMainWindow.cpp    
HEADERS  += CMainWindow.h

main.cpp

#include "CMainWindow.h"
#include <QApplication>    
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   CMainWindow w;
   w.show();
   return a.exec();
}

C主窗口.h

#include <QMainWindow>
class QPlainTextEdit;    
class CMainWindow : public QMainWindow
{
   Q_OBJECT
public:
   CMainWindow(QWidget *parent = 0);
   ~CMainWindow();    
private:
   QPlainTextEdit *m_p_myScriptWindow;
   QPlainTextEdit *m_p_myResultWindow;    
private slots:
   void slot_ExecuteScript();
};

CMainWindow.cpp

#include "CMainWindow.h"
#include <QtWidgets>
#include <QJSEngine>
    CMainWindow::CMainWindow(QWidget *parent)
   : QMainWindow(parent)
{
   QWidget *window = new QWidget(this);
   setCentralWidget(window);
   QString sampleScript = "var X = [];";
   sampleScript.append("for (var i=0 ; i < 934600 ; ++i ){X[i]=i;}");
   sampleScript.append("X[120]");
   m_p_myScriptWindow = new QPlainTextEdit(sampleScript, this);
   m_p_myResultWindow = new QPlainTextEdit(this);
   QPushButton *myButton = new QPushButton("Execute", this);
   QVBoxLayout *myLayout = new QVBoxLayout(this);
   myLayout->addWidget(m_p_myScriptWindow);
   myLayout->addWidget(myButton);
   myLayout->addWidget(m_p_myResultWindow);
   window->setLayout(myLayout);
   connect(myButton, SIGNAL(clicked()), this, SLOT(slot_ExecuteScript()));
}
CMainWindow::~CMainWindow(){}
void CMainWindow::slot_ExecuteScript()
{
   QJSEngine myEngine;
   QString myScript = m_p_myScriptWindow->toPlainText();
   QJSValue myValue = myEngine.evaluate(myScript);
   if(myValue.isError())
   {
    m_p_myResultWindow->setPlainText(myValue.property("message").toString());
   }
   else
   {
      m_p_myResultWindow->setPlainText(myValue.toString());
   }
   // This code is "instanteneous"
   // QVector<double> myVec;
   // for(int i=0; i < 934600; ++i) {myVec.append(i);}
   // m_p_myResultWindow->setPlainText(QString::number(myVec.value(120)));
}

我找到了答案。

问题是我在调试模式下编译它。在释放模式下速度快10倍。

测量次数(使用QElapedTimer(执行多次:

JavaScript脚本:

  • 在调试模式下:2900-3000毫秒
  • 在释放模式下:255-300毫秒

与原生Qt/C++中的"for"相同:

  • 在调试模式下:26-29毫秒
  • 在释放模式下:7-6毫秒