0

ツリー内のすべてのパスを 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 引数が -Xms2g -Xmx2g に設定されている)、適度に大きな入力で非常に遅くなることです。誰でもこれを改善する方法を見ることができますか?

4

3 に答える 3

1

プロファイラーを介してコードを実行します。それが、コードに関する実際の事実を取得する唯一の方法です。他のすべては単なる推測です。

于 2009-08-13T11:54:30.307 に答える
0

コードは RAM を指数関数的に消費します。したがって、レイヤーが 1 つ多いということはchildren.size()、RAM が 2 倍多いことを意味します。

結果を実体化する代わりに、ジェネレーターを使用してみてください。事前に結果を計算せずnext()、セットのイテレーターを呼び出したときにツリー構造を反復処理するマルチセットを実装します。

于 2009-08-13T12:49:11.833 に答える