Reputation: 13
So I was reworking my Event System and I want to get it as optimized as possible. I have this down to about 82ms to fire 1 million events. I want to ask if there is anything you'd do differently and how to further optimize this? At the moment there is only some basic logic being done when an event is fired to the method, when I plan to use this for an upcoming project it will be a little more advanced which would probably double the execution time.
package me.xerces.eventbus;
import me.xerces.eventbus.annotation.EventHandler;
import me.xerces.eventbus.event.Event;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
public class EventManager {
private ArrayList<Map.Entry<Class, EventHandle>> eventHandlerList = new ArrayList<Map.Entry<Class, EventHandle>>();
public void addEventListener(Object object)
{
for(Method method : object.getClass().getDeclaredMethods())
{
if(method.isAnnotationPresent(EventHandler.class))
{
Map.Entry<Class, EventHandle> eventHandleEntry = new AbstractMap.SimpleEntry<Class, EventHandle>(method.getParameterTypes()[0], new EventHandle(method, object));
method.setAccessible(true);
eventHandlerList.add(eventHandleEntry);
}
}
}
public void addSpecificEventListener(Object object, Class eventClass)
{
for(Method method : object.getClass().getDeclaredMethods())
{
if(method.isAnnotationPresent(EventHandler.class) && method.getParameterTypes().length > 0 && method.getParameterTypes()[0].equals(eventClass))
{
Map.Entry<Class, EventHandle> eventHandleEntry = new AbstractMap.SimpleEntry<Class, EventHandle>(method.getParameterTypes()[0], new EventHandle(method, object));
method.setAccessible(true);
eventHandlerList.add(eventHandleEntry);
}
}
}
public void removeEventListener(Object object)
{
Iterator<Map.Entry<Class, EventHandle>> iterator = eventHandlerList.iterator();
while(iterator.hasNext())
{
Map.Entry<Class, EventHandle> entry = iterator.next();
if(entry.getValue().getMethodClass().equals(object))
iterator.remove();
}
}
public void fireEvent(Event event)
{
Iterator<Map.Entry<Class, EventHandle>> iterator = eventHandlerList.iterator();
while(iterator.hasNext())
{
Map.Entry<Class, EventHandle> entry = iterator.next();
if(entry.getKey().equals(event.getClass())) {
try {
EventHandle eventHandle = entry.getValue();
eventHandle.getMethod().invoke(eventHandle.getMethodClass(), event);
} catch (IllegalAccessException | InvocationTargetException e)
{
e.printStackTrace();
}
}
}
}
}
Github link: https://github.com/X3rces/EventBus EDIT: Is there a way to speed up when the JVM converts the invokation to a straight method call instead of using JNI?
Upvotes: 1
Views: 309
Reputation: 2662
You can avoid
if(entry.getKey().equals(event.getClass())) {
by using
private final Map<Class<?>, List<EventHandle>> eventHandlerMap = new HashMap<>();
See my EventSystem code in question
Upvotes: 1