ARTEMIS-4814 Make direct binding lookup time constant
Currently, with 500K+ queues, the cleanup step of TempQueueCleanerUpper requires invoking WildcardAddressManager#getDirectBindings, which is O(k) in the number of queues. From method profiling, this can consume up to 95% of our CPU time when needing to clean up many of these. Add a new map to keep track of the direct bindings, and add a test assertion that fails if we don't properly remove it.
This commit is contained in:
parent
ee9d016f6c
commit
166adf4bfb
|
@ -68,6 +68,8 @@ public class SimpleAddressManager implements AddressManager {
|
|||
|
||||
private final ConcurrentMap<SimpleString, Pair<Binding, Address>> nameMap = new ConcurrentHashMap<>();
|
||||
|
||||
private final ConcurrentMap<SimpleString, Collection<Binding>> directBindingMap = new ConcurrentHashMap<>();
|
||||
|
||||
private final BindingsFactory bindingsFactory;
|
||||
|
||||
protected final MetricsManager metricsManager;
|
||||
|
@ -100,6 +102,11 @@ public class SimpleAddressManager implements AddressManager {
|
|||
if (nameMap.putIfAbsent(binding.getUniqueName(), bindingAddressPair) != null) {
|
||||
throw ActiveMQMessageBundle.BUNDLE.bindingAlreadyExists(binding);
|
||||
}
|
||||
directBindingMap.compute(binding.getAddress(), (key, value) -> {
|
||||
Collection<Binding> bindingList = value == null ? new ArrayList<>() : value;
|
||||
bindingList.add(binding);
|
||||
return bindingList;
|
||||
});
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Adding binding {} with address = {}", binding, binding.getUniqueName(), new Exception("trace"));
|
||||
|
@ -116,7 +123,18 @@ public class SimpleAddressManager implements AddressManager {
|
|||
return null;
|
||||
}
|
||||
|
||||
removeBindingInternal(binding.getA().getAddress(), uniqueName);
|
||||
SimpleString address = binding.getA().getAddress();
|
||||
removeBindingInternal(address, uniqueName);
|
||||
directBindingMap.compute(address, (key, value) -> {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
value.remove(binding.getA());
|
||||
if (value.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
});
|
||||
|
||||
return binding.getA();
|
||||
}
|
||||
|
@ -160,15 +178,7 @@ public class SimpleAddressManager implements AddressManager {
|
|||
@Override
|
||||
public Collection<Binding> getDirectBindings(final SimpleString address) throws Exception {
|
||||
SimpleString realAddress = CompositeAddress.extractAddressName(address);
|
||||
Collection<Binding> bindings = new ArrayList<>();
|
||||
|
||||
nameMap.forEach((bindingUniqueName, bindingAddressPair) -> {
|
||||
if (bindingAddressPair.getA().getAddress().equals(realAddress)) {
|
||||
bindings.add(bindingAddressPair.getA());
|
||||
}
|
||||
});
|
||||
|
||||
return bindings;
|
||||
return new ArrayList<>(directBindingMap.getOrDefault(realAddress, Collections.emptyList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -202,6 +202,7 @@ public class WildcardAddressManagerUnitTest extends ActiveMQTestBase {
|
|||
|
||||
assertEquals(0, ad.getAddresses().size());
|
||||
assertEquals(0, ad.getBindings().count());
|
||||
assertEquals(0, ad.getDirectBindings(SimpleString.of("Topic1.>")).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -374,6 +375,8 @@ public class WildcardAddressManagerUnitTest extends ActiveMQTestBase {
|
|||
// publish again, read only
|
||||
ad.getBindingsForRoutingAddress(pubAddr);
|
||||
|
||||
ad.getDirectBindings(pubAddr);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
oops.set(e);
|
||||
|
|
Loading…
Reference in New Issue