Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory & Performance Improvements #96

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import illarion.client.input.CurrentMouseLocationEvent;
import illarion.client.world.World;
import illarion.client.world.characters.CharacterAttribute;
import illarion.common.memory.MemoryPools;
import illarion.common.types.DisplayCoordinate;
import org.illarion.engine.Engine;
import org.illarion.engine.EngineException;
Expand Down Expand Up @@ -148,7 +149,9 @@ public void update(@Nonnull GameContainer container, int delta) {
Camera.getInstance().setViewport(-offX, -offY, container.getWidth(), container.getHeight());

Input engineInput = container.getEngine().getInput();
gameScene.publishEvent(new CurrentMouseLocationEvent(engineInput.getMouseX(), engineInput.getMouseY()));
CurrentMouseLocationEvent event = MemoryPools.get(CurrentMouseLocationEvent.class);
event.set(engineInput.getMouseX(), engineInput.getMouseY());
gameScene.publishEvent(event);
gameScene.update(container, delta);
updateFog(container);
updateDeadView(container);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package illarion.client.input;

import illarion.common.memory.Poolable;
import org.illarion.engine.graphic.SceneEvent;

import javax.annotation.Nonnull;
Expand All @@ -24,16 +25,16 @@
*
* @author Martin Karing <nitram@illarion.org>
*/
public abstract class AbstractMouseLocationEvent implements SceneEvent {
public abstract class AbstractMouseLocationEvent implements SceneEvent, Poolable {
/**
* The x coordinate on the screen where the click occurred.
*/
private final int x;
private int x;

/**
* The y coordinate on the screen where the click occurred.
*/
private final int y;
private int y;

/**
* Create and initialize such an event.
Expand Down Expand Up @@ -74,8 +75,26 @@ public int getY() {
return y;
}

/**
* set x and y coordinate
*
* @param x the x coordinate on the screen where the click occurred.
* @param y the y coordinate on the screen where the click occurred.
*/
protected void set (int x, int y) {
this.x = x;
this.y = y;
}

@Override
public void notHandled() {
// nothing
}

@Override
public void reset () {
this.x = 0;
this.y = 0;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package illarion.client.input;

import illarion.common.memory.Poolable;
import org.illarion.engine.input.Button;

import javax.annotation.Nonnull;
Expand All @@ -29,7 +30,7 @@ public abstract class AbstractMouseOnMapEvent extends AbstractMouseLocationEvent
* The mouse key that was clicked.
*/
@Nonnull
private final Button key;
private Button key;

/**
* Create and initialize such an event.
Expand All @@ -43,6 +44,13 @@ protected AbstractMouseOnMapEvent(@Nonnull Button key, int x, int y) {
this.key = key;
}

/**
* Create and initialize such an event.
*/
protected AbstractMouseOnMapEvent() {
super(0, 0);
}

/**
* The copy constructor.
*
Expand All @@ -53,6 +61,18 @@ protected AbstractMouseOnMapEvent(@Nonnull AbstractMouseOnMapEvent org) {
key = org.key;
}

/**
* Create and initialize such an event.
*
* @param key the mouse key that was clicked
* @param x the x coordinate of the click
* @param y the y coordinate of the click
*/
public void set (@Nonnull Button key, int x, int y) {
super.set(x, y);
this.key = key;
}

/**
* Get the key that was clicked on the mouse.
*
Expand All @@ -62,4 +82,11 @@ protected AbstractMouseOnMapEvent(@Nonnull AbstractMouseOnMapEvent org) {
public Button getKey() {
return key;
}

@Override
public void reset () {
super.reset();
this.key = null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,24 @@ public final class ClickOnMapEvent extends AbstractMouseOnMapEvent {
super(key, x, y);
}

/**
* Create and initialize such an event.
*/
public ClickOnMapEvent() {
super();
}

/**
* Initialize such an event.
*
* @param key the mouse key that was clicked
* @param x the x coordinate of the click
* @param y the y coordinate of the click
*/
public void set (@Nonnull Button key, int x, int y) {
super.set(key, x, y);
}

@Override
public void notHandled() {
if (getKey() == Button.Right) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ public CurrentMouseLocationEvent(int x, int y) {
super(x, y);
}

/**
* Create and initialize such an event.
*/
public CurrentMouseLocationEvent () {
super(0, 0);
}

public void set (int x, int y) {
super.set(x, y);
}

/**
* Create and initialize such an event.
*
Expand All @@ -53,4 +64,11 @@ public boolean isHighlightHandled() {
public void setHighlightHandled(boolean highlightHandled) {
this.highlightHandled = highlightHandled;
}

@Override
public void reset () {
super.reset();
highlightHandled = false;
}

}
17 changes: 13 additions & 4 deletions illaclient/src/main/java/illarion/client/input/InputReceiver.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import illarion.client.IllaClient;
import illarion.client.world.World;
import illarion.common.gui.AbstractMultiActionHelper;
import illarion.common.memory.MemoryPools;
import org.bushe.swing.event.EventBus;
import org.illarion.engine.input.*;
import org.slf4j.Logger;
Expand Down Expand Up @@ -85,7 +86,9 @@ public void executeAction(int count) {
if (log.isDebugEnabled()) {
log.debug("Raising single click event for {} button at {} {}", key.name(), x, y);
}
EventBus.publish(new ClickOnMapEvent(key, x, y));
ClickOnMapEvent event = MemoryPools.get(ClickOnMapEvent.class);
event.set(key, x, y);
EventBus.publish(event);
break;
case 2:
if (log.isDebugEnabled()) {
Expand Down Expand Up @@ -131,7 +134,9 @@ public void setInputData(int posX, int posY) {

@Override
public void executeAction(int count) {
EventBus.publish(new PointOnMapEvent(x, y));
PointOnMapEvent event = MemoryPools.get(PointOnMapEvent.class);
event.set(x, y);
EventBus.publish(event);
}
}

Expand Down Expand Up @@ -255,7 +260,9 @@ public void buttonClicked(int mouseX, int mouseY, @Nonnull Button button, int co
log.debug("Received {} mouse clicked {} times at {}, {}", button, count, mouseX, mouseY);
switch (count) {
case 1:
World.getMapDisplay().getGameScene().publishEvent(new ClickOnMapEvent(button, mouseX, mouseY));
ClickOnMapEvent event = MemoryPools.get(ClickOnMapEvent.class);
event.set(button, mouseX, mouseY);
World.getMapDisplay().getGameScene().publishEvent(event);
break;
case 2:
World.getMapDisplay().getGameScene()
Expand All @@ -273,7 +280,9 @@ public void mouseMoved(int mouseX, int mouseY) {
if (enabled) {
pointAtHelper.setInputData(mouseX, mouseY);
pointAtHelper.pulse();
EventBus.publish(new MoveOnMapEvent(mouseX, mouseY));
MoveOnMapEvent event = MemoryPools.get(MoveOnMapEvent.class);
event.set(mouseX, mouseY);
EventBus.publish(event);
}
}

Expand Down
19 changes: 19 additions & 0 deletions illaclient/src/main/java/illarion/client/input/MoveOnMapEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,23 @@ public final class MoveOnMapEvent extends AbstractMouseLocationEvent {
public MoveOnMapEvent(int x, int y) {
super(x, y);
}

/**
* Create and initialize such an event.
*/
public MoveOnMapEvent() {
super(0, 0);
}

/**
* Initialize such an event.
*
* @param x the x coordinate of the click
* @param y the y coordinate of the click
*/
@Override
public void set (int x, int y) {
super.set(x, y);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,21 @@ public final class PointOnMapEvent extends AbstractMouseLocationEvent {
public PointOnMapEvent(int x, int y) {
super(x, y);
}

/**
* Create and initialize such an event.
*/
public PointOnMapEvent() {
super(0, 0);
}

/**
* Initialize such an event.
*
* @param x the x coordinate of the click
* @param y the y coordinate of the click
*/
public void set (int x, int y) {
super.set(x, y);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package illarion.common.memory;

public class MemoryAllocatorException extends RuntimeException {

public MemoryAllocatorException (Class<?> cls, Throwable e) {
super("Couldn't create a new instance of class " + cls.getCanonicalName() + ", maybe constructor is not accessible (private / protected) or there isn't a default constructor?", e);
}

}
53 changes: 53 additions & 0 deletions illacommon/src/main/java/illarion/common/memory/MemoryPool.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package illarion.common.memory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
* A pool of objects that can be reused to avoid allocation
*/
public class MemoryPool<T> {

private static final Logger LOGGER = LoggerFactory.getLogger(MemoryPool.class);

protected Queue<T> freeObjs = new ConcurrentLinkedQueue<>();
protected final int MAX_OBJECTS = 20;

protected MemoryPool() {
//
}

public T get (Class<T> cls) {
T obj = freeObjs.poll();

if (obj == null) {
// There is no free object in queue --> allocate a new one
try {
obj = cls.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new MemoryAllocatorException(cls, e);
}
}

return obj;
}

public void free (T obj) {
// Reset object, if possible
if (obj instanceof Poolable) {
((Poolable) obj).reset();
}

if (freeObjs.size() >= MAX_OBJECTS) {
// Queue is full, don't add another object, else memory usage will increase drastically
LOGGER.warn("memory pool of type '" + obj.getClass().getSimpleName() + "' is full, cannot recycle object.");
return;
}

freeObjs.add(obj);
}

}
Loading