使用 Saxon-JS 识别 XSLT 转换的性能瓶颈

Posted

技术标签:

【中文标题】使用 Saxon-JS 识别 XSLT 转换的性能瓶颈【英文标题】:Identify performance bottlenecks for XSLT transform using Saxon-JS 【发布时间】:2021-05-02 16:31:36 【问题描述】:

谁能提供一些关于查明转换瓶颈的指导?

这是 Saxon-JS 的 node.js 实现。我正在尝试提高转换某些 XML 文档的速度,以便我可以提供一个同步 API,理想情况下在 60 秒内响应(230 秒是应用程序网关的硬限制)。我还需要能够处理最大 50MB 大小的 XML 文件。

我已经运行了节点的内置分析器 (https://nodejs.org/en/docs/guides/simple-profiling/)。但考虑到免费版本的 Saxon-JS 的源代码并不是真正可读的,因此很难理解结果。

我的代码

const path = require('path');
const SaxonJS = require('saxon-js');
const  loadCodelistsInMem  = require('../standards_cache/codelists');
const  writeFile  = require('../config/fileSystem');
const config = require('../config/config');
const  getStartTime, getElapsedTime  = require('../config/appInsights');

// Used for easy debugging the xslt stylesheet
// Runs iati.xslt transform on the supplied XML
const runTransform = async (sourceFile) => 
    try 
        const fileName = path.basename(sourceFile);

        const codelists = await loadCodelistsInMem();

        // this pulls the right array of SaxonJS resources from the resources object
        const collectionFinder = (url) => 
            if (url.includes('codelist')) 
                // get the right filepath (remove file:// and after the ?
                const versionPath = url.split('schemata/')[1].split('?')[0];
                if (codelists[versionPath]) return codelists[versionPath];
            
            return [];
        ;

        const start = getStartTime();
        const result = await SaxonJS.transform(
            
                sourceFileName: sourceFile,
                stylesheetFileName: `$config.TMP_BASE_DIR/data-quality/rules/iati.sef.json`,
                destination: 'serialized',
                collectionFinder,
                logLevel: 10,
            ,
            'async'
        );
        console.log(`$getElapsedTime(start) (s)`);

        await writeFile(`performance_tests/output/$fileName`, result.principalResult);
     catch (e) 
        console.log(e);
    
;

runTransform('performance_tests/test_files/test8meg.xml');

控制台输出示例:

❯ node --prof utils/runTransform.js
SEF generated by Saxon-JS 2.0 at 2021-01-27T17:10:38.029Z with -target:JS -relocate:true
79.938 (s)
❯ node --prof-process isolate-0x102d7b000-19859-v8.log > v8_log.txt

文件:

stylesheet 示例 XML:是 test8meg.xml 节点分析日志v8_log.txt

最大性能违规者的 V8 日志片段:

 [Bottom up (heavy) profile]:
  Note: percentage shows a share of a particular caller in the total
  amount of its parent calls.
  Callers occupying less than 1.0% are not shown.

   ticks parent  name
  33729   52.5%  T __ZN2v88internal20Builtin_ConsoleClearEiPmPNS0_7IsolateE
   6901   20.5%    T __ZN2v88internal20Builtin_ConsoleClearEiPmPNS0_7IsolateE
   3500   50.7%      T __ZN2v88internal20Builtin_ConsoleClearEiPmPNS0_7IsolateE
   3197   91.3%        LazyCompile: *k /Users/nosvalds/Projects/validator-api/node_modules/saxon-js/SaxonJS2N.js:287:264
   3182   99.5%          LazyCompile: *<anonymous> /Users/nosvalds/Projects/validator-api/node_modules/saxon-js/SaxonJS2N.js:682:218
   2880   90.5%            LazyCompile: *d /Users/nosvalds/Projects/validator-api/node_modules/saxon-js/SaxonJS2N.js:734:184

非常感谢。没有大量的资源可以让我自己完成。我也试过了:

将 stylesheetInternal 参数与预解析的 JSON 结合使用(差别不大) 将文档拆分为单独的文档,其中仅包含一个活动 &lt;iati-activity&gt; 根元素内的子元素 &lt;iati-activities&gt; 根元素,分别转换每个文档,然后将其重新组合在一起,最终花费了 2 倍的时间。

最好的,

尼克

【问题讨论】:

【参考方案1】:

您在https://saxonica.plan.io/boards/5/topics/8105?r=8106 提出了同样的问题,我已经在那里回复了。我知道 *** 不喜欢仅提供链接的答案,但我更愿意通过我们自己的支持渠道为用户提供支持,而不是尽可能通过 ***。

【讨论】:

以上是关于使用 Saxon-JS 识别 XSLT 转换的性能瓶颈的主要内容,如果未能解决你的问题,请参考以下文章

如何将xsl文件转换为sef文件

Saxon JS 性能问题

如果 DOM classList 包含特定类,请检查 Saxon-JS 2.1

Saxon-js 是不是对 xsl:param 执行 XML 语法检查?

XSLT学习通过JavaScript转化xml

使用 Saxon-JS 及其全局 Javascript 函数命名空间在 XSL 中调用 jQuery-UI 组件?