提高JS重复数据删除功能的性能

时间:2015-08-30 09:53:19

标签: javascript performance

功能问题来自postcss-discard-duplicates插件。以下是index.js中的代码:

'use strict';

var postcss = require('postcss');

function dedupe (node) {
    if (node.nodes) { node.each(dedupe); }

    if (node.type === 'comment') { return; }

    var nodes = node.parent.nodes.filter(function (n) {
        return String(n) === String(node);
    });

    nodes.forEach(function (n, i) {
        if (i !== nodes.length - 1) {
            n.removeSelf();
        }
    });
}

module.exports = postcss.plugin('postcss-discard-duplicates', function () {
    return function (css) {
        css.each(dedupe);
    };
});

插件使用PostCSS API返回CSS节点树。完整的API已有详细记录here

目前我在Twitter Bootstrap上构建了大量的CSS文件,其中包含许多复杂的选择器。 CSS需要约37秒。编译,如果使用此函数来查找和删除任何重复的规则。没有它,它是〜3秒。

我正在寻求帮助优化此功能以获得更好的性能。

更新:我发布了复制功能作者所做改进的答案。它将编译时间缩短了50%以上。

2 个答案:

答案 0 :(得分:0)

我不确定在这个函数中直接找到优化很容易,看起来像是通过构建二叉树等帮助结构进行职业优化的任务。这不是问题,算法中的问题,而不是实现中的问题。 如果您只想优化代码 - 尝试合并 monster.update(delta); filter。至少,它有助于避免重复迭代。

forEach

答案 1 :(得分:0)

reported this issue回购所有者,他做了一些重大的性能改进。我的编译时间现在是~13.5秒。 (通过添加问题评论中提到的微优化,我也设法削减了第二个补贴)

这是改进的代码:

'use strict';

var postcss = require('postcss');

function dedupe (node, index) {
    if (node.type === 'comment') { return; }
    if (node.nodes) { node.each(dedupe); }

    var toString = node.toString();
    var nodes = node.parent.nodes;
    var result = [node];
    var i = index + 1;
    var max = nodes.length;

    for (; i < max; i++) {
        if (nodes[i].toString() === toString) {
            result.push(nodes[i]);
        }
    }

    for (var x = 0; x < result.length; x++) {
        if (x !== result.length - 1) {
            result[x].remove();
        }
    }

}

module.exports = postcss.plugin('postcss-discard-duplicates', function () {
    return function (css) {
        css.each(dedupe);
    };
});