Extreme Editor Performance issues when viewing components that have prefab overrides in a scene.

Issue #733 open
Ryan Murphy created an issue

Bringing this over from Discord. Username Dracko22.

I am experiencing extreme slow down in editor on some components I have with many Odin rendered frields. Performance issues seem more common with lists being rendered. I have narrowed the performance issues down to If a Prefab is in a scene, AND the prefab has many modifications the editor becomes unusable when that object is selected and the inspector is rendering.

Unity 2019.4.16

Odin 3.0.1

OSX 11.1

I am not in Editor only mode

This issue has been around since early 2019 versions of unity and 2.0 version os Odin. We just now isolated it to editing components with Prefab Overrides in Scenes. To be clear this is an editor render performance, not a bug about prefab overrides not serializing properly, I know there are still some missing areas of support around that.

I believe to repro you would

  1. Create a prefab with components rendered by odin that have multiple fields including lists of objects
  2. Place the prefab in a scene
  3. Make many edits to the prefab in the scene but do not apply them to the prefab
  4. Note editor degregation

Here is an example of what I am talking about. The editor runs at about 1 fps or lower just sitting here, not interacting with anything.

Deep profile while in this state.


Here is a screenshot of a component that has many overrides that when view leads to bad performance and is what was viewed during the deep profile above. Also a sample screenshot of it in an endless list of prefab modification calls

This issue makes Odin pretty unusable inside of scenes and we have refactored much of our logic to try to work around these issues including making a custom class that allows us to turn on and off Odin on specific components while editing.

