#Spawing Performance
1 messages · Page 1 of 1 (latest)
yeah it's as i thought, you haven't bursted compiled your system
you're missing [BurstCompile] OnUpdate
[BurstCompile] on the struct does nothing (this only works on jobs)
i see you have tried to burst compile the specific function
I need to read up on that
I did try spamming it on every class/struct and method before though
never seemed to make a difference, in fact I got the same timings without any [BurstCompile]
~200ms with Burst->Enable Compilation off
~40ms with it on
do you have safety off?
(side note, Profiler.Begin sample doesn't work in burst - you need to use profile markers)
Ok, I replaced those
Safety also doesn't seem to make a difference
I'm new to Unity, but have used profilers like these in C++ before
Seems to me there's simply one malloc happening per entity when spawning or deleting all entities, I've not found any method that does not do that
Maybe this is just my machine? Using Unity 6 (6000.0.37f1)
I'd be interested (assuming you Instantiate in a similar way) what your profiler says for the when hovering over any allocs -> UnsafeUtility.Malloc/Free X instances on thread
The blue on the right is my InitJob, which is quite fast
https://discussions.unity.com/t/when-where-and-why-to-put-burstcompile-with-mild-under-the-hood-explanation/896228
I don't need [BurstCompile] it seems
SystemBase / ISystem → .Run / .Schedule / .ScheduleParallel - Burst Compiled by default, no need to mark static methods if those are called from ForEach / IJobs (in some cases would actually throw errors!). Unless .WithoutBurst()
Static methods can be burst compiled even when called outside Entities context when marked as [BurstCompile] (-> results in a function pointer)
Jobs can be marked with [BurstCompile] to be bursted from non-system context;
If in doubt - check Burst Inspector.
The blue on the right is my InitJob, which is quite fast
blue means its not burst compiled
burst compiled is green
blue is mono
also what od you mean you don't need [BurstCompile]
what's just saying is you don't need to mark a method that's in burst already with burst
[BurstCompile] // this is required
public void OnUpdate(ref SystemState state)
{
SomeOtherMethod();
}
[BurstCompile] // this is not required
private static void SomeOtherMethod()```
do you have a dynamic buffer on your archetype?
(i didn't have 100k allocations, it was like 25 or something)
I'll see if I can test it with an entity created from code tomorrow, maybe it's something weird with baking
thanks a lot for your input until now
mines from baking
is the top archetype the one you're instantiating
i actually suspect it has to allocate the linkedentitygroup buffer
i'm running a forked entities which stops forcing this buffer on unless required
https://github.com/tertle/com.unity.entities
you can give it a try to see if it makes a difference, i would be interested
It's both, since the MeshLODGroupComponent entity needs the children entities
Seems plausible, but I thought testing it with a simple cube would do it, that still did many 100k mallocs though
nope, the thing i dislike about default implementation is it forces LEG even with no hierarchy
it's pointless to me
(it also forces dynamic transform which i dont always want)
what's LEG?
I'm pretty sure that for my project I'm going to create a custom LOD implementation as well
Pretty sure I can do it with very few components
I'd also like to implement a system where I can render prop meshes attached to entities without those props needing to exist as entities
Probably requires a custom renderer anyway
Probably also not going to use baking, since I want to load assets at runtime, for user generated content
LinkedEntityGroup
got cha
Only 23 Mallocs when I do CreateEntity(prefab_arch, s.SpawnCount, Allocator.Temp) with prefab_arch = CreateArchetype(typeof(LocalTransform))
So it really is due to something in the Prefab Entity
yeah which is what i've been suggesting
it's most likely the LEG
Did you have any expectation that [EntityIndexInQuery] should only match your recently spawned entities by that system?
We already have the entity array after bulk instantiation, we can directly process that array via IJobFor rather than using IJE.
We already have the entity array after bulk instantiation, we can directly process that array via IJobFor rather than using IJE
yeah but then you have to use lookups
and risk doing work on the same chunk across multiple threads
it only took me 0.2ms to initialize the localtransform data in 100k entities in IJE
i didnt bother posting it because he didn't seem to have issues with that
If we use a initialization component to filter the entites on that chunk, would it be slower?
i don't think so as these entities will all be created in the same chunks if i recall
and not added to existing chunks
so the whole chunk will always be enabled avoiding having to check the actual individual entity bits
What if the component is enableable?
that's exactly what i just replied about
sorry when you said intialization i just assumed enableable
Me too
I have a problem understanding this
say you have 1 entity in a chunk
and you call bulk instantiate and create 50 more entities
i don't believe these 50 entities will be put in the existing chunk
and instead all be put in a new chunk
(it's been a long time since i looked at source code, so there is a chance this would have changed, however i believe it remains true)
so you'll have 2 chunks now
1 with 1 entity
1 with 50 entities
the 50 entities will all have their initialization component enabled, so it doesn't need to do enable component checks
it just goes through the fast path of iterating them all
(bulk instantiate is one of the reason fragmentation can occur i believe, the other more critical one is chunk components)
(that said, we should test this again been ages)
interesting, thanks again
No, I ignored getting that right for the time being
Does the system leave holes at the end of chunks when destroying entities, or just at the last chunk (does it swap in within a chunk or from different chunks)
If bulk CreateEntity/Instantiate always create 'contiguous' entities I imagine IJobFor would be fine, it would just repeat the lookup per entity like you said
(though I don't understand yet how to get around the This container does not support parallel writing)
Surely simply writing normal component data from threads is perfectly fine
Holes will always fill
If you go look at manual chunk and component iteration you get a linear array of data
If there were holes you'd have issues
But a chunk won't get filled from another chunk if you destroy an entity
so bulk CreateEntity in theory could return a list of chunks that each have arrays of contiguous new entities
I've only gotten IJobEntity to work for initialization, I'm actually completely lost on how to do it with IJobFor, I always get 'does not support parallel writing'
Why is this a thing? The lookup Entity->memory address of its component should be perfectly safe, right?
You just need to be careful not to write to the same entity from two threads at once like aways with multithreading, is unity trying to prevent user mistakes?
Yes but unity didn't know you aren't accessing the same entity in multiple threads
You have to promise it that your aren't then you can do it
With the disable parallel write safety attribute
Ije is going to be faster here anyway
Did you have any expectation that [EntityIndexInQuery] should only match your recently spawned entities by that system?
It has this issue though, Should I use a temporary Init Tag?
yeah can use an enable component or just add it to all missing objects vs a build query operation which is super fast
I can't seem to easily find info on this?
Would you like to link me an example?
The idea is to allow to query exactly the newly spawned entities by using a empty component = tag for this
but if you need to remove this after that causes structural changes (even for tags?), so instead we use enable components, which can be disabled?
better off doing the opposite imo as you dont have to worry about adding it via baking (thought here are merits of doing it how you suggest)
can just put a component inside the system hidden from world
private struct Initialized : IComponentData {}
and just add it to things that don't have it
and query on that
alternative you can add an enablable component to the entities in baking
and then disable/enable it in the initialization
both have pros/cons