I'm experimenting with rewriting some old C code into Rust - which I'm new to. One recurring issue I have is that the C code has a lot of loops like this:
for (i = startIndex; i < asize; i++)
{
if (firstEdge < 0 && condLeft(i))
{
firstEdge = i;
}
RightIndex = asize-1-i;
if (firstEdgeRight < 0 && condRight(RightIndex))
{
firstEdgeRight = RightIndex;
}
// Found both edges
if (firstEdge >= 0 && firstEdgeRight >= 0) {
break;
}
}
How would you translate that into Rust in a performant way? My issue is that while I could probably get the functionality I want I'm not sure how to do it obtain (roughly) the same speed.
This part of the code is the main bottleneck in our code (this part of the code at least) and when translating it would like to keep the following properties.
- The loop should break ASAP since
asize
can be very large. - Both
firstEdge
andfirstEdgeRight
are found roughly at the same time. Therefore it has been a good thing to only have one loop instead of two - in order to avoid search from the beginning again (even though I think this solution kills the prefetcher (but I'm not sure, maybe the old machine running the code doesn't even have a prefetcher)).
While performance is important, readability is of course even more important :)
EDIT Ok, here is a possible Rust implementation by me (cond_right()
and cond_left()
are left out).
The things I think about is:
- Is this how other people would write it if they had to implement it from scratch?
- Do I really need to make
first_edge
andfirst_edge_right
mutable? They are in my implementation, but it feels wrong to me since they are only assigned once.
let mut first_edge = -1;
let mut first_edge_right = -1;
// Find first edge
let start_index = 300; // or something
let asize = 10000000;
for i in start_index..asize {
if first_edge < 0 && cond_left(i) {
first_edge = i;
}
let right_index = asize - i -1;
if first_edge_right < 0 && cond_right(right_index) {
first_edge_right = right_index;
}
if (first_edge >= 0 && first_edge_right >= 0) {
break;
}
}