Private
Public Access
1
0

update perf logs, split OnParticleTick, add throttling

This commit is contained in:
2026-05-24 10:42:23 +02:00
parent 3fca34a009
commit a87825df6d
4 changed files with 96 additions and 34 deletions

View File

@@ -1,5 +1,5 @@
{ {
"total": 650000, "total": 656662,
"sessions": [ "sessions": [
{ {
"begin": "2026-01-09T17:26:02+01:00", "begin": "2026-01-09T17:26:02+01:00",
@@ -1495,6 +1495,11 @@
"begin": "2026-05-24T08:36:27+02:00", "begin": "2026-05-24T08:36:27+02:00",
"end": "2026-05-24T08:51:27+02:00", "end": "2026-05-24T08:51:27+02:00",
"duration": 900 "duration": 900
},
{
"begin": "2026-05-24T08:51:27+02:00",
"end": "2026-05-24T10:42:30+02:00",
"duration": 6662
} }
] ]
} }

View File

@@ -5,7 +5,7 @@ namespace OrekiWoofsBees.Common;
public static class DiagnosticsUtil public static class DiagnosticsUtil
{ {
public static void StopAndLogTime<T>( public static bool StopAndLogTime<T>(
this Stopwatch stopwatch, this Stopwatch stopwatch,
T instance, T instance,
double totalSecondsThreshold, double totalSecondsThreshold,
@@ -14,7 +14,11 @@ public static class DiagnosticsUtil
{ {
stopwatch.Stop(); stopwatch.Stop();
if (stopwatch.Elapsed.TotalSeconds >= totalSecondsThreshold) if (stopwatch.Elapsed.TotalSeconds >= totalSecondsThreshold)
{
instance.Mod?.Logger.Warning($"{typeof(T).Name}.{callerName} ({note}) took {stopwatch.Elapsed.TotalSeconds:F2}s"); instance.Mod?.Logger.Warning($"{typeof(T).Name}.{callerName} ({note}) took {stopwatch.Elapsed.TotalSeconds:F2}s");
return true;
}
return false;
} }
public static void LogTime<T>( public static void LogTime<T>(

View File

@@ -39,7 +39,12 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
private ClimateCondition? climate; private ClimateCondition? climate;
private Vec3d? windVec; private Vec3d? windVec;
private readonly Stopwatch stopwatch = new(); private int onParticleTickStopwatchTriggerCount;
private int spawnStopwatchTriggerCount;
private readonly Stopwatch plantInfoStopwatch = new();
private readonly Stopwatch particleStopwatch = new();
private readonly Stopwatch serverSpawnStopwatch = new();
private readonly Stopwatch handleSpawnStopwatch = new();
private readonly List<StructVec3i> flowerPositions = []; private readonly List<StructVec3i> flowerPositions = [];
private readonly List<StructVec3i> cropPositions = []; private readonly List<StructVec3i> cropPositions = [];
private readonly List<Vector3> relativePlantPositions = []; private readonly List<Vector3> relativePlantPositions = [];
@@ -47,7 +52,6 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
public const string TARGET_BEE_PARTICLE_COUNT_ATTRIBUTE = "roamingbees_targetBeeParticleCount"; public const string TARGET_BEE_PARTICLE_COUNT_ATTRIBUTE = "roamingbees_targetBeeParticleCount";
public const string RADIUS_ATTRIBUTE = "roamingbees_radius"; public const string RADIUS_ATTRIBUTE = "roamingbees_radius";
public const string NETWORK_CHANNEL_NAME = "bee particle spawns"; public const string NETWORK_CHANNEL_NAME = "bee particle spawns";
public const int SERVER_TICK_FREQUENCY_DECREASE = 50;
public int ActiveBeesCount => activeBees.Count; public int ActiveBeesCount => activeBees.Count;
public IEnumerable<BeeSpawnPacket> ActiveBeesPackets => activeBees.Select(x => x.SpawnPacket); public IEnumerable<BeeSpawnPacket> ActiveBeesPackets => activeBees.Select(x => x.SpawnPacket);
@@ -85,10 +89,25 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
plantPositionRegistry?.RegisterBeehive(Blockentity.Pos, radius); plantPositionRegistry?.RegisterBeehive(Blockentity.Pos, radius);
var updateFrequency = 20; var updateFrequency = 20;
if (api.Side == EnumAppSide.Server)
updateFrequency *= SERVER_TICK_FREQUENCY_DECREASE;
Blockentity.RegisterGameTickListener(OnParticleTick, updateFrequency); Blockentity.RegisterGameTickListener(OnParticleTick, updateFrequency);
Blockentity.RegisterGameTickListener(UpdateClimateInfo, 10000); Blockentity.RegisterGameTickListener(UpdateClimateInfo, 10000);
Blockentity.RegisterGameTickListener(DecreaseStopwatchCounts, 60000);
if (api.Side.IsServer())
{
Blockentity.RegisterGameTickListener(OnSpawnTick, 500);
Blockentity.RegisterGameTickListener(OnUpdatePlantInfoTick, 5000);
}
}
private void DecreaseStopwatchCounts(float dt)
{
if (spawnStopwatchTriggerCount > 10)
modSystem?.Mod.Logger.Warning($"{nameof(spawnStopwatchTriggerCount)} is {spawnStopwatchTriggerCount}");
spawnStopwatchTriggerCount = Math.Max(0, spawnStopwatchTriggerCount - 1);
if (onParticleTickStopwatchTriggerCount > 10)
modSystem?.Mod.Logger.Warning($"{nameof(onParticleTickStopwatchTriggerCount)} is {onParticleTickStopwatchTriggerCount}");
onParticleTickStopwatchTriggerCount = Math.Max(0, onParticleTickStopwatchTriggerCount - 1);
} }
private void UpdateClimateInfo(float dt) private void UpdateClimateInfo(float dt)
@@ -150,7 +169,7 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
public void HandleBeeParticleSpawn(BeeSpawnPacket packet, bool catchup = false) public void HandleBeeParticleSpawn(BeeSpawnPacket packet, bool catchup = false)
{ {
stopwatch.Restart(); handleSpawnStopwatch.Restart();
if (Blockentity.Pos != packet.HivePosition) if (Blockentity.Pos != packet.HivePosition)
return; return;
@@ -189,7 +208,7 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
for (var i = 0; i < totalDelta / 0.1f; i++) for (var i = 0; i < totalDelta / 0.1f; i++)
bee.Step(0.1f, 0.1f); // todo bee.Step(0.1f, 0.1f); // todo
} }
stopwatch.StopAndLogTime(this, 0.05); handleSpawnStopwatch.StopAndLogTime(this, 0.05);
} }
public void Clear() public void Clear()
@@ -204,12 +223,22 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
activeBees.Clear(); activeBees.Clear();
} }
private void OnParticleTick(float dt) private void OnUpdatePlantInfoTick(float dt)
{ {
if (Block is BlockSkep && !Config.Instance.EnableOnVanillaSkeps) if (!ShouldTick())
return; return;
stopwatch.Restart(); plantInfoStopwatch.Restart();
UpdatePlantInfo();
var note = $"global bees: {modSystem?.GlobalActiveBees}, registered hives: {modSystem?.BeeSpawnPacketDistributor?.SpawnHandlersCount}, radius: {Config.Instance.BeeRoamingRadius}";
plantInfoStopwatch.StopAndLogTime(this, 0.1, note);
}
private bool ShouldTick()
{
if (Block is BlockSkep && !Config.Instance.EnableOnVanillaSkeps)
return false;
var isFgc = Block?.Code?.Domain == "fromgoldencombs"; var isFgc = Block?.Code?.Domain == "fromgoldencombs";
var path = Block?.Code?.Path ?? string.Empty; var path = Block?.Code?.Path ?? string.Empty;
var isFgcLangstroth = isFgc && path.Contains("langstrothstack", StringComparison.OrdinalIgnoreCase); var isFgcLangstroth = isFgc && path.Contains("langstrothstack", StringComparison.OrdinalIgnoreCase);
@@ -218,22 +247,37 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
if (isFgcLangstroth) if (isFgcLangstroth)
{ {
if (!Config.Instance.EnableOnFgcLangstroth) if (!Config.Instance.EnableOnFgcLangstroth)
return; return false;
if (!HasRequiredLangstrothBase()) if (!HasRequiredLangstrothBase())
return; return false;
} }
if (isFgcCeramic && !Config.Instance.EnableOnFgcCeramic) if (isFgcCeramic && !Config.Instance.EnableOnFgcCeramic)
return false;
return true;
}
private void OnParticleTick(float dt)
{
if (!ShouldTick())
return; return;
var isFgc = Block?.Code?.Domain == "fromgoldencombs";
var path = Block?.Code?.Path ?? string.Empty;
var isFgcLangstroth = isFgc && path.Contains("langstrothstack", StringComparison.OrdinalIgnoreCase);
var isFgcCeramic = isFgc && path.Contains("ceramicbroodpot", StringComparison.OrdinalIgnoreCase);
particleStopwatch.Restart();
entityAttributeSnapshot.Clear(); entityAttributeSnapshot.Clear();
Blockentity.ToTreeAttributes(entityAttributeSnapshot); Blockentity.ToTreeAttributes(entityAttributeSnapshot);
var targetBeeParticleCount = GetTargetBeeParticleCountFromBlockEntity(); var targetBeeParticleCount = GetTargetBeeParticleCountFromBlockEntity();
if (targetBeeParticleCount <= 0) TargetParticleCount = Math.Max(0, targetBeeParticleCount);
if (TargetParticleCount <= 0)
return; return;
TargetParticleCount = Math.Max(0, targetBeeParticleCount);
if (Block is BlockSkep) if (Block is BlockSkep)
TargetParticleCount = Config.Instance.RoamingBeesPerVanillaSkep; TargetParticleCount = Config.Instance.RoamingBeesPerVanillaSkep;
if (isFgcLangstroth) if (isFgcLangstroth)
@@ -241,14 +285,9 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
if (isFgcCeramic) if (isFgcCeramic)
TargetParticleCount = Config.Instance.RoamingBeesPerFgcCeramic; TargetParticleCount = Config.Instance.RoamingBeesPerFgcCeramic;
if (Api.Side == EnumAppSide.Server)
{
UpdatePlantInfo();
stopwatch.LogTime(this, 0.05, "after UpdatePlantInfo");
}
Update(dt); Update(dt);
stopwatch.StopAndLogTime(this, 0.05); if (particleStopwatch.StopAndLogTime(this, 0.1, note: $"global bees: {modSystem?.GlobalActiveBees}, registered hives: {modSystem?.BeeSpawnPacketDistributor?.SpawnHandlersCount}"))
onParticleTickStopwatchTriggerCount++;
} }
private void Update(float dt) private void Update(float dt)
@@ -265,7 +304,10 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
temperature = climate?.Temperature ?? 20f; temperature = climate?.Temperature ?? 20f;
// iterate from end to easily remove from list // iterate from end to easily remove from list
for (int i = activeBees.Count - 1; i >= 0; i--) var end = activeBees.Count - 1;
end -= onParticleTickStopwatchTriggerCount * 10;
for (int i = end; i >= 0; i--)
{ {
var bee = activeBees[i]; var bee = activeBees[i];
@@ -276,10 +318,7 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
BeeVisualParticleRenderer.Spawn(clientWorld, Blockentity.Pos, bee); BeeVisualParticleRenderer.Spawn(clientWorld, Blockentity.Pos, bee);
} }
if (Api.Side == EnumAppSide.Server) if (Api.Side == EnumAppSide.Server)
{ bee.Step(dt, windSpeed);
for (var j = 0; j < SERVER_TICK_FREQUENCY_DECREASE; j++)
bee.Step(dt / SERVER_TICK_FREQUENCY_DECREASE, windSpeed);
}
if (bee.ShouldBeDespawned && modSystem != null) if (bee.ShouldBeDespawned && modSystem != null)
{ {
@@ -289,12 +328,28 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
} }
TimeSinceLastSpawn += dt; TimeSinceLastSpawn += dt;
if (Api.Side == EnumAppSide.Server) }
private void OnSpawnTick(float dt)
{
if (!ShouldTick())
return;
if (climate is null || windVec is null)
return;
serverSpawnStopwatch.Restart();
TrySpawnNewBee(TargetParticleCount); TrySpawnNewBee(TargetParticleCount);
if (serverSpawnStopwatch.StopAndLogTime(this, 0.1))
spawnStopwatchTriggerCount++;
} }
private void TrySpawnNewBee(int targetParticleCount) private void TrySpawnNewBee(int targetParticleCount)
{ {
int desiredParticleCount = targetParticleCount;
if (activeBees.Count >= desiredParticleCount)
return;
if (TimeSinceLastSpawn < spawn_cooldown_seconds) if (TimeSinceLastSpawn < spawn_cooldown_seconds)
return; return;
@@ -305,7 +360,7 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
var sunPos = Api.World.Calendar.GetSunPosition(new Vec3d(Blockentity.Pos.X, Blockentity.Pos.Y, Blockentity.Pos.Z), Api.World.Calendar.TotalDays); var sunPos = Api.World.Calendar.GetSunPosition(new Vec3d(Blockentity.Pos.X, Blockentity.Pos.Y, Blockentity.Pos.Z), Api.World.Calendar.TotalDays);
float sunAltitudeDegrees = MathF.Asin(sunPos.Y) * 180f / GameMath.PI; float sunAltitudeDegrees = MathF.Asin(sunPos.Y) * 180f / GameMath.PI;
if (sunPos.Y <= cfg.SunAltitudeMinDegrees) if (sunAltitudeDegrees <= cfg.SunAltitudeMinDegrees)
return; return;
if (rainfall >= cfg.RainfallSpawnStopThreshold) if (rainfall >= cfg.RainfallSpawnStopThreshold)
@@ -318,10 +373,6 @@ public class BlockEntityBehaviorRoamingBees(BlockEntity blockEntity) : BlockEnti
if (modSystem.GlobalActiveBees >= maxGlobal) if (modSystem.GlobalActiveBees >= maxGlobal)
return; return;
int desiredParticleCount = targetParticleCount;
if (activeBees.Count >= desiredParticleCount)
return;
float sunAltitudeModifier = 1 - Math.Clamp((sunAltitudeDegrees - cfg.SunAltitudeMinDegrees) / cfg.SunAltitudeRangeDegrees, 0f, 1f); float sunAltitudeModifier = 1 - Math.Clamp((sunAltitudeDegrees - cfg.SunAltitudeMinDegrees) / cfg.SunAltitudeRangeDegrees, 0f, 1f);
float sunAltitudeCooldownPenalty = sunAltitudeModifier * cfg.MaxSunAltitudeCooldownPenalty; float sunAltitudeCooldownPenalty = sunAltitudeModifier * cfg.MaxSunAltitudeCooldownPenalty;

View File

@@ -17,6 +17,8 @@ internal class BeeSpawnPacketDistributor(RoamingBeesModSystem modSystem, EnumApp
private Dictionary<Vector3, IBeeSpawnHandler> spawnHandlers { get; } = []; private Dictionary<Vector3, IBeeSpawnHandler> spawnHandlers { get; } = [];
private Dictionary<Vector3, IBeeSpawnCatchup> catchupHandlers { get; } = []; private Dictionary<Vector3, IBeeSpawnCatchup> catchupHandlers { get; } = [];
public int SpawnHandlersCount => spawnHandlers.Count;
public void Register(BlockPos position, object manager) public void Register(BlockPos position, object manager)
{ {
if (manager is IBeeSpawnHandler spawnHandler) if (manager is IBeeSpawnHandler spawnHandler)