Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce the size of the future returned by async get_with and friend methods (v0.9) #222

Merged
merged 1 commit into from
Feb 5, 2023

Conversation

tatsuya6502
Copy link
Member

@tatsuya6502 tatsuya6502 commented Feb 5, 2023

This PR will mitigate #212 for upcoming Moka v0.9.7 release.

Changes

future::Cache:

  1. To mitigate current rustc's optimization issue, switched the internally using type for the init future from impl Future to a reference Pin<&mut impl Future>.
  2. Eliminated an internal async function ValueInitializer:init_or_read(..., init, ...) from the call path.

Updated Methods:

future::Cache:

  • get_with(...)
  • get_with_if(...)
  • optionally_get_with(...)
  • try_get_with(...)
  • get_with_by_ref(...)
  • optionally_get_with_by_ref(...)
  • try_get_with_by_ref(...)

@tatsuya6502 tatsuya6502 added the enhancement New feature or request label Feb 5, 2023
@tatsuya6502 tatsuya6502 added this to the v0.9.7 milestone Feb 5, 2023
Change the type of the `init` future argument for internal `async fn`s
from `Future<...>` to `Pin<&mut impl Future<...>>`.
@tatsuya6502 tatsuya6502 marked this pull request as ready for review February 5, 2023 12:58
@tatsuya6502
Copy link
Member Author

To verify that this PR will reduce the future size, I ran the following program on Moka before and after applying the PR:

Program

check_future_sizes.rs
use std::convert::Infallible;

fn main() {
    let cache = moka::future::Cache::new(1);

    let get_fut = async {
        let buf = [0u8; 1024];
        async {}.await;
        #[allow(clippy::drop_copy)]
        drop(buf);
    };

    let get_fut_size = std::mem::size_of_val(&get_fut);
    println!("get_fut size:                     {} bytes", get_fut_size);

    let moka_fut = cache.get_with((), get_fut);
    let moka_fut_size = std::mem::size_of_val(&moka_fut);
    println!(
        "moka_get_with_fut size:           {} bytes ({:.2}x)",
        moka_fut_size,
        moka_fut_size as f64 / get_fut_size as f64
    );

    let opt_get_fut = async {
        let buf = [0u8; 1024];
        async {}.await;
        #[allow(clippy::drop_copy)]
        drop(buf);
        Some(())
    };
    let opt_get_fut_size = std::mem::size_of_val(&opt_get_fut);
    println!(
        "opt_get_fut size:                 {} bytes",
        opt_get_fut_size
    );

    let moka_fut = cache.optionally_get_with((), opt_get_fut);
    let moka_fut_size = std::mem::size_of_val(&moka_fut);
    println!(
        "moka_opt_get_with_fut size:       {} bytes ({:.2}x)",
        moka_fut_size,
        moka_fut_size as f64 / opt_get_fut_size as f64
    );

    let try_get_fut = async {
        let buf = [0u8; 1024];
        async {}.await;
        #[allow(clippy::drop_copy)]
        drop(buf);
        Ok(()) as Result<(), Infallible>
    };
    let try_get_fut_size = std::mem::size_of_val(&try_get_fut);
    println!("try_get_fut size:                 {} bytes", try_get_fut_size);

    let moka_fut = cache.try_get_with((), try_get_fut);
    let moka_fut_size = std::mem::size_of_val(&moka_fut);
    println!(
        "moka_try_get_with_fut size:       {} bytes ({:.2}x)",
        moka_fut_size,
        moka_fut_size as f64 / try_get_fut_size as f64
    );
}

Results

Before applying this PR

get_fut size:                     1026 bytes
moka_get_with_fut size:           7688 bytes (7.49x)
opt_get_fut size:                 1026 bytes
moka_opt_get_with_fut size:       7632 bytes (7.44x)
try_get_fut size:                 1026 bytes
moka_try_get_with_fut size:       7632 bytes (7.44x)

After applying this PR

get_fut size:                     1026 bytes
moka_get_with_fut size:           2632 bytes (2.57x)
opt_get_fut size:                 1026 bytes
moka_opt_get_with_fut size:       2584 bytes (2.52x)
try_get_fut size:                 1026 bytes
moka_try_get_with_fut size:       2584 bytes (2.52x)

@tatsuya6502
Copy link
Member Author

The above program covered only the following methods:

  • get_with(...)
  • optionally_get_with(...)
  • try_get_with(...)

I modified the program and ran a couple of times to check the future sizes of the other methods:

  • get_with_if(...)
  • get_with_by_ref(...)
  • optionally_get_with_by_ref(...)
  • try_get_with_by_ref(...)

I got similar outputs for them and verified that this PR reduces the future sizes.

Copy link
Member Author

@tatsuya6502 tatsuya6502 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant