Reduce external inventory polling overhead (#1596)

This commit is contained in:
Algent authored and GitHub committed 2026-09-24 04:35:19 +00:00
1 parent a5b9cf5e16
commit 3455778252
2 files changed
+72 -13

No files matched your search

@@ -0,0 +1,51 @@
package appeng.test.me.storage;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import org.junit.jupiter.api.Test;
import appeng.api.config.StorageFilter;
import appeng.api.storage.data.IAEItemStack;
import appeng.me.storage.MEMonitorIInventory;
import appeng.util.inv.AdaptorList;
public class MEMonitorIInventoryFunctionalTest {
@Test
public void boundsRetainedTypesWithoutReadingTheCache() {
final int slots = 54;
final Item item = new Item().setHasSubtypes(true);
final List<ItemStack> contents = new ArrayList<>();
for (int slot = 0; slot < slots; slot++) {
contents.add(null);
}
final MEMonitorIInventory monitor = new MEMonitorIInventory(new AdaptorList(contents));
monitor.setMode(StorageFilter.NONE);
for (int poll = 0; poll < 512; poll++) {
for (int slot = 0; slot < slots; slot++) {
contents.set(slot, new ItemStack(item, 1, poll * slots + slot));
}
monitor.onTick();
// size() does not iterate or clean the list; iteration would hide the regression.
assertTrue(monitor.getStorageList().size() <= 2 * slots);
}
long total = 0;
for (final IAEItemStack stack : monitor.getStorageList()) {
total += stack.getStackSize();
}
assertEquals(slots, total);
contents.clear();
monitor.onTick();
assertTrue(monitor.getStorageList().isEmpty());
}
}
@@ -40,6 +40,8 @@ import appeng.util.item.ItemFilterList;
public class MEMonitorIInventory implements IStorageBusMonitor<IAEItemStack> {
private static final int CACHE_REFRESH_INTERVAL = 256;
private final InventoryAdaptor adaptor;
private final IItemList<IAEItemStack> list = AEApi.instance().storage().createItemList();
private final HashMap<IMEMonitorHandlerReceiver, Object> listeners = new HashMap<>();
@@ -47,6 +49,7 @@ public class MEMonitorIInventory implements IStorageBusMonitor<IAEItemStack> {
private BaseActionSource mySource;
private StorageFilter mode = StorageFilter.EXTRACTABLE_ONLY;
private boolean init = false;
private int ticksSinceCacheRefresh = 0;
public MEMonitorIInventory(final InventoryAdaptor adaptor) {
this.adaptor = adaptor;
@@ -123,10 +126,11 @@ public class MEMonitorIInventory implements IStorageBusMonitor<IAEItemStack> {
final LinkedList<IAEStack<?>> changes = new LinkedList<>();
this.list.resetStatus();
int high = 0;
int high = -1;
int slots = 0;
boolean changed = false;
for (final ItemSlot is : this.adaptor) {
slots++;
final CachedItemStack old = this.memory.get(is.getSlot());
high = Math.max(high, is.getSlot());
@@ -145,7 +149,6 @@ public class MEMonitorIInventory implements IStorageBusMonitor<IAEItemStack> {
if (cis.aeStack != null) {
changes.add(cis.aeStack);
this.list.add(cis.aeStack);
}
changed = true;
@@ -153,19 +156,11 @@ public class MEMonitorIInventory implements IStorageBusMonitor<IAEItemStack> {
final int newSize = (newIS == null ? 0 : newIS.stackSize);
final int diff = newSize - (oldIS == null ? 0 : oldIS.stackSize);
final IAEItemStack stack = (old == null || old.aeStack == null
? AEApi.instance().storage().createItemStack(newIS)
: old.aeStack.copy());
if (stack != null) {
stack.setStackSize(newSize);
this.list.add(stack);
}
if (diff != 0 && stack != null) {
if (diff != 0 && old != null && old.aeStack != null) {
final CachedItemStack cis = new CachedItemStack(is.getItemStack());
this.memory.put(is.getSlot(), cis);
final IAEItemStack a = stack.copy();
final IAEItemStack a = old.aeStack.copy();
a.setStackSize(diff);
changes.add(a);
changed = true;
@@ -187,6 +182,19 @@ public class MEMonitorIInventory implements IStorageBusMonitor<IAEItemStack> {
end.clear();
}
// Bound zero-count entries under item-type churn without scanning the list on every poll.
if (++this.ticksSinceCacheRefresh >= CACHE_REFRESH_INTERVAL || this.list.size() > slots) {
this.list.resetStatus();
for (final CachedItemStack cached : this.memory.values()) {
this.list.add(cached.aeStack);
}
this.ticksSinceCacheRefresh = 0;
} else {
for (final IAEStack<?> change : changes) {
this.list.add((IAEItemStack) change);
}
}
if (!changes.isEmpty()) {
this.postDifference(changes);
}