Because under the hood it's allocating a one-dimensional vector. Try this instead:
vec![0; width * height]
A zero-initialized vector of a numeric type can be created very quickly because initialization isn't necessary. However, your second method allocates width + 1
vectors, and requires initialization of the outer container. This is not only needlessly wasteful in terms of memory consumption, but will likely cause poor data locality and possible heap fragmentation as nothing requires the heap allocations for the inner vectors to be near to each other. The performance hit here is almost certainly due to having to perform 1,000 extra heap allocations.
The third method creates an array of arrays. This lays out the data contiguously, so is better than the second method, but with this approach Rust can't skip the initialization step like it can when allocating from the heap, and so it takes a bit longer.