From 59208aad8678291f011da1435b1b390488ec303c Mon Sep 17 00:00:00 2001 From: Tux Date: Fri, 4 Sep 2015 22:44:54 -0400 Subject: [PATCH] Improve EventBus by removing read locking. This is primarily done by using ConcurrentHashMap, which has lock-free reads and thread-contention-based writes. Only one thread at a time can register threads, however, as baking events isn't thread safe (and there's no reason to make it thread-safe anyway). My own benchmarks indicate 1.4-2.2 million operations/ms throughput and approximately ~1ns/event post for four threads posting events. --- .../java/net/md_5/bungee/event/EventBus.java | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/event/src/main/java/net/md_5/bungee/event/EventBus.java b/event/src/main/java/net/md_5/bungee/event/EventBus.java index 00dc76d1..5b5d4201 100644 --- a/event/src/main/java/net/md_5/bungee/event/EventBus.java +++ b/event/src/main/java/net/md_5/bungee/event/EventBus.java @@ -9,8 +9,9 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger; @@ -18,8 +19,8 @@ public class EventBus { private final Map, Map>> byListenerAndPriority = new HashMap<>(); - private final Map, EventHandlerMethod[]> byEventBaked = new HashMap<>(); - private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final Map, EventHandlerMethod[]> byEventBaked = new ConcurrentHashMap<>(); + private final Lock lock = new ReentrantLock(); private final Logger logger; public EventBus() @@ -34,15 +35,7 @@ public class EventBus public void post(Object event) { - EventHandlerMethod[] handlers; - lock.readLock().lock(); - try - { - handlers = byEventBaked.get( event.getClass() ); - } finally - { - lock.readLock().unlock(); - } + EventHandlerMethod[] handlers = byEventBaked.get( event.getClass() ); if ( handlers != null ) { @@ -103,7 +96,7 @@ public class EventBus public void register(Object listener) { Map, Map>> handler = findHandlers( listener ); - lock.writeLock().lock(); + lock.lock(); try { for ( Map.Entry, Map>> e : handler.entrySet() ) @@ -129,14 +122,14 @@ public class EventBus } } finally { - lock.writeLock().unlock(); + lock.unlock(); } } public void unregister(Object listener) { Map, Map>> handler = findHandlers( listener ); - lock.writeLock().lock(); + lock.lock(); try { for ( Map.Entry, Map>> e : handler.entrySet() ) @@ -165,7 +158,7 @@ public class EventBus } } finally { - lock.writeLock().unlock(); + lock.unlock(); } } @@ -202,7 +195,7 @@ public class EventBus byEventBaked.put( eventClass, handlersList.toArray( new EventHandlerMethod[ handlersList.size() ] ) ); } else { - byEventBaked.put( eventClass, null ); + byEventBaked.remove( eventClass ); } } }