【发布时间】:2014-02-20 12:43:25
【问题描述】:
我正在尝试实现一个框架,以便在 Unity 应用程序中使用多个内核。
到目前为止,我所拥有的是由 Julian M Bucknal 实现的non-blocking queue。它似乎对我的目的非常有效。我创建了一个任务类和一个结果类,并使用两个队列来分发和收集在辅助线程上处理的工作。
剩下的问题是,由于这段代码将在我的应用程序的性能关键部分中大量使用,我真的希望尽量减少垃圾收集器的使用。
是否有已知的库/模板/技术可以帮助我进行这项改进?
using System.Threading;
public class LockFreeQueue<T> {
internal struct SingleLinkNode<U> where U : T {
// Note; the Next member cannot be a property since
// it participates in many CAS operations
public SingleLinkNode<U> Next;
public U Item;
}
static private bool CAS<V>(ref V location, V comparand, V newValue) where V : class {
return
(object) comparand ==
(object) Interlocked.CompareExchange<V>(ref location, newValue, comparand);
}
SingleLinkNode<T> head;
SingleLinkNode<T> tail;
public LockFreeQueue() {
head = new SingleLinkNode<T>();
tail = head;
}
public void Enqueue(T item) {
SingleLinkNode<T> oldTail = null;
SingleLinkNode<T> oldTailNext;
SingleLinkNode<T> newNode = new SingleLinkNode<T>();
newNode.Item = item;
bool newNodeWasAdded = false;
while (!newNodeWasAdded) {
oldTail = tail;
oldTailNext = oldTail.Next;
if (tail == oldTail) {
if (oldTailNext == null)
newNodeWasAdded = CAS<SingleLinkNode<T>>(ref tail.Next, null, newNode);
else
CAS<SingleLinkNode<T>>(ref tail, oldTail, oldTailNext);
}
}
CAS<SingleLinkNode<T>>(ref tail, oldTail, newNode);
}
public bool Dequeue(out T item) {
item = default(T);
SingleLinkNode<T> oldHead = null;
bool haveAdvancedHead = false;
while (!haveAdvancedHead) {
oldHead = head;
SingleLinkNode<T> oldTail = tail;
SingleLinkNode<T> oldHeadNext = oldHead.Next;
if (oldHead == head) {
if (oldHead == oldTail) {
if (oldHeadNext == null) {
return false;
}
CAS<SingleLinkNode<T>>(ref tail, oldTail, oldHeadNext);
} else {
item = oldHeadNext.Item;
haveAdvancedHead = CAS<SingleLinkNode<T>>(ref head, oldHead, oldHeadNext);
}
}
}
return true;
}
public T Dequeue() {
T result;
Dequeue(out result);
return result;
}
}
【问题讨论】:
-
嗯,如果您正在寻找迁移到 .NET 4 的充分理由,那么您找到了。这个问题问得太晚了五年。
-
我猜 Unity 有十几个理由不这样做……但我希望他们能这样做。
-
嗯...如果我有一个非阻塞堆栈,它不会产生太多垃圾...我可以使用它通过对象池来解决问题(我认为)。跨度>
-
您是否真的尝试过使用它并确定它对内存的使用实际上会导致问题?在我看来,您似乎只是假设它会导致 GC 问题。似乎您应该尝试一下,然后如果您遇到性能问题,请分析您的代码并查看问题所在。我强烈怀疑这不会成为问题。
-
是的,在 Unity 中,有一个物理循环以每秒约 50 次迭代的速度运行……我尝试在每次迭代中添加 1000 个任务并获得了性能提升……但是垃圾收集器被触发了每 1-2 秒一次。 Unity 中的垃圾收集器有时会导致帧率小幅下降……尤其是在不支持 mono 的平台上,该问题的代码是自动编译的。
标签: c# multithreading concurrency queue