Skip to content

Commit

Permalink
micro-optimise TileComponentFrequency some more
Browse files Browse the repository at this point in the history
  • Loading branch information
thiakil committed Aug 9, 2024
1 parent 0601185 commit b53e5fa
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package mekanism.common.lib;

import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import it.unimi.dsi.fastutil.objects.ObjectSet;
import it.unimi.dsi.fastutil.objects.ObjectSets;
import java.util.Map;
import java.util.function.BiConsumer;
import org.jetbrains.annotations.NotNull;

/**
* Version of array map which does a proper BiConsumer and a couple other microoptimisations.
* Used in {@link mekanism.common.lib.frequency.TileComponentFrequency}, which is in a very hot path as EVERY mek machine uses one
*/
public class CustomObjectToObjectArrayMap<KEY, VALUE> extends Object2ObjectArrayMap<KEY, VALUE> {

public CustomObjectToObjectArrayMap() {
super();
}

public CustomObjectToObjectArrayMap(Map<? extends KEY, ? extends VALUE> m) {
super(m);
}

@SuppressWarnings("unchecked")
@Override
public void forEach(BiConsumer<? super KEY, ? super VALUE> consumer) {
if (size == 0) {
return;
}
final int max = size;
for (int i = 0; i < max; i++) {
consumer.accept((KEY)key[i], (VALUE)value[i]);
}
}

//save a tiny bit of heap space and not create an object
@Override
public @NotNull ObjectSet<KEY> keySet() {
return size == 0 ? ObjectSets.emptySet() : super.keySet();
}

//save a tiny bit of heap space and not create an object
@Override
public @NotNull ObjectSet<Map.Entry<KEY, VALUE>> entrySet() {
return size == 0 ? ObjectSets.emptySet() : super.entrySet();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.LinkedHashMap;
import java.util.List;
Expand All @@ -15,13 +13,15 @@
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import mekanism.api.SerializationConstants;
import mekanism.api.security.SecurityMode;
import mekanism.common.attachments.FrequencyAware;
import mekanism.common.inventory.container.MekanismContainer;
import mekanism.common.inventory.container.sync.SyncableFrequency;
import mekanism.common.inventory.container.sync.list.SyncableFrequencyList;
import mekanism.common.lib.CustomObjectToObjectArrayMap;
import mekanism.common.lib.frequency.Frequency.FrequencyIdentity;
import mekanism.common.lib.security.SecurityFrequency;
import mekanism.common.lib.security.SecurityUtils;
Expand Down Expand Up @@ -49,7 +49,7 @@ public class TileComponentFrequency implements ITileComponent {

private final TileEntityMekanism tile;

private Map<FrequencyType<?>, FrequencyData> nonSecurityFrequencies = Collections.emptyMap();
private final CustomObjectToObjectArrayMap<FrequencyType<?>, FrequencyData> nonSecurityFrequencies = new CustomObjectToObjectArrayMap<>();
@Nullable
private FrequencyData securityFrequency = null;

Expand All @@ -59,6 +59,9 @@ public class TileComponentFrequency implements ITileComponent {
private boolean needsSave;
private boolean needsNotify;

//Method refs to allocate once and reuse in hot path
private final BiConsumer<FrequencyType<?>, FrequencyData> updateFrequencyRef = this::updateFrequency;

public TileComponentFrequency(TileEntityMekanism tile) {
this.tile = tile;
this.tickOffset = OFFSET.getAndIncrement() % 5;
Expand All @@ -78,9 +81,7 @@ public void tickServer(Level level, BlockPos pos) {
if (securityFrequency != null) {
updateFrequency(FrequencyType.SECURITY, securityFrequency);
}
for (Entry<FrequencyType<?>, FrequencyData> entry : nonSecurityFrequencies.entrySet()) {
updateFrequency(entry.getKey(), entry.getValue());
}
nonSecurityFrequencies.forEach(updateFrequencyRef);
}
if (needsNotify) {
tile.invalidateCapabilitiesFull();
Expand All @@ -101,15 +102,7 @@ public void track(FrequencyType<?> type, boolean needsSync, boolean needsListCac
if (type == FrequencyType.SECURITY) {
securityFrequency = value;
} else {
if (nonSecurityFrequencies.isEmpty()) {
nonSecurityFrequencies = Collections.singletonMap(type, value);
} else if (nonSecurityFrequencies.size() == 1) {
//don't expect this to happen, unless we get an all-in-one block
nonSecurityFrequencies = new Object2ObjectArrayMap<>(nonSecurityFrequencies);
nonSecurityFrequencies.put(type, value);
} else {
nonSecurityFrequencies.put(type, value);
}
nonSecurityFrequencies.put(type, value);
}
}

Expand Down Expand Up @@ -266,8 +259,8 @@ public String getComponentKey() {
@Override
public void applyImplicitComponents(@NotNull BlockEntity.DataComponentInput input) {
if (!tile.isRemote()) {
for (Map.Entry<FrequencyType<?>, FrequencyData> entry : nonSecurityFrequencies.entrySet()) {
setFrequencyFromComponent(input, entry.getKey());
for (FrequencyType<?> key : nonSecurityFrequencies.keySet()) {
setFrequencyFromComponent(input, key);
}
}
}
Expand All @@ -286,8 +279,7 @@ private <FREQ extends Frequency> void setFrequencyFromComponent(BlockEntity.Data

@Override
public void addRemapEntries(List<DataComponentType<?>> remapEntries) {
for (Map.Entry<FrequencyType<?>, FrequencyData> entry : nonSecurityFrequencies.entrySet()) {
FrequencyType<?> type = entry.getKey();
for (FrequencyType<?> type : nonSecurityFrequencies.keySet()) {
DataComponentType<? extends FrequencyAware<?>> frequencyComponent = MekanismDataComponents.getFrequencyComponent(type);
if (frequencyComponent != null && !remapEntries.contains(frequencyComponent)) {
remapEntries.add(frequencyComponent);
Expand Down

0 comments on commit b53e5fa

Please sign in to comment.