Skip to content
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

Convert "Mode" classes to abstract enums. #48

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

player-03
Copy link
Contributor

These classes are basically enums already, just without the benefits. This change should have zero impact on performance or existing code, it'll just make new code a bit simpler.

@dimensionscape
Copy link
Member

Just a minor note: Haxe enums are on average 10-40% slower than static inline vars, because they're runtime Objects as opposed to compile time constants.

Typically this doesn't matter unless the enum is being used repeatedly in performance critical operations, but there are definitely times that it's more beneficial to use static inlines over enums. The benefits of using an enum do not come without additional overhead in almost all use cases.

@player-03 player-03 changed the title Convert "Mode" classes to enums. Convert "Mode" classes to abstract enums. Apr 26, 2023
@player-03
Copy link
Contributor Author

But abstract enums are fine, right?

@dimensionscape
Copy link
Member

They're still slower, I just wanted to point that out. But in this case, the change probably outweighs the cost.

@player-03
Copy link
Contributor Author

player-03 commented Apr 26, 2023

On Try Haxe, it literally just inlines the variables. How is it slower?

Edit: https://haxe.org/manual/types-abstract-enum.html

@dimensionscape
Copy link
Member

dimensionscape commented Apr 26, 2023

Its a little bit more complicated than that. Even though it attempts to inline them whenever possible, the compiler generates less optimized code in many cases when using an enum abstract. I think it has something to do with the analyzer. If you compare some more complicated code, you will see that it optimizes the static inline var usage more often, even though they are virtually the same, theoretically.

@dimensionscape
Copy link
Member

dimensionscape commented Apr 26, 2023

For example, here is the generated code(with the analyzer on) of two identical functions, the only difference being one uses an abstract enum value and the other uses a static inline var. The compiler allows unnecessary code(and memory allocations) to run in the former function.
image

And Javascript gets the better of it because it is not strictly typed like C++, where I notice it is often worse.

This is a really bad real world example(https://try.haxe.org/#636458B1), but I was using it to test different targets locally with and without the analyzer. In try.haxe, with the analyzer optimization, the abstract enum test always finishes slower by a decent margin, despite the code being basically identical.

But once again, I'm not saying we shouldn't do it, only that it seemed like the perfect opportunity to maybe mention the ramifications. Its an issue I've run into in the past when writing my server framework, where every millisecond of cpu time reduction is literally tons of money saved at scale. I just never really talked about it before.

@player-03
Copy link
Contributor Author

Interesting. Thanks for the sample!

I spotted two code structures that caused a discrepancy. First, declaring a local variable that later gets reassigned. (Which is also known to break constructor inlining, and I doubt that's a coincidence.) Second, using a switch statement, on some targets. Guess the analyzer still has a little ways to go.

I don't recall Away3D doing either of those things, and even if it did, this isn't performance-critical code.

And Javascript gets the better of it because it is not strictly typed like C++, where I notice it is often worse.

The only C++-specific difference I noticed was the switch statement thing. It kept track of types just fine.

But once again, I'm not saying we shouldn't do it, only that it seemed like the perfect opportunity to maybe mention the ramifications.

Yeah, this was a good time for it. And now I know to keep an eye out for it in performance-critical sections.

@dimensionscape
Copy link
Member

The only C++-specific difference I noticed was the switch statement thing. It kept track of types just fine.

I mean, the analyzer and code generation proficiency in general, not necessarily the example. There are some practices that generate very obtuse C++ that runs slower than its JS counterpart generation, although its not easy to predict or determine what pattern is causing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants