Skip to content

Commit c132e5c

Browse files
committed
Optimize asynchronous queue commit performance; Fix issue where addBlock() method of BlockArrayBuilder was not getting meta values from IItemStack correctly; Fix issue where FluidPerTickOutput was not working correctly; Reduce an interval for mechanical controller to update redstone signals (may have side effects); Add performance consumption display for controllers (experimental).
1 parent 1ddf5ba commit c132e5c

File tree

9 files changed

+63
-42
lines changed

9 files changed

+63
-42
lines changed

src/main/java/github/kasuminova/mmce/common/concurrent/ActionExecutor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
public class ActionExecutor implements Runnable, Comparable<ActionExecutor> {
44
public final Action action;
5-
public int usedTime = 0;
65
public final int priority;
6+
public int usedTime = 0;
77

88
public ActionExecutor(Action action) {
99
this(action, 0);

src/main/java/github/kasuminova/mmce/common/concurrent/TaskExecutor.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
import hellfirepvp.modularmachinery.ModularMachinery;
44
import hellfirepvp.modularmachinery.common.tiles.base.TileEntitySynchronized;
55
import io.netty.util.internal.ThrowableUtil;
6+
import io.netty.util.internal.shaded.org.jctools.queues.atomic.MpscLinkedAtomicQueue;
67
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
78
import net.minecraftforge.fml.common.gameevent.TickEvent;
89
import net.minecraftforge.fml.relauncher.Side;
910

1011
import java.util.ArrayList;
1112
import java.util.HashSet;
12-
import java.util.concurrent.ConcurrentLinkedQueue;
1313
import java.util.concurrent.PriorityBlockingQueue;
1414
import java.util.concurrent.ThreadPoolExecutor;
1515
import java.util.concurrent.TimeUnit;
@@ -22,16 +22,16 @@
2222
public class TaskExecutor {
2323
public static final int THREAD_COUNT = Math.max(Math.max(Runtime.getRuntime().availableProcessors() / 4, 8), 4);
2424
public static final ThreadPoolExecutor THREAD_POOL = new ThreadPoolExecutor(
25-
THREAD_COUNT / 2, THREAD_COUNT, 5000, TimeUnit.MILLISECONDS,
25+
THREAD_COUNT / 4, THREAD_COUNT, 5000, TimeUnit.MILLISECONDS,
2626
new PriorityBlockingQueue<>(),
2727
new CustomThreadFactory("MMCE-TaskExecutor-%s"));
2828
public static long totalExecuted = 0;
2929
public static long taskUsedTime = 0;
3030
public static long totalUsedTime = 0;
3131
public static long executedCount = 0;
3232
private final ArrayList<ActionExecutor> submitted = new ArrayList<>();
33-
private final ConcurrentLinkedQueue<ActionExecutor> executors = new ConcurrentLinkedQueue<>();
34-
private final ConcurrentLinkedQueue<Action> mainThreadActions = new ConcurrentLinkedQueue<>();
33+
private final MpscLinkedAtomicQueue<ActionExecutor> executors = new MpscLinkedAtomicQueue<>();
34+
private final MpscLinkedAtomicQueue<Action> mainThreadActions = new MpscLinkedAtomicQueue<>();
3535
private final HashSet<TileEntitySynchronized> requireUpdateTEList = new HashSet<>();
3636
private final TaskSubmitter submitter = new TaskSubmitter();
3737
private volatile boolean inTick = false;

src/main/java/hellfirepvp/modularmachinery/common/crafting/requirement/RequirementFluid.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ private Optional<CraftCheck> checkStartCraftingWithMekanism(ProcessingComponent<
267267
@Override
268268
public boolean startCrafting(ProcessingComponent<?> component, RecipeCraftingContext context, ResultChance chance) {
269269
HybridTank handler = (HybridTank) component.providedComponent;
270-
if (Objects.requireNonNull(actionType) == IOType.INPUT) {
270+
if (actionType == IOType.INPUT) {
271271
if (Mods.MEKANISM.isPresent()) {
272272
return startCraftingWithMekanismHandling(handler, chance);
273273
}

src/main/java/hellfirepvp/modularmachinery/common/crafting/requirement/RequirementFluidPerTick.java

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import hellfirepvp.modularmachinery.common.machine.IOType;
1010
import hellfirepvp.modularmachinery.common.machine.MachineComponent;
1111
import hellfirepvp.modularmachinery.common.modifier.RecipeModifier;
12-
import hellfirepvp.modularmachinery.common.util.CopyHandlerHelper;
1312
import hellfirepvp.modularmachinery.common.util.HybridTank;
1413
import hellfirepvp.modularmachinery.common.util.ResultChance;
1514
import hellfirepvp.modularmachinery.common.util.nbt.NBTMatchingHelper;
@@ -74,21 +73,9 @@ public CraftCheck doFluidIO(ProcessingComponent<?> component, RecipeCraftingCont
7473
}
7574
return CraftCheck.failure("craftcheck.failure.fluid.input");
7675
case OUTPUT:
77-
handler = CopyHandlerHelper.copyTank(handler);
78-
79-
for (ComponentOutputRestrictor restrictor : restrictions) {
80-
if (restrictor instanceof ComponentOutputRestrictor.RestrictionTank) {
81-
ComponentOutputRestrictor.RestrictionTank tank = (ComponentOutputRestrictor.RestrictionTank) restrictor;
82-
83-
if (tank.exactComponent.equals(component)) {
84-
handler.fillInternal(tank.inserted == null ? null : tank.inserted.copy().asFluidStack(), true);
85-
}
86-
}
87-
}
88-
int filled = handler.fillInternal(this.requirementCheck.copy().asFluidStack(), doFillOrDrain); //True or false doesn't really matter tbh
76+
int filled = handler.fillInternal(this.requirementCheck.copy().asFluidStack(), doFillOrDrain);
8977
boolean didFill = filled >= this.requirementCheck.getAmount();
9078
if (didFill) {
91-
context.addRestriction(new ComponentOutputRestrictor.RestrictionTank(this.requirementCheck.copy(), component));
9279
return CraftCheck.success();
9380
}
9481
return CraftCheck.failure("craftcheck.failure.fluid.output.space");

src/main/java/hellfirepvp/modularmachinery/common/integration/crafttweaker/BlockArrayBuilder.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import hellfirepvp.modularmachinery.common.util.IBlockStateDescriptor;
1515
import net.minecraft.block.Block;
1616
import net.minecraft.init.Blocks;
17+
import net.minecraft.item.Item;
1718
import net.minecraft.item.ItemStack;
1819
import net.minecraft.nbt.NBTTagCompound;
1920
import net.minecraft.util.math.BlockPos;
@@ -119,6 +120,7 @@ public BlockArrayBuilder addBlock(int[] xList, int[] yList, int[] zList, IBlockS
119120
* @param z Z
120121
* @param ctItemStacks 物品
121122
*/
123+
@SuppressWarnings("deprecation")
122124
@ZenMethod
123125
public BlockArrayBuilder addBlock(int x, int y, int z, IItemStack... ctItemStacks) {
124126
List<ItemStack> stackList = new ArrayList<>();
@@ -127,9 +129,18 @@ public BlockArrayBuilder addBlock(int x, int y, int z, IItemStack... ctItemStack
127129
}
128130
List<IBlockStateDescriptor> stateDescriptorList = new ArrayList<>();
129131
for (ItemStack stack : stackList) {
130-
Block block = Block.getBlockFromItem(stack.getItem());
132+
Item item = stack.getItem();
133+
int meta = stack.getMetadata();
134+
Block block = Block.getBlockFromItem(item);
131135
if (block != Blocks.AIR) {
132-
stateDescriptorList.add(new IBlockStateDescriptor(block));
136+
try {
137+
net.minecraft.block.state.IBlockState state = block.getStateFromMeta(meta);
138+
stateDescriptorList.add(new IBlockStateDescriptor(state));
139+
} catch (Exception e) {
140+
CraftTweakerAPI.logError(String.format("[ModularMachinery] Failed to get BlockState from <%s>!",
141+
stack.getItem().getRegistryName() + ":" + meta
142+
));
143+
}
133144
} else {
134145
CraftTweakerAPI.logError("[ModularMachinery] " + stack.getDisplayName() + " cannot convert to Block!");
135146
}

src/main/java/hellfirepvp/modularmachinery/common/tiles/TileMachineController.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ private void doRecipeTick() {
145145
}
146146
if (this.getCraftingStatus().isCrafting()) {
147147
onTick();
148-
if (this.activeRecipe.isCompleted()) {
148+
if (activeRecipe != null && activeRecipe.isCompleted()) {
149149
if (ModularMachinery.pluginServerCompatibleMode) {
150150
ModularMachinery.EXECUTE_MANAGER.addSyncTask(this::onFinished);
151151
} else {
@@ -244,7 +244,14 @@ public void onTick() {
244244
* <p>机械完成一个配方。</p>
245245
*/
246246
public void onFinished() {
247-
List<IEventHandler<RecipeEvent>> handlerList = this.activeRecipe.getRecipe().getRecipeEventHandlers(RecipeFinishEvent.class);
247+
if (this.activeRecipe == null) {
248+
ModularMachinery.log.warn("Machine " + MiscUtils.posToString(getPos()) + " Try to finish a null recipe! ignored.");
249+
this.context = null;
250+
this.activeRecipe = null;
251+
return;
252+
}
253+
MachineRecipe recipe = this.activeRecipe.getRecipe();
254+
List<IEventHandler<RecipeEvent>> handlerList = recipe.getRecipeEventHandlers(RecipeFinishEvent.class);
248255
if (handlerList != null && !handlerList.isEmpty()) {
249256
for (IEventHandler<RecipeEvent> handler : handlerList) {
250257
RecipeFinishEvent event = new RecipeFinishEvent(this);

src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileEntitySynchronized.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,10 @@ public final void onDataPacket(@Nonnull NetworkManager manager, @Nonnull SPacket
7777
readNetNBT(packet.getNbtCompound());
7878
}
7979

80-
@SuppressWarnings("deprecation")
8180
public void markForUpdate() {
8281
IBlockState state = world.getBlockState(pos);
8382
world.notifyBlockUpdate(pos, state, state, 3);
84-
if (state.getBlock().hasComparatorInputOverride(state)) {
85-
markDirty();
86-
}
83+
markDirty();
8784
}
8885

8986
/**

src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileFluidTank.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
@Optional.Interface(modid = "mekanism", iface = "mekanism.api.gas.IGasHandler"),
4141
@Optional.Interface(modid = "mekanism", iface = "mekanism.api.gas.ITubeConnection")
4242
})
43+
@SuppressWarnings("deprecation")
4344
public abstract class TileFluidTank extends TileColorableMachineComponent implements MachineComponentTile, IGasHandler, ITubeConnection, SelectiveUpdateTileEntity {
4445

4546
private HybridTank tank;
@@ -56,14 +57,14 @@ public TileFluidTank(FluidHatchSize size, IOType type) {
5657
}
5758

5859
@Optional.Method(modid = "mekanism")
59-
private static boolean checkMekanismGasCapabilitiesPresence(Capability<?> capability, @Nullable EnumFacing facing) {
60-
return checkMekanismGasCapabilities(capability, facing);
60+
private static boolean checkMekanismGasCapabilitiesPresence(Capability<?> capability) {
61+
return checkMekanismGasCapabilities(capability);
6162
}
6263

6364
@Optional.Method(modid = "mekanism")
64-
private static boolean checkMekanismGasCapabilities(Capability<?> capability, @Nullable EnumFacing facing) {
65-
String gasType = IGasHandler.class.getName().intern();
66-
String tubeConnectionName = ITubeConnection.class.getName().intern();
65+
private static boolean checkMekanismGasCapabilities(Capability<?> capability) {
66+
String gasType = IGasHandler.class.getName();
67+
String tubeConnectionName = ITubeConnection.class.getName();
6768
return capability != null && (capability.getName().equals(gasType) || capability.getName().equals(tubeConnectionName));
6869
}
6970

@@ -77,7 +78,7 @@ public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing faci
7778
return true;
7879
}
7980
if (Mods.MEKANISM.isPresent()) {
80-
if (checkMekanismGasCapabilitiesPresence(capability, facing)) {
81+
if (checkMekanismGasCapabilitiesPresence(capability)) {
8182
return true;
8283
}
8384
}
@@ -86,12 +87,13 @@ public boolean hasCapability(Capability<?> capability, @Nullable EnumFacing faci
8687

8788
@Nullable
8889
@Override
90+
@SuppressWarnings("unchecked")
8991
public <T> T getCapability(Capability<T> capability, @Nullable EnumFacing facing) {
9092
if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) {
9193
return (T) tank;
9294
}
9395
if (Mods.MEKANISM.isPresent()) {
94-
if (checkMekanismGasCapabilities(capability, facing)) {
96+
if (checkMekanismGasCapabilities(capability)) {
9597
return (T) this;
9698
}
9799
}
@@ -139,7 +141,7 @@ public void writeCustomNBT(NBTTagCompound compound) {
139141

140142
@Nullable
141143
@Override
142-
public MachineComponent provideComponent() {
144+
public MachineComponent<?> provideComponent() {
143145
return new MachineComponent.FluidHatch(ioType) {
144146
@Override
145147
public HybridTank getContainerProvider() {

src/main/java/hellfirepvp/modularmachinery/common/tiles/base/TileMultiblockMachineController.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ public abstract class TileMultiblockMachineController extends TileEntityRestrict
7676
protected TaggedPositionBlockArray foundPattern = null;
7777
protected ActionExecutor tickExecutor = null;
7878
protected LinkedList<Integer> usedTimeList = new LinkedList<>();
79+
protected int usedTimeCache = 0;
7980
protected int structureCheckCounter = 0;
8081
protected int recipeResearchRetryCounter = 0;
8182

@@ -115,11 +116,13 @@ public final void doRestrictedTick() {
115116
return;
116117
}
117118
updateUsedTime();
119+
118120
long tickStart = System.nanoTime();
119121

122+
// Controller Tick
120123
doControllerTick();
121124

122-
addUsedTime((int) TimeUnit.MICROSECONDS.convert(System.nanoTime() - tickStart, TimeUnit.NANOSECONDS));
125+
incrementUsedTime((int) TimeUnit.MICROSECONDS.convert(System.nanoTime() - tickStart, TimeUnit.NANOSECONDS));
123126
}
124127

125128
public abstract void doControllerTick();
@@ -132,6 +135,13 @@ protected void updateUsedTime() {
132135
addUsedTime(tickExecutor == null ? 0 : tickExecutor.usedTime);
133136
}
134137

138+
protected void incrementUsedTime(int add) {
139+
Integer first = usedTimeList.getFirst();
140+
if (first != null) {
141+
usedTimeList.set(0, first + add);
142+
}
143+
}
144+
135145
protected void addUsedTime(int time) {
136146
usedTimeList.addFirst(time);
137147
if (usedTimeList.size() > 100) {
@@ -140,11 +150,9 @@ protected void addUsedTime(int time) {
140150
}
141151

142152
public int usedTimeAvg() {
143-
int sum = 0;
144-
for (Integer time : usedTimeList) {
145-
sum += time;
146-
}
147-
return sum / usedTimeList.size();
153+
ModularMachinery.EXECUTE_MANAGER.addParallelAsyncTask(() ->
154+
usedTimeCache = usedTimeList.stream().mapToInt(time -> time).sum() / usedTimeList.size());
155+
return usedTimeCache;
148156
}
149157

150158
public int getMaxParallelism() {
@@ -826,6 +834,15 @@ public int getTicksExisted() {
826834
return ticksExisted;
827835
}
828836

837+
@Override
838+
public void markForUpdate() {
839+
IBlockState state = world.getBlockState(pos);
840+
world.notifyBlockUpdate(pos, state, state, 3);
841+
if (ticksExisted % 10 == 0) {
842+
markDirty();
843+
}
844+
}
845+
829846
public enum Type {
830847
MISSING_STRUCTURE,
831848
CHUNK_UNLOADED,

0 commit comments

Comments
 (0)