New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove reflection #44
Conversation
Thanks! Looks great :) So it's actually a bit faster than the current version that uses "type magic" under the hood. This is great ^^ The main advantage of managed structs and classes is their "easy" usage... there are some cases where the user does not want to write boilerplate code for converting existing courses to components, indexes, and containers. This could probably scare some people away since they will need to write more boilerplate code to reach their goal. So I wonder if its possible to combine both ways and if its worth it. By a flag or combined API. Unity for example has the mechanic of "ObjectComponents" which are basically classes and structs with managed references. We could theoretically do the same, without losing performance... while maintaining flexibility for some scenarios.
Thats also sounding pretty nice ^^ Probably there could be even some sort of inbuild lookup mechanism which helps to map the index of an sprite, string e.g. to its class, without forcing the user to do it himself. |
Somebody already answered to this question :D
It's pretty close to the Bevy Handles concept and I really like it, |
I see, that's actually very close to those So there actually like three ways for providing managed struct or class support.
I think the first one is not worth it, since it causes the most work and could be a nightmare to maintain.
This will be merged, however, it will still take some time. Im currently working on the documentation on the |
I definitely prefer the
|
Well in that case we should create a issue for it :) Should we probably wait for the handle api before merging this ? |
I think this is up to you :) |
In this case, i think its the best to wait till I finally finished the code style rework ^^ ( Which is hella annoying ). Out of curiosity, could the Is the PR approach really faster compared to the previous reflection one ?Is it possible that the speed advantage came from component restructuring instead of reflection removal ? In your updated I assume that the PR and the master actually perform similar when both use the same technique. Could such
|
I actually found a memory overlap somewhere in the code. |
Well that's right, but using a Atleast in theory,
This however looks incredible... probably a bit "too" good :D C# should not really treat a raw So Im curious why exactly the PR is "faster" and if it really is, or if we probably misunderstand something ^^
Have you probably looked into benchmarking the versions to see how they perform under heavy load ?
|
Looks like I fall into the hell. During the development of this PR I tried to replace the |
Is it probably a padding problem ? I ran into this problem a lot since c#/c++ will automatic add padding bytes to make it fit the registers better. If the types of the 32 bytes struct arent aligned properly, it will add a few bytes which results in wrong sizes.
This is hella work ^^ Furthermore it would remove flexbility. There many many usecases where its great to e.g. create entities by types instead generics. For example custom serialization. I actually planned to add |
Closed as not applicable |
Main
To follow the project phylosophy, this PR aims to make Arch faster.
As discussed in #40 Arch still using Reflection and an unconventional components access with the
Unsafe.As<T>
API.The solution: use a bytes buffer
The
Archetype
class accepts a set ofComponents
which the corrispective types are unknown at compile time and the opaqueArray
class get casted to a specific type using theUnsafe.As<T>
API with some magic.I replaced the
Array
with the following implementationhttps://github.com/andreakarasho/Arch/blob/remove-reflection/Arch/Core/Chunk.cs#L12-L28
The hack is to use a
byte[sizeof(T) * Capacity]
array to store the components set.In this way we can cast our components using the
MemoryMarshal.Cast<byte, TComponent>
API which garantees aO(1)
operation.No managed references declared as struct field
Solution: usually ECS components contains an index to the managed resource
About the
string
type I think to implement a struct which will handle the implicit convertion to unmanaged memory automatically. Something like inflecs-cs
:Reference: https://github.com/flecs-hub/flecs-cs/blob/main/src/cs/production/Flecs/flecs.cs#L11708-L11937
No
class
componentsI don't consider this a bad thing actually. I don't see a valid reason to use
class
components becase they cause addresses jump). Sostruct
is the way to go!Unity discourages the
class
usage too: https://docs.unity3d.com/Packages/com.unity.entities@0.16/manual/component_data.html#managed-icomponentdataThe sample
No reflection sample
Arch.Sample.NoReflection.mp4
(The initial fps drops was due to a misslick to the tiltle bar during the video recording)
Current
master
Arch.Samples.WithReflection.mp4
TODO