Skip to content

successors is 2x slower than map #113055

Open
@Centri3

Description

@Centri3

I tried this code:

use std::iter::successors;

pub fn foo_map(y: u32) -> Vec<u32> {
    (0..).map(|i| y.pow(i)).take(5).collect()
}

pub fn foo_successors(y: u32) -> Vec<u32> {
    successors(Some(1), |x| Some(y * x)).take(5).collect()
}

godbolt

I expected to see this happen: the same performance

Instead, this happened: foo_successors is ~2x slower than foo_map, and the assembly outputted has a ton of checks. Changing foo_map to (0..).map(|i| Some(y.pow(i)).take(5).collect::<Option<_>>().unwrap() produces identical assembly (afaict, I have bad eyes :D), which leads me to believe it's because of Some, which should be optimized out as it never returns None.

Meta

rustc --version --verbose:

rustc 1.72.0-nightly (fe7454bf4 2023-06-19)
binary: rustc
commit-hash: fe7454bf439c93cbe9ac8a8f7fcfacd5a40244c2
commit-date: 2023-06-19
host: x86_64-unknown-linux-gnu
release: 1.72.0-nightly
LLVM version: 16.0.5

@rustbot label +I-slow

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-iteratorsArea: IteratorsC-enhancementCategory: An issue proposing an enhancement or a PR with one.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchI-slowIssue: Problems and improvements with respect to performance of generated code.T-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions