如何在JavaScript中实现尽可能快的自底向上树转换器?我应该自己管理内存吗?

如何在JavaScript中实现尽可能快的自底向上树转换器?我应该自己管理内存吗?,javascript,performance,algorithm,tree,asm.js,Javascript,Performance,Algorithm,Tree,Asm.js,我正在用JavaScript实现一个自底向上的树转换器。它将用于超级组合减缩器的解释器,因此该算法必须尽可能快,因为它会影响在其上构建的每个程序。这是我当前的实现: function transform(tree,fn){ var root = tree, node = tree, child, parent, is_node, dir; root.dir = 0; while(true) {

我正在用JavaScript实现一个自底向上的树转换器。它将用于超级组合减缩器的解释器,因此该算法必须尽可能快,因为它会影响在其上构建的每个程序。这是我当前的实现:

function transform(tree,fn){
    var root = tree,
        node = tree,
        child,
        parent,
        is_node,
        dir;
    root.dir = 0;
    while(true) {
        is_node = typeof(node)==="object";
        dir = is_node ? node.dir : 2;
        if (dir < 2)
            child = node[dir],
            node.dir++,
            child.parent = parent = node,
            child.dir = 0,
            node = child;
        else if ((changed = fn(node))!==undefined)
            changed.parent = parent,
            changed.dir = 0,
            node = changed;
        else
            if (!parent)
                return node;
            else
                parent[parent.dir-1] = node,
                node = parent,
                parent = node.parent;
    };
};

// TEST
var tree = [[1,2],[[3,4],[5,6]]];
console.log(
    JSON.stringify(transform(tree,function(a){
        if (a[0]===1) return [3,[5,5]];
        if (a[0]===5) return 77;
    })) === "[[3,77],[[3,4],77]]");
函数变换(树,fn){
var root=tree,
节点=树,
小孩
父母亲
是_节点,
迪尔;
root.dir=0;
while(true){
is_node=typeof(node)==“object”;
dir=is_node?node.dir:2;
if(dir<2)
子节点=节点[dir],
node.dir++,
child.parent=parent=node,
child.dir=0,
节点=子节点;
如果((已更改=fn(节点))!==未定义),则为else
已更改。父项=父项,
changed.dir=0,
节点=已更改;
其他的
如果(!父项)
返回节点;
其他的
父[parent.dir-1]=节点,
节点=父节点,
parent=node.parent;
};
};
//试验
var-tree=[[1,2],[3,4],[5,6]];
console.log(
stringify(转换(树,函数)(a){
如果(a[0]==1)返回[3[5,5];
如果(a[0]==5)返回77;
})) === "[[3,77],[[3,4],77]]");

这显然远远不是最优的。如何使变压器尽可能快?也许我不需要寻找更快的算法,我可以自己管理内存,使用
asm.js

你有几个选择,从最简单但最慢到最快但最棘手

使用常规JavaScript 这就是你现在正在做的。看看你的算法,我看不出有什么比速度的微小提高更能说明问题的了

使用asm.js 使用asm.js可能是您的一个选择。这将提高速度。您不会详细介绍这个系统将在何处使用,但是如果它能工作,实现这样的东西应该不会太困难。您可能会看到性能的提高,但这取决于您计划如何使用它,它可能没有您希望的那么大(对于这种情况,您可能会看到速度提高50%-500%,具体取决于代码的效率)

用一种不同的、编译过的、类型化的语言构建它。 如果速度真的很高,这取决于您的用例,那么最好用另一种编译语言编写这个程序(或者至少是这个函数)。然后,您可以在服务器上运行这个编译后的脚本,并通过web服务与之通信

如果您需要在短时间内转换树的次数非常多,那么由于发送和接收数据所需的时间,因此不会有太大的提升。然而,如果您只是执行相对较少但长期运行的树转换,那么您可以看到性能方面的巨大好处。编译的类型化语言(C++、Java等)总是比解释的无类型语言(如JavaScript)具有更好的性能


在服务器上运行它的另一个好处是,您通常可以向它投入更多的马力,因为您可以将它编写为多线程,甚至可以在一个计算机集群上运行,而不是仅在一个计算机集群上运行(对于高端构建)。使用JavaScript时,您通常只能使用一个线程,最终用户的计算机也只能使用一个线程。

很有趣!这个想法是移植一个完整的框架在浏览器中运行,所以我真的支持asm.js的建议。问题是我不知道该怎么做。我的方法是实现我自己的内存管理系统和垃圾收集,我搞砸的机会很大。那你会怎么做?记住,这个系统不过是一个大的二叉树,所以这可能有助于更好地组织内存?我不知道你是否真的能从自己的内存管理和GC中获得很大的好处。js的最大好处是它接近类型化和编译语言。您在上面添加的内容越多,就越有可能影响性能。如果您有短期运行的转换,两者都没有帮助。如果运行时间更长,稍微清理一下可能会有所帮助。您还可以使它看起来更快,但要使它异步。如果您坚持使用JavaScript,您应该尝试一个基本的asm.js版本,然后在一个新问题中发布该代码,以获得对该代码的实际反馈。好的,只是一个问题。TBH我真的不知道如何正确地编写asm.js。也许用C编写代码并编译成asm.js是一个更好的主意?老实说,如果我要写这篇文章,我可能也会用其他东西来写。asm.js无论如何都不是最终版本,因此要找到它的文档有点困难。使用像C这样的东西可能会让你省去一些麻烦你是说C->Asm还是只是C?例如,使用服务器来完成工作?这里的问题是,在性能至关重要的地方使用代码:每当有人在结构树编辑器中编辑节点时,就会调用该代码,因此在刷新屏幕之前等待服务器应答会大大恶化体验(