C++ ranges/views 与 Rust 迭代器对比
2 分•作者: bijan7•9 个月前
看起来,除非我遗漏了什么,Rust 迭代器和 C++ ranges/views 的性能之间存在相当大的差距。
[https://godbolt.org/z/v76rcEb9n](https://godbolt.org/z/v76rcEb9n)
[https://godbolt.org/z/YG1dv4qYh](https://godbolt.org/z/YG1dv4qYh)
Rust:
```
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
);
}
```
输出:
Rust Result count: 292825
Rust Total count (1000 iterations): 292825000
Rust Total time: 1025 microseconds
Rust Average per iteration: 1.02 microseconds
C++:
```
#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;
}
```
输出:
C++ Result count: 292825
C++ Total count (1000 iterations): 292825000
C++ Total time: 174455 microseconds
C++ Average per iteration: 174.455 microseconds
查看原文
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.<p>https://godbolt.org/z/v76rcEb9n
https://godbolt.org/z/YG1dv4qYh<p>Rust:
<code>
use std::time::Instant;<p>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)
}<p>fn main() {
let input: Vec<i32> = (0..=50).collect();<p><pre><code> 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></pre>
}
</code><p>Output:
Rust Result count: 292825
Rust Total count (1000 iterations): 292825000
Rust Total time: 1025 microseconds
Rust Average per iteration: 1.02 microseconds<p>C++:
<code>
#include <chrono>
#include <iostream>
#include <numeric>
#include <ranges>
#include <vector><p>inline auto expandIotaViews(const std::vector<int>& input) {
auto iota_transform = [](const int number) {
return std::views::iota(1, number + 1);
};<p><pre><code> 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;</code></pre>
}<p>int main() {
std::vector<int> input(51);
std::iota(input.begin(), input.end(), 0);<p><pre><code> 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></pre>
}
</code><p>Output:
C++ Result count: 292825
C++ Total count (1000 iterations): 292825000
C++ Total time: 174455 microseconds
C++ Average per iteration: 174.455 microseconds