io.vlingo.actors.Directory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vlingo-actors Show documentation
Show all versions of vlingo-actors Show documentation
Type safe Actor Model toolkit for reactive concurrency and resiliency using Java and other JVM languages.
// Copyright © 2012-2018 Vaughn Vernon. All rights reserved.
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL
// was not distributed with this file, You can obtain
// one at https://mozilla.org/MPL/2.0/.
package io.vlingo.actors;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
final class Directory {
private final Address none;
private final Map[] maps;
Directory(final Address none) {
this.none = none;
this.maps = build();
}
Actor actorOf(final Address address) {
return this.maps[mapIndex(address)].get(address);
}
int count() {
int count = 0;
for (final Map map : maps) {
count += map.size();
}
return count;
}
void dump(final Logger logger) {
if (logger.isEnabled()) {
for (final Map map : maps) {
for (final Actor actor : map.values()) {
final Address address = actor.address();
final Address parent = actor.lifeCycle.environment.parent == null ? none : actor.lifeCycle.environment.parent.address();
logger.log("DIR: DUMP: ACTOR: " + address + " PARENT: " + parent + " TYPE: " + actor.getClass());
}
}
}
}
boolean isRegistered(final Address address) {
return this.maps[mapIndex(address)].containsKey(address);
}
void register(final Address address, final Actor actor) {
if (isRegistered(address)) {
throw new IllegalArgumentException("The actor address is already registered: " + address);
}
this.maps[mapIndex(address)].put(address, actor);
}
Actor remove(final Address address) {
return this.maps[mapIndex(address)].remove(address);
}
@SuppressWarnings("unchecked")
private Map[] build() {
// This particular tuning is based on relatively few actors being spread
// across 32 buckets with only 32 pre-allocated elements, for a total of
// 1024 actors. This hard-coded configuration will have good performance
// up to around 75% of 1024 actors, but very average if not poor performance
// following that.
//
// TODO: Change to configuration-based values to enable the
// application to estimate how many actors are likely to exist at
// any one time. For example, there will be very few actors in some
// "applications" such as vlingo/cluster, but then the application
// running on the cluster itself may have many, many actors. These
// run on a different stage, and thus should be tuned separately.
// For example, preallocate 128 buckets that each have a Map of 16K
// elements in initial capacity (and probably no greater than that).
// This will support 2 million actors with an average of a few hundred
// less than 16K actors in each bucket.
final Map[] tempMaps = new ConcurrentHashMap[32];
for (int idx = 0; idx < tempMaps.length; ++idx) {
tempMaps[idx] = new ConcurrentHashMap<>(32, 0.75f, 16); // TODO: base this on scheduler/dispatcher
}
return tempMaps;
}
private int mapIndex(final Address address) {
return Math.abs(address.hashCode() % maps.length);
}
}