While profiling other code, trying to get my perf to match Rust, I noticed that my vanilla for-loop seemed to be one large source of difference. I'm not great with assembly, but looking at what was generated it seemed like Rust was able to skip bound checks when indexing into the arrays since the length of the array was/is given in the range.
Has anyone else ran into this? While this is a toy example, I've run into in more complex scenarios and with real data as well.
The two programs in question, repo has benching script:
import sysfn main() raises: var times = sys.argv()[1].__int__() var array = List[UInt64]() for i in range(0, times): array.append(i) var sum: UInt64 = 0 for _ in range(0, times): for i in range(0, times): sum += array[i] print(sum)
import sysfn main() raises: var times = sys.argv()[1].__int__() var array = List[UInt64]() for i in range(0, times): array.append(i) var sum: UInt64 = 0 for _ in range(0, times): for i in range(0, times): sum += array[i] print(sum)
use std::env::args;fn main() { let times = args() .skip(1) .next() .unwrap() .parse::<usize>() .expect("Expected number as first arg"); // I don't think filling the array with the macro has any hidden optimizations, but just in case: let mut array: Vec<u64> = vec![]; for i in 0..times { array.push(i as u64) } let mut sum = 0; for _ in 0..times { for i in 0..times { sum += array[i]; } } println!("{}", sum)}
use std::env::args;fn main() { let times = args() .skip(1) .next() .unwrap() .parse::<usize>() .expect("Expected number as first arg"); // I don't think filling the array with the macro has any hidden optimizations, but just in case: let mut array: Vec<u64> = vec![]; for i in 0..times { array.push(i as u64) } let mut sum = 0; for _ in 0..times { for i in 0..times { sum += array[i]; } } println!("{}", sum)}