mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-26 02:19:19 +00:00
Bunch of side perf improvements (#217)
* Fix TE Lag * Sepals Rearrange the attackable conditions * Cache ItemStack max stack size * fix build * extra: Skip dirty stats copy when requesting player stats * extra: Reset dirty flag when loading maps from the disk * extra: Supporting block cache * extra: Avoid useless deque clear on - credit: @MachineBreaker * experimental/draft: Optimize SortedArraySet * experimental/draft: Simplify SortedArraySet - sometime complex stuff doesnt mean faster. * extra: Change maps/sets in brain + remove streams from villagers * extra: Remove 'copyOf' from Baby Villager Sensor * experimental: Rewrite trigger in SimpleCriterionTrigger * [ci/skip] fix comments * Faster setter for SimpleCriterionTrigger * extra: Cache and optimize fluidOnEyes * Sync changes * [ci/skip] cleanup * extra: QuadTree implementation for isChunkNearPlayer * [ci/skip] cleanup * [ci/skip] cleanup * [ci/skip] clean up * [ci/skip] cleanup * Only player pushable * Store chunkPos with keys * [ci/skip] cleanup * [ci/skip] cleanup * cleanup * rebuild patches * cache some more stuff * extra: optimize collectTickingChunks * remove quadTree optimization for now (will open a new PR just for that) * temp: Lazily optimize isChunkNearPlayer * Inline filter & merge as a single loop * [ci/skip] Add diff on change * extra: optimize everything but the testing itself on getEntities * [ci/skip] cleanup * Optimize chunkUnloadQueue * Remove iterators from inventory * [ci/skip] Add TODOs * i hate programming * remove forEach * extra: Alternative Brain Behaviour * remove: opt getEntities + cache fluidOnEyes * extra: Improve checkDespawn - credits: @kidofcubes * extra: Improve pushEntity and getEntities * yeet this * VERY EXPERIMENTAL: getEntities Optimization * fix bunch of issues from getEntities patch * extra: slightly optimize getNearestPlayer - credits: @kidofcubes * drop a patch for now (will open a new pr) * move these to a new branch * fix and optimize checkDespawn patches * Rebuild Patches * [ci/skip] Update benchmark * [ci/skip] cleanup * Drop * [ci/skip] Drop * Rebuild * [ci/skip] * Add configurable brain running behavior cache update interval * Move to new pr * [ci/skip] Update benchmark --------- Co-authored-by: MachineBreaker <saltspigotpp@gmail.com> Co-authored-by: kidofcubes <kidofcubes@gmail.com> Co-authored-by: Dreeam <61569423+Dreeam-qwq@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
package org.dreeam.leaf.config.modules.gameplay;
|
||||
|
||||
import org.dreeam.leaf.config.ConfigModules;
|
||||
import org.dreeam.leaf.config.EnumConfigCategory;
|
||||
|
||||
public class OnlyPlayerPushable extends ConfigModules {
|
||||
|
||||
public String getBasePath() {
|
||||
return EnumConfigCategory.GAMEPLAY.getBaseKeyName() + ".only-player-pushable";
|
||||
}
|
||||
|
||||
public static boolean enabled = false;
|
||||
|
||||
@Override
|
||||
public void onLoaded() {
|
||||
enabled = config.getBoolean(getBasePath(), enabled, """
|
||||
Enable to make only player pushable
|
||||
This option override the armorstand doCollisionEntityLookups and
|
||||
...write in docs""");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.dreeam.leaf.config.modules.opt;
|
||||
|
||||
import org.dreeam.leaf.config.ConfigModules;
|
||||
import org.dreeam.leaf.config.EnumConfigCategory;
|
||||
|
||||
public class BrainRunningBehaviorCacheUpdate extends ConfigModules {
|
||||
|
||||
public String getBasePath() {
|
||||
return EnumConfigCategory.PERF.getBaseKeyName();
|
||||
}
|
||||
|
||||
public static int interval = 5;
|
||||
|
||||
@Override
|
||||
public void onLoaded() {
|
||||
interval = config.getInt(getBasePath() + ".entity-running-behavior-cache-update-interval", interval,
|
||||
config.pickStringRegionBased(
|
||||
"How often entity update current brain running behavior list.",
|
||||
"生物更新现有 Brain Behavior 列表缓存的间隔."));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package org.dreeam.leaf.util.list;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import net.minecraft.world.level.block.entity.TickingBlockEntity;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A list for ServerLevel's blockEntityTickers
|
||||
* <p>
|
||||
* This list behaves identically to ObjectArrayList, but it has an additional method, `removeAllByIndex`, that allows a list of integers to be passed indicating what
|
||||
* indexes should be deleted from the list
|
||||
* <p>
|
||||
* This is faster than using removeAll, since we don't need to compare the identity of each block entity, and faster than looping thru each index manually and deleting with remove,
|
||||
* since we don't need to resize the array every single remove.
|
||||
*/
|
||||
public final class BlockEntityTickersList extends ObjectArrayList<TickingBlockEntity> {
|
||||
|
||||
private final IntOpenHashSet toRemove = new IntOpenHashSet();
|
||||
private int startSearchFromIndex = -1;
|
||||
|
||||
/**
|
||||
* Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
|
||||
*/
|
||||
public BlockEntityTickersList() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array list and fills it with a given collection.
|
||||
*
|
||||
* @param c a collection that will be used to fill the array list.
|
||||
*/
|
||||
public BlockEntityTickersList(final Collection<? extends TickingBlockEntity> c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks an entry as removed
|
||||
*
|
||||
* @param index the index of the item on the list to be marked as removed
|
||||
*/
|
||||
public void markAsRemoved(final int index) {
|
||||
// The block entities list always loop starting from 0, so we only need to check if the startSearchFromIndex is -1 and that's it
|
||||
if (this.startSearchFromIndex == -1)
|
||||
this.startSearchFromIndex = index;
|
||||
|
||||
this.toRemove.add(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes elements that have been marked as removed.
|
||||
*/
|
||||
public void removeMarkedEntries() {
|
||||
if (this.startSearchFromIndex == -1) // No entries in the list, skip
|
||||
return;
|
||||
|
||||
removeAllByIndex(startSearchFromIndex, toRemove);
|
||||
toRemove.clear();
|
||||
this.startSearchFromIndex = -1; // Reset the start search index
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes elements by their index.
|
||||
*/
|
||||
private void removeAllByIndex(final int startSearchFromIndex, final IntOpenHashSet c) { // can't use Set<Integer> because we want to avoid autoboxing when using contains
|
||||
final int requiredMatches = c.size();
|
||||
if (requiredMatches == 0)
|
||||
return; // exit early, we don't need to do anything
|
||||
|
||||
final Object[] a = this.a;
|
||||
int j = startSearchFromIndex;
|
||||
int matches = 0;
|
||||
for (int i = startSearchFromIndex; i < size; i++) { // If the user knows the first index to be removed, we can skip a lot of unnecessary comparsions
|
||||
if (!c.contains(i)) {
|
||||
// TODO: It can be possible to optimize this loop by tracking the start/finish and then using arraycopy to "skip" the elements,
|
||||
// this would optimize cases where the index to be removed are far apart, HOWEVER it does have a big performance impact if you are doing
|
||||
// "arraycopy" for each element
|
||||
a[j++] = a[i];
|
||||
} else {
|
||||
matches++;
|
||||
}
|
||||
|
||||
if (matches == requiredMatches) { // Exit the loop if we already removed everything, we don't need to check anything else
|
||||
// We need to update the final size here, because we know that we already found everything!
|
||||
// Because we know that the size must be currentSize - requiredMatches (because we have matched everything), let's update the value
|
||||
// However, we need to copy the rest of the stuff over
|
||||
if (i != (size - 1)) { // If it isn't the last index...
|
||||
// i + 1 because we want to copy the *next* element over
|
||||
// and the size - i - 1 is because we want to get the current size, minus the current index (which is i), and then - 1 because we want to copy -1 ahead (remember, we are adding +1 to copy the *next* element)
|
||||
System.arraycopy(a, i + 1, a, j, size - i - 1);
|
||||
}
|
||||
j = size - requiredMatches;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Arrays.fill(a, j, size, null);
|
||||
size = j;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user