Recently I’ve been exploring Rust Clippy lints and started thinking about len zero
lint which
Checks for getting the length of something via
.len()
just to compare to zero, and suggests using.is_empty()
where applicable.
In addition to communicating an actual intent, there is another, performance related reason -
Some structures can answer
.is_empty()
much faster than calculating their length. So it is good to get into the habit of using.is_empty()
, and having it is cheap.
This got me thinking about a ways to check if a string is empty:
s == ““
s.is_empty()
s.len() == 0
Depending on the context, each of these options may be chosen for looking most natural, but is there some objective reason, like performance? Let’s put this test:
but the results do not suggest a clear winner:
So to pick a winner, I’ve decided to take a look at the generated assembly for these functions and since in Rust str
and String
are very different, let’s check them out separately. For &str
:
generated code looks identical for all 3 versions:
It simply checks if the length of the character array, passed via %rsi
, basically doing s.len() == 0
.
For String
the generated code is a little more involved but is still identical for all 3 versions:
The extra complexity comes from the fact that String
is represented as
and Vec
in turn is represented as
so to get to len
we need to skip the buf
.
This is great news, since we can just focus on writing code that communicates its intent the best and let the compiler pick the most performant way to back it up.
P.S.: the same holds true for Go’s implementation:
are both translated into