Files
ss14-wl/Content.Benchmarks/PvsBenchmark.cs
Dmitry 25c5e59248 Upstream (#3172)
Signed-off-by: Prole <172158352+Prole0@users.noreply.github.com>
Co-authored-by: PJBot <pieterjan.briers+bot@gmail.com>
Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>
Co-authored-by: Samuka-C <47865393+Samuka-C@users.noreply.github.com>
Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
Co-authored-by: Partmedia <kevinz5000@gmail.com>
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Co-authored-by: themias <89101928+themias@users.noreply.github.com>
Co-authored-by: Victor Shen <71985089+Vexerot@users.noreply.github.com>
Co-authored-by: Ed <96445749+TheShuEd@users.noreply.github.com>
Co-authored-by: Milon <milonpl.git@proton.me>
Co-authored-by: Kirus59 <145689588+Kirus59@users.noreply.github.com>
Co-authored-by: Nemanja <98561806+EmoGarbage404@users.noreply.github.com>
Co-authored-by: Stomf <5dorkydorks@gmail.com>
Co-authored-by: drakewill-CRL <46307022+drakewill-CRL@users.noreply.github.com>
Co-authored-by: PraxisMapper <praxismapper@gmail.com>
Co-authored-by: EmoGarbage404 <retron404@gmail.com>
Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com>
Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com>
Co-authored-by: IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com>
Co-authored-by: TytosB <54259736+TytosB@users.noreply.github.com>
Co-authored-by: abadaba695 <spacestation13thingy@gmail.com>
Co-authored-by: kosticia <kosticia46@gmail.com>
Co-authored-by: Thinbug <101073555+Thinbug0@users.noreply.github.com>
Co-authored-by: pathetic meowmeow <uhhadd@gmail.com>
Co-authored-by: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com>
Co-authored-by: Boaz1111 <149967078+Boaz1111@users.noreply.github.com>
Co-authored-by: ActiveMammmoth <140334666+ActiveMammmoth@users.noreply.github.com>
Co-authored-by: Myra <vasilis@pikachu.systems>
Co-authored-by: Whatstone <166147148+whatston3@users.noreply.github.com>
Co-authored-by: Pieter-Jan Briers <pieterjan.briers+git@gmail.com>
Co-authored-by: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com>
Co-authored-by: Gentleman-Bird <dcgreen406@gmail.com>
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
Co-authored-by: BIGZi0348 <svalker0348@gmail.com>
Co-authored-by: LaCumbiaDelCoronavirus <90893484+LaCumbiaDelCoronavirus@users.noreply.github.com>
Co-authored-by: imatsoup <93290208+imatsoup@users.noreply.github.com>
Co-authored-by: Matthew Herber <32679887+happyrobot33@users.noreply.github.com>
Co-authored-by: Ertanic <36124833+Ertanic@users.noreply.github.com>
Co-authored-by: MissKay1994 <15877268+MissKay1994@users.noreply.github.com>
Co-authored-by: Errant <35878406+Errant-4@users.noreply.github.com>
Co-authored-by: eoineoineoin <helloworld@eoinrul.es>
Co-authored-by: Tiniest Shark <head.rebel@yahoo.com>
Co-authored-by: nikitosych <boriszyn@gmail.com>
Co-authored-by: Tayrtahn <tayrtahn@gmail.com>
Co-authored-by: Perry Fraser <perryprog@users.noreply.github.com>
Co-authored-by: YoungThug <ramialanbagy@gmail.com>
Co-authored-by: beck-thompson <107373427+beck-thompson@users.noreply.github.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
Co-authored-by: Southbridge <7013162+southbridge-fur@users.noreply.github.com>
Co-authored-by: Vladislav Suchkov <20380250+murolem@users.noreply.github.com>
Co-authored-by: Prole <172158352+Prole0@users.noreply.github.com>
Co-authored-by: Unkn0wn_Gh0st <shadowstalkermll@gmail.com>
Co-authored-by: 3nderall <101940324+3nderall@users.noreply.github.com>
Co-authored-by: Radezolid <snappednexus@gmail.com>
Co-authored-by: J <billsmith116@gmail.com>
Co-authored-by: Ghagliiarghii <68826635+Ghagliiarghii@users.noreply.github.com>
Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com>
Co-authored-by: youtissoum <51883137+youtissoum@users.noreply.github.com>
Co-authored-by: Minemoder5000 <minemoder50000@gmail.com>
Co-authored-by: Spanky <scott@wearejacob.com>
Co-authored-by: Spessmann <156740760+Spessmann@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: brainfood1183 <113240905+brainfood1183@users.noreply.github.com>
Co-authored-by: Deerstop <edainturner@gmail.com>
Co-authored-by: B_Kirill <153602297+B-Kirill@users.noreply.github.com>
Co-authored-by: archee1 <archee3@hotmail.co.uk>
Co-authored-by: Cojoke <83733158+Cojoke-dot@users.noreply.github.com>
Co-authored-by: Quantum-cross <7065792+Quantum-cross@users.noreply.github.com>
Co-authored-by: poklj <compgeek223@gmail.com>
Co-authored-by: Krunklehorn <42424291+Krunklehorn@users.noreply.github.com>
Co-authored-by: OnyxTheBrave <131422822+OnyxTheBrave@users.noreply.github.com>
Co-authored-by: UpAndLeaves <92269094+Alpha-Two@users.noreply.github.com>
Co-authored-by: Flareguy <78941145+Flareguy@users.noreply.github.com>
Co-authored-by: Zalycon <84675130+Zalycon@users.noreply.github.com>
Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com>
Co-authored-by: Verm <32827189+Vermidia@users.noreply.github.com>
Co-authored-by: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com>
Co-authored-by: ScarKy0 <scarky0@onet.eu>
Co-authored-by: Dmitry <57028746+dimm00n@users.noreply.github.com>
2025-05-24 11:00:17 +03:00

179 lines
6.0 KiB
C#

#nullable enable
using System;
using System.Linq;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Content.IntegrationTests;
using Content.IntegrationTests.Pair;
using Content.Server.Mind;
using Content.Server.Warps;
using Content.Shared.Warps;
using Robust.Shared;
using Robust.Shared.Analyzers;
using Robust.Shared.EntitySerialization;
using Robust.Shared.EntitySerialization.Systems;
using Robust.Shared.GameObjects;
using Robust.Shared.Map;
using Robust.Shared.Player;
using Robust.Shared.Random;
using Robust.Shared.Utility;
namespace Content.Benchmarks;
// This benchmark probably benefits from some accidental cache locality. I,e. the order in which entities in a pvs
// chunk are sent to players matches the order in which the entities were spawned.
//
// in a real mid-late game round, this is probably no longer the case.
// One way to somewhat offset this is to update the NetEntity assignment to assign random (but still unique) NetEntity uids to entities.
// This makes the benchmark run noticeably slower.
[Virtual]
public class PvsBenchmark
{
public const string Map = "Maps/box.yml";
[Params(1, 8, 80)]
public int PlayerCount { get; set; }
private TestPair _pair = default!;
private IEntityManager _entMan = default!;
private ICommonSession[] _players = default!;
private EntityCoordinates[] _spawns = default!;
public int _cycleOffset = 0;
private SharedTransformSystem _sys = default!;
private EntityCoordinates[] _locations = default!;
[GlobalSetup]
public void Setup()
{
#if !DEBUG
ProgramShared.PathOffset = "../../../../";
#endif
PoolManager.Startup();
_pair = PoolManager.GetServerClient().GetAwaiter().GetResult();
_entMan = _pair.Server.ResolveDependency<IEntityManager>();
_pair.Server.CfgMan.SetCVar(CVars.NetPVS, true);
_pair.Server.CfgMan.SetCVar(CVars.ThreadParallelCount, 0);
_pair.Server.CfgMan.SetCVar(CVars.NetPvsAsync, false);
_sys = _entMan.System<SharedTransformSystem>();
SetupAsync().Wait();
}
private async Task SetupAsync()
{
// Spawn the map
_pair.Server.ResolveDependency<IRobustRandom>().SetSeed(42);
await _pair.Server.WaitPost(() =>
{
var path = new ResPath(Map);
var opts = DeserializationOptions.Default with {InitializeMaps = true};
if (!_entMan.System<MapLoaderSystem>().TryLoadMap(path, out _, out _, opts))
throw new Exception("Map load failed");
});
// Get list of ghost warp positions
_spawns = _entMan.AllComponentsList<WarpPointComponent>()
.OrderBy(x => x.Component.Location)
.Select(x => _entMan.GetComponent<TransformComponent>(x.Uid).Coordinates)
.ToArray();
Array.Resize(ref _players, PlayerCount);
// Spawn "Players"
_players = await _pair.Server.AddDummySessions(PlayerCount);
await _pair.Server.WaitPost(() =>
{
var mind = _pair.Server.System<MindSystem>();
for (var i = 0; i < PlayerCount; i++)
{
var pos = _spawns[i % _spawns.Length];
var uid =_entMan.SpawnEntity("MobHuman", pos);
_pair.Server.ConsoleHost.ExecuteCommand($"setoutfit {_entMan.GetNetEntity(uid)} CaptainGear");
mind.ControlMob(_players[i].UserId, uid);
}
});
// Repeatedly move players around so that they "explore" the map and see lots of entities.
// This will populate their PVS data with out-of-view entities.
var rng = new Random(42);
ShufflePlayers(rng, 100);
_pair.Server.PvsTick(_players);
_pair.Server.PvsTick(_players);
var ents = _players.Select(x => x.AttachedEntity!.Value).ToArray();
_locations = ents.Select(x => _entMan.GetComponent<TransformComponent>(x).Coordinates).ToArray();
}
private void ShufflePlayers(Random rng, int count)
{
while (count > 0)
{
ShufflePlayers(rng);
count--;
}
}
private void ShufflePlayers(Random rng)
{
_pair.Server.PvsTick(_players);
var ents = _players.Select(x => x.AttachedEntity!.Value).ToArray();
var locations = ents.Select(x => _entMan.GetComponent<TransformComponent>(x).Coordinates).ToArray();
// Shuffle locations
var n = locations.Length;
while (n > 1)
{
n -= 1;
var k = rng.Next(n + 1);
(locations[k], locations[n]) = (locations[n], locations[k]);
}
_pair.Server.WaitPost(() =>
{
for (var i = 0; i < PlayerCount; i++)
{
_sys.SetCoordinates(ents[i], locations[i]);
}
}).Wait();
_pair.Server.PvsTick(_players);
}
/// <summary>
/// Basic benchmark for PVS in a static situation where nothing moves or gets dirtied..
/// This effectively provides a lower bound on "real" pvs tick time, as it is missing:
/// - PVS chunks getting dirtied and needing to be rebuilt
/// - Fetching component states for dirty components
/// - Compressing & sending network messages
/// - Sending PVS leave messages
/// </summary>
[Benchmark]
public void StaticTick()
{
_pair.Server.PvsTick(_players);
}
/// <summary>
/// Basic benchmark for PVS in a situation where players are teleporting all over the place. This isn't very
/// realistic, but unlike <see cref="StaticTick"/> this will actually also measure the speed of processing dirty
/// chunks and sending PVS leave messages.
/// </summary>
[Benchmark]
public void CycleTick()
{
_cycleOffset = (_cycleOffset + 1) % _players.Length;
_pair.Server.WaitPost(() =>
{
for (var i = 0; i < PlayerCount; i++)
{
_sys.SetCoordinates(_players[i].AttachedEntity!.Value, _locations[(i + _cycleOffset) % _players.Length]);
}
}).Wait();
_pair.Server.PvsTick(_players);
}
}