Skip to content

Copy trait defeats generator optimization #62952

Open

Description

@tmandry

The following example (playground):

#![feature(generators, generator_trait)]

use std::ops::Generator;

#[derive(Clone)]
struct Foo([u8; 1024]);

fn overlap_foo() -> impl Generator<Yield = (), Return = ()>{
    static || {
        let x = Foo([0u8; 1024]);
        yield;
        drop(x);
        let y = Foo([0u8; 1024]);
        yield;
        drop(y);
    }
}

#[derive(Clone, Copy)]
struct Bar([u8; 1024]);

fn overlap_bar() -> impl Generator<Yield = (), Return = ()>{
    static || {
        let x = Bar([0u8; 1024]);
        yield;
        drop(x);
        let y = Bar([0u8; 1024]);
        yield;
        drop(y);
    }
}

fn main() {
    dbg!(std::mem::size_of_val(&overlap_foo()));
    dbg!(std::mem::size_of_val(&overlap_bar()));
}

Outputs:

[gen-explicit-drop.rs:34] std::mem::size_of_val(&overlap_foo()) = 1028                                                                                                                                                                                                                                                       
[gen-explicit-drop.rs:35] std::mem::size_of_val(&overlap_bar()) = 2052  

The only difference between Foo and Bar is that Foo is Copy. This defeats the generator optimization implemented in #61922 which considers any local that has been moved from as a candidate for overlap.

Technically, this is semantically consistent with the existing overlap behavior for generators. But making a type Copy and getting worse performance is a footgun that we should fix.

This can be fixed with a pass that turns unnecessary copies into moves in MIR.

Activity

  1. added
    C-enhancementCategory: An issue proposing an enhancement or a PR with one.
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jul 24, 2019
  2. Centril commented on Jul 25, 2019

    @Centril
    Contributor

    This can be fixed with a pass that turns unnecessary copies into moves in MIR.

    I thought that's what https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/copy_prop/index.html does?

    cc @oli-obk

  3. added
    I-heavyIssue: Problems and improvements with respect to binary size of generated code.
    on Jul 25, 2019
  4. tmandry commented on Jul 30, 2019

    @tmandry
    MemberAuthor

    I thought that's what https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/transform/copy_prop/index.html does?

    Nice find, this does indeed do the required transformation. Running that (along with simplify_locals) right before the generator transform almost does the trick.

    The problem is that we currently eliminate all storage markers as part of copy_prop, and this defeats the generator optimization. If we merged the live ranges of the two variables instead, it should work.

    (EDIT: simplify_locals is not needed)

  5. added
    C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing such
    on Oct 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-coroutinesArea: CoroutinesC-enhancementCategory: An issue proposing an enhancement or a PR with one.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchI-heavyIssue: Problems and improvements with respect to binary size of generated code.T-compilerRelevant to the compiler 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