When do you use
usize, or just
u32? (Is there any performance difference?)
When do you use
Don't worry about performance;
usize does not exist to give you performance. It's the same size and has exactly the same behavior as one of the (unsigned) integer types (specifically, the one that matches the target word size). The point of
usize is that it can encode platform-dependent size/count/alignment information and can be converted to a pointer (and back) if that's needed. Since word sizes and pointer widths vary across platforms (at least 16, 32 and 64 bits are in use in the wild), it's nice to have an integer type that always matches the platform word size. Otherwise we would be stuck with at least 3-way compile-time branching (in the form of
#[cfg(target_pointer_width = ...)]) every single time we wanted to count the number of elements in a collection or similar, which would be detrimental to usability and highly error-prone.
That should be avoided. It is almost never the proper solution, just use the raw pointers
*const () /
*mut (). It is not guaranteed that any pointer is round-trippable through
usize, and it will almost certainly be false on some architectures.
The proper way to use
usize is as offsets from a pointer. For example, it is what you should use to index slices and vectors. It is also what you should use for pointer arithmetics (occasionally you may also need
In general, don't worry about memory usage or performance of
usize unless you have good benchmarks that prove it would matter. The size optimization is useful only in very constrained environments where spending a couple of bytes is an issue, or if you are writing a virtual machine (because it can use much less memory than the hardware has). The performance benefits of different integer types are extremely non-obvious and are a micro-optimization of the worst kind.
One issue with
usize is that it's different on different platforms, so you can't use it for e.g. serialization. If you expect to serialize some data, even if it's expected to be read by your own program, most of the time it's best to use fixed-size integer types and avoid the possible size issues. You should also use fixed-sized types if you are doing low-level or performance-sensitive computations (since the behaviour of
usize is quite unpredictable). For example, you shouldn't base a big integer library around
usize, since you must carefully track any possible overflow.
On pretty niche ones. However, the intent of usize always was pointer compatibility (until very recently some people argued that it should not be because that makes support for Weird Embedded Platform #69287TM hard, which is not a good reason).
I wasn't actively advising round-tripping through integers when it's avoidable. I was merely saying it's possible, and that this property also allows usize to fit all platform-allowed sizes and offsets, which of course is its primary and preferred use.
In terms of instruction count? Not at all. If you're compiling to x64, for example, then even if you use
u32 the compiler will probably often end up using 64-bit registers anyway.
As such, if you're using a local variable for indexing, just make it a
usize. It'll never be slower—and might even be faster than using a smaller type—and it'll be way easier in the code you're writing by not needing casts for indexing all over the place.
The one place you might consider using a smaller type is for memory impact. If you need to store millions of indexes into a short vector for some reason, then sometimes it can be worth it to store them as, say,
u16s which you immediately convert to
usizes when you load them from memory for use.
usize mostly when it's for lengths of things in memory, array indices, counting, and ONLY when there is no need for the value to be cross-platform (i.e. when it's not shared with something else that may have a different
usize size, like through network or file).
I use others for the other cases, according to the size I need, or when I need to store lots of them, as described in the previous reply.