@MiloXia
2015-05-07T10:51:42.000000Z
字数 1101
阅读 3382
akka
根据这篇文章[http://ifeve.com/dissecting-disruptor-whats-so-special/ ]和
[http://ifeve.com/disruptor-cacheline-padding/ ]以及
[http://ifeve.com/volatile/ ]
分析了一下Akka Actor默认实现的性能问题:
Akka的 Actor 的Mailbox使用的是ConcurrentLinkedQueue,是非阻塞的队列(无锁),多线程写入应该没问题,读取就不用说了,完全是单线程在读取队列元素,ConcurrentLinkedQueue为链表结构,但是通过CAS修改head和tail,所以不会发生因锁产生的缓存丢失问题,只是链表的缓存干扰而已,head和tail字段为volatile但没填充为64缓存行长度,可能发生伪共享问题, (可能性很小)
底层是forkjoinpool的工作线程,全局任务队列(工作线程共享)是有锁的数组,false sharing和缓存缺失问题都有可能发生,
workthread的taskQueue为无锁数组,且为双端队列,只有在work-stealing的时候会冲突(也为Unsafe的CAS操作),其它基本是单线程在读,queueBase和queueTop没有填充处理,可能会发生false sharing(可能性小,两字段得刚好在同一个内存行里啊)
注:伪共享问题对数组的影响比较大
注:把队列的tail和head填充为cache line大小 可增加出队和入队的速度
填充实现
/** head of the queue */
private transient final PaddedAtomicReference<QNode> head;
/** tail of the queue */
private transient final PaddedAtomicReference<QNode> tail;
static final class PaddedAtomicReference <T> extends AtomicReference <T> {
// enough padding for 64bytes with 4byte refs
Object p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pa, pb, pc, pd, pe;
PaddedAtomicReference(T r) {
super(r);
}
}
public class AtomicReference <V> implements java.io.Serializable {
private volatile V value;
//省略其他代码
}