Comments (16)

  1. Joel McDonald

    Any updates on this, 3 months later? I’m seeing the same issue, on Unity 2019.4.22f1 and it’s seriously hurting our workflow.

    EDIT: BTW, I’m able to repro the issue without making a ton of edits/overrides. All it takes is a single edit such as overriding the mesh material for each of the objects in the prefab.

  2. Tor Esa Vestergaard

    Thanks for the reminder - this issue managed to get lost over christmas and I failed to pick it back up afterward. My apologies for that.

    As far as I can tell from the profiling data, Unity is giving us an array of about 5000 modifications made to the object that we then have to go through and process, and this profile snapshot lasts over two GUI events, so it happens twice here (likely just Layout → Repaint).

    However, I suspect we could invert the order of operations here so instead of proactively registering prefab modification entries with the properties they are applied to, the properties themselves can lazily fetch it on demand. The framerate will be very low regardless - Unity’s prefab API was simply not made to handle this amount of data efficiently. Merely the Unity level API call to get our hands on this data so we can even theoretically know what was modified is taking 55 ms out of this frame all by itself, and there will inevitably be just a little overhead to process all the data it returns. Even were I to cut this overhead down by a factor of 100-1000, which might be possible, you are still looking at a framerate of, at best, 10 FPS, likely closer to 5 FPS.

    I will certainly look at improving the performance of this part of the code, and hopefully I will have a build for you to try out soon, but I suggest you move some of your data elsewhere into InlineEditor’ed object references or otherwise split it up, or don’t rely on Odin in this one particular instance; it is a very extreme usecase that I do not believe it is feasible for us to handle with the way the prefab API is currently set up.

  3. Tor Esa Vestergaard

    One theory I just had that might make a difference, possibly, is to take the SerializedMonoBehaviour that contains all this data and implement the IOverridesSerializationFormat interface, then always return DataFormat.Binary from the GetFormatToSerializeAs(bool isPlayer) method.

    This will force the serializer to serialize everything into a single binary blob of data, which might make a difference, assuming that Unity is generating a massive delta over the serialized data that just changed a tiny bit from that one value changing because of the difference in internal reference counting and so on. Odin’s prefab serialization is set up to try to avoid this, and to delete those deltas when they happen, however that is no guarantee that it is not happening.

    As it said in the warnings you have clicked through to use this feature, Odin-serialized prefabs are officially a deprecated feature, and the only reason we are not removing them entirely is to prevent data loss, and so that people have time to migrate away from using them. Unity’s new nested prefab workflow is too unstable and unwieldy for us to plausibly support this Odin feature; it is not within our ability to do so, though we truly have tried our best and spent a great deal of effort in the attempt.

    I feel like I should reiterate that warning we display when you try to use this feature: if you use Odin-serialized prefabs, do not expect anything to work, do not expect your data to be safe, and when things break, do not expect us to be able to help you.

    I should also clarify though that this bug is not directly an Odin-serialized prefab issue, though it might indirectly be caused by such an issue. We provide full support for regular Unity-serialized prefabs, and it is certainly worth optimizing the part of the code that deals with that, so we will certainly be doing our best to deal with that part of the issue 🙂

  4. Joel McDonald

    Sorry I don’t know anything about Odin serialized prefabs--I’m pretty sure I’m not using that functionality. I’m just inheriting from MonoBehaviour. I don’t remember ever seeing a warning about Odin serialized prefabs either.

  5. Tor Esa Vestergaard

    I can see in the profiler data that the object which is causing this performance issue is a SerializedMonoBehaviour, IE, an Odin-serialized prefab.

    Edit: It furthermore seems to contain many BetterEvents instances, and these are also not meant for use with prefabs from what I know of the library.

  6. Joel McDonald

    I’m not the original person who posted this bug so it’s not my profiler data, I’m simply piggybacking off of the issue since I am seeing it as well. If I need to create a separate issue let me know. Or if you would like a repro of my situation I can also provide that I think.

  7. Tor Esa Vestergaard

    Ah! My apologies - in that case, yes, I would love to see some profiling data of the issue you are seeing.

  8. Joel McDonald

    Here’s the profiler data. (it’s not a deep profile. assuming you can turn on Call Stacks and check the Timeline but maybe not w/ saved data files?) https://www.dropbox.com/s/tym5f5556fou57m/odin %2B prefab issue - profile.zip?dl=0

    This test case is selecting 155 gameobjects that are part of the prefab and have their Mesh Renderer material overriden. And here’s what my inspector looks like. The Geo script is not changed/overridden at all but is the thing causing the slowdown. As soon as I ‘collapse’ the script it speeds up again.

  9. Tor Esa Vestergaard

    As I posted on #777: To give an update, we are still working on this, but solving it correctly and in a future-proof way is a problem of some algorithmic complexity, so we have not yet crafted a solution where we are happy with all the performance and memory characteristics.

  10. Tor Esa Vestergaard

    We’ve now totally rewritten the way we handle and register Unity PropertyModifications on prefab instances to be far (far!) faster, but this has required a rather large rewrite and refactor of some internal parts of the property system to use string slices (resulting in some very nice speed-ups and a complete elimination of garbage allocations re: property path lookups) as well as the development of a new custom string lookup data structure, so we would like to verify this solution with a number of users before introducing it into the stable branch of Odin. If anybody would like to try out this fix and verify its stability, please contact me on Discord and I will send you a preview build ASAP 🙂

    Edit: I should note that even with the fix, it will still be quite chunky in many cases and there are some cases where this won’t be fixed - this is inevitable because of the parts of Unity’s Prefab API that we have no choice but to invoke. However, Odin’s own part of the issue is now far faster. Once we receive the array of modifications from Unity, things go quickly from there, where-as before they would have been quite slow per modification. Getting the modifications array from Unity in the first place, though, cannot be sped up. It is possible that we can do some clever caching tricks, but that would be a great deal more work on its own.

  11. Tor Esa Vestergaard

    The afore-mentioned change has just been released in patch 3.0.6. I will leave this issue open, as I am hopeful that we can further address the performance problems by caching the property modification arrays we get from Unity and only updating them when we can prove that it is necessary to do so. If this second half of optimizations work out as I hope they will, we should be able to achieve fairly smooth performance in the editor even for prefabs with very large numbers of modifications.

  12. Joel McDonald

    Thanks for the updates. I just tried out 3.0.6 and unfortunately it doesn’t help my particular case yet, but like you said this could be intrinsic to Unity. I’ll keep following this thread for additional updates.

  13. Log in to comment