-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
ECS: Use fxhash in TypeIdMap. #1119
Conversation
benchmarks I made is here: #1097 (comment) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be worth doing some whole system performance analysis of how much impact this has by using a Hash implementation that's quite slow (i.e. using Ahmdal's law).
@@ -20,6 +20,7 @@ trace = [] | |||
bevy_tasks = { path = "../bevy_tasks", version = "0.4.0" } | |||
bevy_utils = { path = "../bevy_utils", version = "0.4.0" } | |||
bevy_ecs_macros = { path = "macros", version = "0.4.0" } | |||
fxhash = "0.2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to use fx_hash
? In bevy_util
we are already set up for using ahash
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See reasoning #1119 (comment)
Also fxhash used by other dependencies so it needs to be compiled anyway.
/// which hashbrown needs), there is no need to hash it again. Instead, this uses the much | ||
/// faster no-op hash. | ||
pub(crate) type TypeIdMap<V> = HashMap<TypeId, V, BuildHasherDefault<TypeIdHasher>>; | ||
pub(crate) type TypeIdMap<V> = HashMap<TypeId, V, fxhash::FxBuildHasher>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we leave a comment here mentioning why we aren't just using RandomState
, and perhaps mentioning TypeIdHasher
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps mentioning TypeIdHasher
I don't think that there is a reason to mention deleted code in comments. It would just distract people unneccessary.
@DJMcNab I run benches in I don't know is Ahash better or FxHash, it seems that both have little effect (ahash performs little better in single threaded benches while fxhash in multithreaded). I think, differences here is just noise. Comparison between old TypeIdHash and fxhash.
This is comparison between FxHash and Ahash:
|
Last time I compared fxhash to ahash in the context of Bevy ECS, aHash came out on top. We use aHash everywhere in Bevy (see bevy_utils), largely as a result of those numbers ... which were never published publicly 😄 Unless we have a very good reason, I'd prefer to stay consistent everywhere / use what already works for us. If we can prove that fxhash is a measurable / significant perf improvement, I'm down to make the switch. But otherwise id rather just stick with what currently works. When it comes to benchmarks, id prefer it if we used less synthetic benchmarks because optimizers are weird. Lets use ecs_bench_suite to check for perf changes. See this discussion on the upstream hecs repo for the rationale behind the change and some significant perf improvements we measured (both in upstream hecs and bevy ecs) |
@cart @DJMcNab
And old hash -> ahash
fxhash -> ahash
I looks like that fxhash has comparable speed as noop hasher and ahash clearly slower than fxhash and noop. Probable reason of this that ahash optimized for data chunked by 128 bits (its code uses u128 heavily). fxhash, in contrast, optimized to use |
Relying on TypeId being some hash internally isn't future-proof because there is no guarantee about internal layout or structure of TypeId. I benchmarked TypeId noop hasher vs fxhash and found that there is very little difference. Also fxhash is likely to be better supported because it is widely used in rustc itself. [Benchmarks of hashers](#1097) [Engine wide benchmarks](#1119 (comment))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already import fxhash
anyway via wgpu, so I'm happy using fxhash, considering how much faster it is than ahash.
$ cargo tree -p byteorder
byteorder v1.3.4
Edit: Well that's not right, obviously
Can't fix it as on mobile
What is not right? |
The exact message which I sent, because that was about the byteorder crate instead of the fxhash crate. Because I knew the byteorder crate was the only dependency of fxhash, I checked that first. |
Awesome. Those numbers are pretty convincing. In a few days when I'm back at the computer I've benched on before, I'll run some benches on my side just to convince myself thoroughly. But if everything lines up this looks like a clear win (small perf boosts in some cases, reduced code complexity, and maybe the potential to remove ahash from the build tree) |
Relying on TypeId being some hash internally isn't future-proof because there is no guarantee about internal layout or structure of TypeId. I benchmarked TypeId noop hasher vs fxhash and found that there is very little difference. Also fxhash is likely to be better supported because it is widely used in rustc itself. [Benchmarks of hashers](bevyengine#1097) [Engine wide benchmarks](bevyengine#1119 (comment))
Relying on TypeId being some hash internally isn't future-proof because there is no guarantee about internal layout or structure of TypeId. I benchmarked TypeId noop hasher vs fxhash and found that there is very little difference.
Also fxhash is likely to be better supported because it is widely used in rustc itself.