我正在编写一个函数,它在树中生成所有路径作为xpath语句并将它们存储在下面的包中是一个天真的(对不起,这很长),下面是我尝试优化它:
/**
* Create the structural fingerprint of a tree. Defined as the multiset of
* all paths and their multiplicities
*/
protected Multiset<String> createSF(AbstractTree<String> t,
List<AbstractTree<String>> allSiblings) {
/*
* difference between unordered and ordered trees is that the
* next-sibling axis must also be used
*
* this means that each node's children are liable to be generated more
* than once and so are memo-ised and reused
*/
Multiset<String> res = new Multiset<String>();
// so, we return a set containing:
// 1. the node name itself, prepended by root symbol
res.add("/" + t.getNodeName());
List<AbstractTree<String>> children = t.getChildren();
// all of the childrens' sets prepended by this one
if (children != null) {
for (AbstractTree<String> child : children) {
Multiset<String> sub = createSF(child, children);
for (String nextOne : sub) {
if (nextOne.indexOf("//") == 0) {
res.add(nextOne);
} else {
res.add("/" + nextOne);
res.add("/" + t.getNodeName() + nextOne);
}
}
}
}
// 2. all of the following siblings' sets, prepended by this one
if (allSiblings != null) {
// node is neither original root nor leaf
// first, find current node
int currentNodePos = 0;
int ptrPos = 0;
for (AbstractTree<String> node : allSiblings) {
if (node == t) {
currentNodePos = ptrPos;
}
ptrPos++;
}
// 3. then add all paths deriving from (all) following siblings
for (int i = currentNodePos + 1; i < allSiblings.size(); i++) {
AbstractTree<String> sibling = allSiblings.get(i);
Multiset<String> sub = createSF(sibling, allSiblings);
for (String nextOne : sub) {
if (nextOne.indexOf("//") == 0) {
res.add(nextOne);
} else {
res.add("/" + nextOne);
res.add("/" + t.getNodeName() + nextOne);
}
}
}
}
return res;
}
现在是(当前)在子类中的优化:
private Map<AbstractTree<String>, Multiset<String>> lookupTable = new HashMap<AbstractTree<String>, Multiset<String>>();
public Multiset<String> createSF(AbstractTree<String> t,
List<AbstractTree<String>> allSiblings) {
Multiset<String> lookup = lookupTable.get(t);
if (lookup != null) {
return lookup;
} else {
Multiset<String> res = super.createSF(t, allSiblings);
lookupTable.put(t, res);
return res;
}
}
我的麻烦是优化版本耗尽了堆空间(vm args设置为-Xms2g -Xmx2g),并且在适度大的输入上非常慢。任何人都可以看到改进的方法吗?
答案 0 :(得分:1)
通过分析器运行代码。这是获取代码真实事实的唯一方法。其他一切都只是猜测。
答案 1 :(得分:1)
“将树中的所有路径生成为xpath语句”
您创建了多少条路径?这可能是非平凡的。路径的数量应该是 O ( n log n ),但算法可能会更糟糕,具体取决于它们用于儿童的表示父母。
您应该简单地列出路径的简单枚举,而不必担心行李存储。
答案 2 :(得分:0)
您的代码以指数方式占用RAM。因此,一层更多意味着children.size()
倍的RAM。
尝试使用生成器而不是实现结果:实现一个Multiset,它不会事先计算结果,但在set的迭代器上调用next()
时会遍历树结构。