Tuned concurrency

This commit is contained in:
nathan 2015-02-20 20:21:00 +01:00
parent d0584d52b0
commit 3315f079d5
2 changed files with 10 additions and 22 deletions

View File

@ -1,7 +1,6 @@
package net.engio.mbassy.multi.common;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
/**
* This implementation uses strong references to the elements.
@ -18,7 +17,8 @@ public class StrongConcurrentSet<T> extends AbstractConcurrentSet<T> {
}
public StrongConcurrentSet(int size, float loadFactor) {
super(new Reference2ReferenceOpenHashMap<T, ISetEntry<T>>(size, loadFactor));
super(new ConcurrentHashMap<T, ISetEntry<T>>(size, loadFactor, 1));
// super(new Reference2ReferenceOpenHashMap<T, ISetEntry<T>>(size, loadFactor));
}
@Override

View File

@ -10,7 +10,6 @@ import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import net.engio.mbassy.multi.common.IdentityObjectTree;
import net.engio.mbassy.multi.common.ReflectionUtils;
@ -31,8 +30,6 @@ import sun.reflect.generics.reflectiveObjects.NotImplementedException;
* Date: 2/2/15
*/
public class SubscriptionManager {
private static final int DEFAULT_SUPER_CLASS_TREE_SIZE = 4;
private final int MAP_STRIPING;
private float LOAD_FACTOR;
@ -58,36 +55,34 @@ public class SubscriptionManager {
// superClassSubscriptions keeps track of all subscriptions of super classes. SUB/UNSUB dumps it, so it is recreated dynamically.
// it's a hit on SUB/UNSUB, but REALLY improves performance on handlers
// it's faster to create a new one for SUB/UNSUB than it is to clear() on the original one
private volatile Map<Class<?>, FastEntrySet<Subscription>> superClassSubscriptions;
private Map<Class<?>, FastEntrySet<Subscription>> superClassSubscriptions;
// private final IdentityObjectTree<Class<?>, Collection<Subscription>> superClassSubscriptionsMulti = new IdentityObjectTree<Class<?>, Collection<Subscription>>();
// remember already processed classes that do not contain any message handlers
private final Map<Class<?>, Object> nonListeners;
// synchronize read/write access to the subscription maps
private final ReentrantReadWriteLock LOCK = new ReentrantReadWriteLock();
public SubscriptionManager(int numberOfThreads) {
this.MAP_STRIPING = numberOfThreads;
this.MAP_STRIPING = numberOfThreads/2;
this.LOAD_FACTOR = 0.8f;
this.subscriptionsPerMessageSingle = new ConcurrentHashMap<Class<?>, Collection<Subscription>>(4, this.LOAD_FACTOR, 1);
this.subscriptionsPerMessageSingle = new ConcurrentHashMap<Class<?>, Collection<Subscription>>(4, this.LOAD_FACTOR, this.MAP_STRIPING);
this.subscriptionsPerMessageMulti = new IdentityObjectTree<Class<?>, Collection<Subscription>>();
// only used during SUB/UNSUB
this.subscriptionsPerListener = new ConcurrentHashMap<Class<?>, Collection<Subscription>>(4, this.LOAD_FACTOR, this.MAP_STRIPING);
this.superClassesCache = new ConcurrentHashMap<Class<?>, FastEntrySet<Class<?>>>(8, this.LOAD_FACTOR, this.MAP_STRIPING);
// superClassSubscriptions keeps track of all subscriptions of super classes. SUB/UNSUB dumps it, so it is recreated dynamically.
// it's a hit on SUB/UNSUB, but improves performance on handlers
this.superClassSubscriptions = new ConcurrentHashMap<Class<?>, FastEntrySet<Subscription>>(8, this.LOAD_FACTOR, this.MAP_STRIPING);
this.nonListeners = new ConcurrentHashMap<Class<?>, Object>(4, this.LOAD_FACTOR, this.MAP_STRIPING);
}
private final void resetSuperClassSubs() {
// superClassSubscriptions keeps track of all subscriptions of super classes. SUB/UNSUB dumps it, so it is recreated dynamically.
// it's a hit on SUB/UNSUB, but improves performance on handlers
this.superClassSubscriptions = new ConcurrentHashMap<Class<?>, FastEntrySet<Subscription>>(8, this.LOAD_FACTOR, this.MAP_STRIPING);
this.superClassSubscriptions.clear();
}
public void unsubscribe(Object listener) {
@ -161,9 +156,6 @@ public class SubscriptionManager {
private final ThreadLocal<Collection<Subscription>> subInitialValue = new ThreadLocal<Collection<Subscription>>() {
@Override
protected java.util.Collection<Subscription> initialValue() {
// return new ArrayDeque<Subscription>(8);
// return Collections.newSetFromMap(new Reference2BooleanOpenHashMap<Subscription>(8, SubscriptionManager.this.LOAD_FACTOR));
// return Collections.newSetFromMap(new ConcurrentHashMap<Subscription, Boolean>(8, SubscriptionManager.this.LOAD_FACTOR, SubscriptionManager.this.MAP_STRIPING));
return new StrongConcurrentSet<Subscription>(8, SubscriptionManager.this.LOAD_FACTOR);
}
};
@ -547,10 +539,6 @@ public class SubscriptionManager {
if (!this.superClassesCache.containsKey(clazz)) {
// it doesn't matter if concurrent access stomps on values, since they are always the same.
Set<Class<?>> superTypes = ReflectionUtils.getSuperTypes(clazz);
// types = new ArrayDeque<Class<?>>(superTypes);
// types = new StrongConcurrentSet<Class<?>>(superTypes.size(), this.LOAD_FACTOR);
// types.addAll(superTypes);
Reference2BooleanArrayMap<Class<?>> map = new Reference2BooleanArrayMap<Class<?>>(superTypes.size() + 1);
for (Class<?> c : superTypes) {
map.put(c, Boolean.TRUE);