我实施了一种管道方法。我将要遍历一棵树,我需要预先不可用的某些值...所以我必须并行(或之前)遍历树,并再次为我想要保存值的每个节点遍历(例如descendantCount) )。
因此我正在通过树进行交互,然后从构造函数中调用一个方法,该方法调用通过ExecutorService启动的新Thread。提交的Callable是:
@Override
public Void call() throws Exception {
// Get descendants for every node and save it to a list.
final ExecutorService executor =
Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
int index = 0;
final Map<Integer, Diff> diffs = mDiffDatabase.getMap();
final int depth = diffs.get(0).getDepth().getNewDepth();
try {
boolean first = true;
for (final AbsAxis axis = new DescendantAxis(mNewRtx, true); index < diffs.size()
&& ((diffs.get(index).getDiff() == EDiff.DELETED && depth < diffs.get(index).getDepth()
.getOldDepth()) || axis.hasNext());) {
if (axis.getTransaction().getNode().getKind() == ENodes.ROOT_KIND) {
axis.next();
} else {
if (index < diffs.size() && diffs.get(index).getDiff() != EDiff.DELETED) {
axis.next();
}
final Future<Integer> submittedDescendants =
executor.submit(new Descendants(mNewRtx.getRevisionNumber(), mOldRtx
.getRevisionNumber(), axis.getTransaction().getNode().getNodeKey(), mDb
.getSession(), index, diffs));
final Future<Modification> submittedModifications =
executor.submit(new Modifications(mNewRtx.getRevisionNumber(), mOldRtx
.getRevisionNumber(), axis.getTransaction().getNode().getNodeKey(), mDb
.getSession(), index, diffs));
if (first) {
first = false;
mMaxDescendantCount = submittedDescendants.get();
// submittedModifications.get();
}
mDescendantsQueue.put(submittedDescendants);
mModificationQueue.put(submittedModifications);
index++;
}
}
mNewRtx.close();
} catch (final AbsTTException e) {
LOGWRAPPER.error(e.getMessage(), e);
}
executor.shutdown();
return null;
}
因此,对于每个节点,它创建一个新的Callable,它遍历每个节点的树并计算后代和修改(我实际上将两个树修订一起融合)。好吧,mDescendantsQueue和mModificationQueue是BlockingQueues。起初我只有了descendantsQueue并再次遍历树以获得每个节点的修改(计算在当前节点的子树中进行的修改)。然后我想为什么不同时做两者并实现流水线方法。可悲的是,每当我实施另一个多线程“步骤”时,性能似乎都在下降。
也许是因为XML树通常不那么深,而且Concurrency-Overhead太重了: - /
起初我做了所有顺序,这是最快的: - 穿越树 - 为每个节点遍历后代并计算descendantCount和modificationCount
在使用BlockingQueues的流水线方法之后,性能似乎有所下降,但我实际上没有采取任何时间措施,我将不得不恢复许多更改以回溯:(可能性能随着CPU的增加而增加,因为我现在只有Core2Duo进行测试。
最好的问候,
约翰内斯
答案 0 :(得分:1)
这可能会有所帮助:Amadahl's law,它基本上说生产率的提高与必须通过同步处理的代码百分比成反比(成反比)。因此,即使通过增加更多的计算资源来增加,它也不会达到更好的结果。理想情况下,如果(同步部分与总部分)的比率较低,则(处理器+1的数量)应该提供最佳输出(除非您使用网络或其他I / O,在这种情况下您可以增加大小的游泳池)。 所以,只需从上面的链接中了解它,看看是否有帮助
答案 1 :(得分:0)
从你的描述中听起来你是递归地创建线程,每个线程处理一个节点然后产生一个新线程?它是否正确?如果是这样,我对您的性能下降感到惊讶。
简单的递归下降方法实际上可能是最好的方法。我无法看到多线程如何在这里获得任何优势。