C++ ranges/views vs. Rust iterator

it seems there is a quite a bit of gap between the performance of Rust iterator and C++ ranges/views unless I am missing something.

https://godbolt.org/z/v76rcEb9n https://godbolt.org/z/YG1dv4qYh

Rust: <code> use std::time::Instant;

fn expand_iota_views(input: &[i32]) -> impl Iterator<Item = i32> + '_ { input .iter() .flat_map(|&n| 1..=n) .flat_map(|n| 1..=n) .flat_map(|n| 1..=n) }

fn main() { let input: Vec<i32> = (0..=50).collect();

    let sample_result: Vec<i32> = expand_iota_views(&input).collect();
    println!("Rust Result count: {}", sample_result.len());

    let start = Instant::now();
    let mut total_count = 0;
    for _ in 0..1000 {
        let result = expand_iota_views(&input);
        total_count += result.count();
    }
    let duration = start.elapsed();

    println!("Rust Total count (1000 iterations): {}", total_count);
    println!("Rust Total time: {} microseconds", duration.as_micros());
    println!(
        "Rust Average per iteration: {:.2} microseconds",
        duration.as_micros() as f64 / 1000.0
    );
} </code>

Output: Rust Result count: 292825 Rust Total count (1000 iterations): 292825000 Rust Total time: 1025 microseconds Rust Average per iteration: 1.02 microseconds

C++: <code> #include <chrono> #include <iostream> #include <numeric> #include <ranges> #include <vector>

inline auto expandIotaViews(const std::vector<int>& input) { auto iota_transform = [](const int number) { return std::views::iota(1, number + 1); };

    return input 
                | std::views::transform(iota_transform) 
                | std::views::join 
                | std::views::transform(iota_transform) 
                | std::views::join
                | std::views::transform(iota_transform) 
                | std::views::join;
}

int main() { std::vector<int> input(51); std::iota(input.begin(), input.end(), 0);

    auto sample_result = expandIotaViews(input);
    std::vector<int> result_vec;
    for (auto val : sample_result) {
        result_vec.push_back(val);
    }

    std::cout << "C++ Result count: " << result_vec.size() << std::endl;

    auto start = std::chrono::high_resolution_clock::now();
    size_t total_count = 0;
    for (int i = 0; i < 1000; ++i) {
        auto result = expandIotaViews(input);
        total_count += std::ranges::distance(result);
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto duration =
        std::chrono::duration_cast<std::chrono::microseconds>(end - start);

    std::cout << "C++ Total count (1000 iterations): " << total_count
              << std::endl;
    std::cout << "C++ Total time: " << duration.count() << " microseconds"
              << std::endl;
    std::cout << "C++ Average per iteration: " << duration.count() / 1000.0
              << " microseconds" << std::endl;

    return 0;
} </code>

Output: C++ Result count: 292825 C++ Total count (1000 iterations): 292825000 C++ Total time: 174455 microseconds C++ Average per iteration: 174.455 microseconds

2 points | by bijan7 4 hours ago

0 comments