This means that if I have a thread threaded 3 Ghz machine doing nothing but generating new IDs in sequence, it would take me 194 years to exhaust all u64 ids?
(The importance of this question is that it guides whether I use u64 or u128, and whether I try to 'reuse ids' or just run them in sequence and not care.)
ECS IDs are indexes into an array. If you don't reuse indices and keep growing the array, you'd exhaust your RAM before you run out of index space, no?
Yes, I've spent 1-2 days playing with the rust/specs crate.
What I'm building is more of "EC" than "ECS".
I also want the list of components for a "table" to be statically defined at compile time (better auto completion, more compile time checks), rather than specs' system of creating world then adding arbitrary components at runtime.
Ok, cool! Look into the source code of the generational-arena crate as it has a nice way of reusing memory without wasting space. There is room for improvement, but it is a cool concept. That can be used to reuse indicies and make even more use of you're u64!
Assuming it takes 1 CPU cycle to increment a register, and branch/jump instructions execute in 0 cycles.
Then it will take roughly 195 years for a single 3 GHz CPU core to cycle through a 64-bit integer. You also cannot physically store all 2^64 IDs in memory simultaneously, in any case.
But this is an unrealistic measurement, and won't really help you answer your question until you consider a few other questions: Do you need global uniqueness? Are there possibilities of ID collisions across domains? Is u64 too large/do you expect to have more than 2^32 items accessible at a time?
What I meant is instead of implementing your own thing, just use TypeId. They choose u64 for a good reason. As you said, it is almost impossible for creating so many types to overflow an u64, so why not going with that?
I see your point. I'm writing an Entity-Component system for fun and learning, so I'\m trying to understand precisely what each piece does. (TypeId seems a bit overkill.)
It uses AtomicUsize + thread_local u64 counter so it should be unique enough for any non-distributed use case and fast enough for most cases. Of course it takes 128bit in memory, though.