With about 1 million entities, my GhostSendSystem SerializeJob takes about 40-50 ms.
A breakdown of my entities when testing my 8192x8192 map:
- 900k Trees
-- Single float2 Ghosted (+ default stuff)
-- Archetype is 440 B
-- Static Optimization - 4k NPC Structures
-- Single float2 Ghosted (+ default stuff)
-- Archetype is 1.2 KB
-- Static Optimization - 50k NPCs
-- Single float2 Ghosted
-- Archetype is 6.5 KB (I need to debug why one of my BufferComps is 5.5 KB ...)
-- Dynamic Optimization
And here's the part where people will judge me:
- 16k Terrain Segments, each of which represents a 64x64 segment of the terrain.
-- Each of which has a Ghosted DynamicBuffer with 4096 elements in it, each with 1 ghosted byte
-- Archetype is only 740 B because the Buffer exceeds the allotted internal capacity and is off-chunk
-- Static Optimization and these currently never change, and only about 12-20 of these are Relevant to a given client at a time
ecuzzillo referred me to the optimization docs: https://docs.unity3d.com/Packages/com.unity.netcode@1.0/manual/optimizations.html
I'm already using GhostRelevancyMode.SetIsRelevant and I'm explicitly managing the Relevancy of ghosts. I confirmed that SetIsRelevant is enabled and I only have 400-1200 entities relevant at a time. The set of ghosts that are relevant only changes when a client moves their camera.
If I cut my generated map down to 4096x4096, my total entity count drops to ~250k and GhostSentSystem:SerializeJob Time drops to 12-15 ms. Though the number of relevant ghosts does not change when I lower the map size.
From the Docs:
Serialization cost
When a GhostField changes, we serialize the data and synchronize it over the network. If a job has write access to a GhostField, Netcode will check if the data changed. First, it serializes the data and compares it with the previous synchronized version of it. If the job did not change the GhostField, it discards the serialized result. For this reason, it is important to ensure that no jobs have write access to data if it will not change (to remove this hidden CPU cost).
It sounds like this Serialization Cost is present even when no client is eligible for receiving data.
I'm going to play around with some of the GhostSendSystemData config values to see if that helps, but I'm curious why the system is serializing and checking entities that are not relevant to any client?
Wow. Looks really complicated. I will wait official to solve scaling issue.