【问题标题】:Optimize QScriptEngine repeated action优化 QScriptEngine 重复动作
【发布时间】:2014-03-14 23:19:15
【问题描述】:

我正在尝试优化我的一个函数中的 QScriptEngine 操作。

该函数名为executeCustomJSOperation,它在多个文件中执行相同的JS代码。但是,每个文件都需要更改一个名为$xmlData 的全局变量。该函数基本上使用 $xmlData 变量将 XML 文件加载到内存中,然后始终应用相同的 javascript 代码 (jsString) 使用 javascript 编辑此 XML 文件。最后,$xmlData 变量再次使用编辑后的 ​​XML 更新。

我在处理每个 XML 文件的 for 循环上仅使用 OpenMP parallel for 获得了 2.5 的加速。但是现在我不知道如何进一步提高此功能的速度。

代码如下:

// allows user to echo js variables to check them in terminal using cout
QScriptValue echo(QScriptContext *context, QScriptEngine *engine)
{
    std::cout << context->argument(0).toString().toUtf8().constData() << std::endl; 
    return "";
}

void executeCustomJSOperation(const QString &jsString, const QStringList &filesToProcess){  
    QString rexmlString, jsxmlString;
    QFile rexmlfile(":/resources/libs/rexml.js"); // load javascript libraries as strings to memory
    QFile jsxmlfile(":/resources/libs/jsxml.js");

    rexmlfile.open(QFile::ReadOnly | QFile::Text);
    jsxmlfile.open(QFile::ReadOnly | QFile::Text);

    rexmlString=QTextStream(&rexmlfile).readAll();
    jsxmlString=QTextStream(&jsxmlfile).readAll();

    // Process all XmlFiles
#pragma omp parallel for // 2.5 speedup in my pc
    for(int i=0; i<filesToProcess.size(); i++){

        QString currXmlFileString;

        QScriptEngine engine;
        QScriptValue engineResult;

        // Add echo function so user can debug the code
        QScriptValue echoFunction = engine.newFunction(echo);
        engine.globalObject().setProperty("echo", echoFunction);

        engine.evaluate(rexmlString); // load js libraries in js engine
        engine.evaluate(jsxmlString);

        QFile currXmlFile(filesToProcess[i]);

        currXmlFileString=QTextStream(&currXmlFile).readAll();

        currXmlFile.close(); // close reading

        engine.globalObject().setProperty("$xmlData",currXmlFileString);

        engine.evaluate("main(); function main() {"+jsString+"}"); // main function allows to use return to exit prematurely from user code

        engineResult=engine.globalObject().property("$xmlData");

        QTextStream(&currXmlFile) << engineResult.toString(); // retreive the modified xml by javascript and save it to the file
    }
}

您认为可以进一步优化这段代码吗?如果您有任何疑问,请询问。

【问题讨论】:

    标签: javascript c++ qt optimization qtscript


    【解决方案1】:

    为什么要为每次迭代创建/初始化一个单独的 QScriptEngine?我建议将所有内容移至您的行

    engine.evaluate(jsxmlString);
    

    for()-loop之外。

    没错,这会使 WRT 线程化变得更加困难。本质上,您必须设置 n 个工作线程,并为每个线程(而不是每个文件)创建一个脚本引擎。对于初学者来说,一个简单的单线程版本应该可以让您初步了解预期的加速效果,以及是否值得这样做。

    当然,如果你的JS代码真的是单用的,只有QScriptProgram是你优化的唯一希望。同样,您将设置有限数量的工作线程,每个工作线程都有自己的 QScriptProgram(每次迭代一个 QScriptEngine,就像在您当前的代码中一样)。

    【讨论】:

    • 谢谢!我已经有一段时间没有用我随着时间所做的更改来更新问题了。我写的和你建议的完全一样,我只为每个线程创建一个QScriptEngine 并将冗余代码移出循环。我没有进行测量,但我知道更快。我已经尝试了QScriptProgram 提示,但我没有注意到性能有任何显着变化,我将 QScriptPrograms 分配在堆中的一个向量中,每个线程使用每个位置。我也尝试了新的QJSEngine,我相信它使用V8 JSengine,但我得到的结果要慢得多。 :|
    【解决方案2】:

    您可以构造一个QScriptProgram,将所有JS代码放入其中并使用QScriptEngine::evaluate对其进行评估。它可以加快执行速度,因为解析 JS 代码只会执行一次。但是,QScriptProgram 并未记录为可重入或线程安全的,因此即使每个线程都使用自己的 QScriptProgram 对象,您也无法确定它是否能在多个线程中正常工作。

    【讨论】:

    • 您好,感谢您的提示。我已经尝试过了,但我无法用它来提高(cpu)性能。同样正如你所说QScriptProgram 不是线程安全的,所以我不能只将它与线程一起使用,除非我为每个在创建后解析 js 的线程使用一个线程。我还尝试对所有线程使用相同的对象(包括 qengine 和 qscriptprogram),为此我尝试了一些同步方法,如 omp critical、qmutex 和 EnterCriticalSection,但它们会使程序减慢太多。迄今为止最快的实现仍然是我发布的那个,每个线程都有单独的引擎/变量。
    • 尝试从 JS 代码中创建一个QScriptProgram,然后创建多个副本(应该很便宜)并将它们分发到所有线程。
    • 不幸的是,该选项似乎也不适用于线程。使用该方法时出现分段错误。似乎构造函数QScriptProgram::QScriptProgram(const QScriptProgram &amp; other) 没有制作QScriptProgram 的深层副本。你可以查看实现的代码here。请注意,此代码包括完整代码,而不仅仅是我在此处发布的简化代码(例如包括错误检查)。
    猜你喜欢
    • 2016-09-28
    • 1970-01-01
    • 2012-05-26
    • 1970-01-01
    • 2021-07-20
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    • 2021-11-07
    相关资源
    最近更新 更多