Skip to content

aws-lc-rs causes substantial binary size increaseΒ #745

Open

Description

@landonxjames

Problem:

The AWS Rust SDK recently updated our default version of rustls to one that uses aws-lc-rs as the crypto provider. This has caused a substantial (consistently ~4MB in my tests) increase in binary size. This has caused some pain points for customers: smithy-lang/smithy-rs#4049. In our debugging using cargo-bloat it appears that much of this size comes from aws-lc functions as can be seen in the output below from a small test application.

$ cargo bloat --release -n 50
 File  .text     Size                  Crate Name
 1.0%   2.1% 173.1KiB             aws_sdk_s3 aws_sdk_s3::config::endpoint::internals::resolve_endpoint
 0.3%   0.6%  47.2KiB              [Unknown] edwards25519_scalarmulbase_alt_edwards25519_gtable
 0.3%   0.6%  47.2KiB              [Unknown] edwards25519_scalarmulbase_edwards25519_gtable
 0.3%   0.6%  47.2KiB              [Unknown] curve25519_x25519base_byte_alt_edwards25519_gtable
 0.3%   0.6%  47.2KiB              [Unknown] curve25519_x25519base_byte_edwards25519_gtable
 0.2%   0.4%  30.7KiB             aws_lc_sys _aws_lc_0_27_0_pqcrystals_kyber512_ref_indcpa_keypair_derand
 0.2%   0.4%  28.7KiB             aws_lc_sys _aws_lc_0_27_0_pqcrystals_kyber768_ref_indcpa_keypair_derand
 0.2%   0.3%  25.7KiB             aws_lc_sys _aws_lc_0_27_0_pqcrystals_kyber768_ref_indcpa_enc
 0.1%   0.3%  24.9KiB              [Unknown] p384_montjscalarmul_p384_montjadd
 0.1%   0.3%  23.1KiB             aws_lc_sys _aws_lc_0_27_0_pqcrystals_kyber512_ref_indcpa_enc
 0.1%   0.3%  21.8KiB             aws_config aws_config::loader::ConfigLoader::load::{{closure}}
 0.1%   0.3%  21.8KiB             aws_config aws_config::loader::ConfigLoader::load::{{closure}}
 0.1%   0.3%  21.8KiB             aws_config aws_config::loader::ConfigLoader::load::{{closure}}
 0.1%   0.2%  17.1KiB              [Unknown] p384_montjscalarmul_alt_p384_montjadd
 0.1%   0.2%  17.0KiB            aws_sdk_sts aws_sdk_sts::config::endpoint::internals::resolve_endpoint
 0.1%   0.2%  16.4KiB             aws_lc_sys _aws_lc_0_27_0_pqcrystals_kyber1024_ref_indcpa_keypair_derand
 0.1%   0.2%  16.0KiB             aws_config aws_config::sso::credentials::load_sso_credentials::{{closure}}
 0.1%   0.2%  15.9KiB             aws_config aws_config::ecs::EcsCredentialsProvider::credentials::{{closure}}
 0.1%   0.2%  14.0KiB              [Unknown] _ec_GFp_nistp224_point_get_affine_coordinates
 0.1%   0.2%  14.0KiB             aws_config aws_config::sso::token::SsoTokenProvider::refresh_cached_token::{{closure}}
 0.1%   0.2%  13.1KiB             aws_lc_sys _aws_lc_0_27_0_pqcrystals_kyber1024_ref_indcpa_enc
 0.1%   0.2%  12.7KiB                   http http::header::name::StandardHeader::from_bytes
 0.1%   0.2%  12.7KiB                   http http::header::name::StandardHeader::from_bytes
 0.1%   0.2%  12.4KiB             aws_config <core::pin::Pin<P> as core::future::future::Future>::poll
 0.1%   0.2%  12.4KiB             aws_config aws_config::imds::credentials::ImdsCredentialsProvider::credentials::{{closure}}
 0.1%   0.1%  12.2KiB              [Unknown] p256_montjscalarmul_p256_montjadd
 0.1%   0.1%  12.2KiB              aws_sigv4 aws_sigv4::http_request::canonical_request::CanonicalRequest::from
 0.1%   0.1%  12.1KiB              [Unknown] p384_montjscalarmul_p384_montjdouble
 0.1%   0.1%  12.1KiB             aws_lc_sys _p384_montjdouble
 0.1%   0.1%  12.0KiB     aws_smithy_runtime aws_smithy_runtime::client::orchestrator::try_attempt::{{closure}}
 0.1%   0.1%  12.0KiB     aws_smithy_runtime aws_smithy_runtime::client::orchestrator::try_attempt::{{closure}}
 0.1%   0.1%  11.9KiB     aws_smithy_runtime aws_smithy_runtime::client::orchestrator::try_attempt::{{closure}}
 0.1%   0.1%  11.9KiB     aws_smithy_runtime aws_smithy_runtime::client::orchestrator::try_attempt::{{closure}}
 0.1%   0.1%  11.8KiB             aws_lc_sys _aws_lc_0_27_0_ml_kem_indcpa_enc_ref
 0.1%   0.1%  11.7KiB     aws_smithy_runtime aws_smithy_runtime::client::orchestrator::try_attempt::{{closure}}
 0.1%   0.1%  11.7KiB     aws_smithy_runtime aws_smithy_runtime::client::orchestrator::try_attempt::{{closure}}
 0.1%   0.1%  11.6KiB             hyper_util hyper_util::client::legacy::client::Client<C,B>::send_request::{{closure}}
 0.1%   0.1%  11.5KiB             aws_lc_sys _aws_lc_0_27_0_ml_kem_indcpa_keypair_derand_ref
 0.1%   0.1%  11.4KiB             aws_sdk_s3 aws_sdk_s3::protocol_serde::shape_put_object::ser_put_object_headers
 0.1%   0.1%  11.3KiB             aws_config aws_config::sso::token::SsoTokenProvider::refresh_cached_token::{{closure}}
 0.1%   0.1%  11.3KiB             aws_config aws_config::profile::credentials::ProfileFileCredentialsProvider::load_credentials::{{closure}}
 0.1%   0.1%  11.0KiB             aws_sdk_s3 aws_sdk_s3::s3_express::identity_provider::DefaultS3ExpressIdentityProvider::identity::{{closure}}
 0.1%   0.1%  10.9KiB             aws_lc_sys _aws_lc_0_27_0_ml_dsa_sign_internal
 0.1%   0.1%  10.7KiB             aws_config aws_config::web_identity_token::WebIdentityTokenCredentialsProvider::credentials::{{closure}}
 0.1%   0.1%  10.7KiB            aws_sdk_sts <aws_sdk_sts::operation::assume_role_with_web_identity::AssumeRoleWithWebIdentityResponseDeserializer as aws_smithy_runtime_api::client::ser_de::DeserializeResponse>::deseriali...
 0.1%   0.1%  10.6KiB                     h2 h2::codec::framed_read::decode_frame
 0.1%   0.1%  10.6KiB                     h2 h2::codec::framed_read::decode_frame
 0.1%   0.1%  10.5KiB            aws_config? <aws_config::imds::client::token::TokenResolver as aws_smithy_runtime_api::client::identity::ResolveIdentity>::resolve_identity::{{closure}}
 0.1%   0.1%  10.5KiB             aws_lc_sys _p521_jdouble_alt
 0.1%   0.1%  10.3KiB aws_smithy_http_client h2::proto::connection::Connection<T,P,B>::poll
42.0%  87.6%   7.0MiB                        And 23518 smaller methods. Use -n N to show more.
47.9% 100.0%   7.9MiB                        .text section size, the file size is 16.6MiB

Solution:

I'm afraid I don't have many suggestions for a full solution to this. I suspect that, since aws-lc is a mostly C based dependency, much of rustc's dead code elimination doesn't work for it so we are getting stuck pulling in functions we aren't actually using. The cheeky suggestion there is rewrite it in Rust, but that isn't a reasonable solution on any kind of short timescale.

Potentially splitting the various algorithms into their own crates could help rustc clean up better?

Activity

  1. amyspark commented on Apr 16, 2025

    @amyspark
    Contributor

    This has caused a substantial (consistently ~4MB in my tests) increase in binary size.

    In our case it's not 4MB, it's 17 MB. The usual offender in gst-plugins-rs, gstrswebrtc, now sits at 804MB when statically built for MSVC.

    The increase in size, combined with aws-smithy's own bloat, is now preventing us from shipping gst-plugins-rs's network-based plugins inside a MSI, at least as MSVC-based static libraries.

    I assume the same will occur with MinGW, as there are no tools to prelink static libraries for PE/COFF.

  2. faern commented on May 8, 2026

    @faern

    We are also trying to migrate from ring to aws-lc-rs, and were surprised by the very large bump in binary size. After some investigation it seems like I was able to avoid most of the size increase by setting this environment variable:

    AWS_LC_SYS_CFLAGS="-DOPENSSL_SMALL -DMY_ASSEMBLER_IS_TOO_OLD_FOR_512AVX"
    

    On x86_64 Linux and macOS this pulls down the size increase compared to ring from ~1.8 MiB to ~300 kiB. And on Windows from ~700 kiB to ~300 kiB. The best I have been able to do is a size regression of those ~300 kiB compared to ring.

    Warning: as this removes some precomputed tables and removes some optimized code, it can potentially cost you performance, depending on what cryptographic primitives you are actually using and what target platform the binary runs on. For our use case this was completely acceptable.

    I made a little github repository to experiment with these sizes. It contains more info about what these variables do, and how much size it saves on various platforms: https://github.com/faern/showcase-aws-lc-binary-size

    I think it would be awesome if aws-lc-rs could be more lean by default, and maybe expose cargo features that allow the user to opt-in to further optimizations, at the cost of binary size (and/or compile time). This would IMHO be better than having everyone pay a large binary tax for things most people might not use.

  3. justsmth commented on Aug 7, 2026

    @justsmth
    Contributor

    We just released aws-lc-rs v1.18.0 which adds built-in support for AWS-LC's size-optimized configuration:

    The trade-off is slower elliptic-curve performance, but no algorithms are removed and all outputs are unchanged. It activates automatically when Cargo is already building for size (opt-level = "s" or "z"), and can be forced independently of opt-level with AWS_LC_SYS_SMALL=1 (or disabled with =0). FIPS builds require an explicit AWS_LC_FIPS_SYS_SMALL=1 and warn when set.

    Measured in our CI on an executable that uses SHA-256, AES-256-GCM, and ECDSA P-256, opt-level=z versus opt-level=3:

    Platform opt-level=3 opt-level=z Reduction
    x86_64 Linux 2,886,280 1,436,656 50%
    aarch64 macOS 2,114,928 1,082,224 48%
    x86_64 Windows 1,454,592 887,296 39%
    aarch64 Linux 1,970,880 1,249,984 36%

    This doesn't resolve everything raised here, so I'll leave this open for now.

    @landonxjames @amyspark @faern -- would you mind re-measuring your respective cases against v1.18.0? @amyspark, yours (17 MB, MSVC static) is the one furthest from what our CI covers, so I'm particularly interested in whether it helps there.

    Many thanks to all of you! πŸ˜„

  4. amyspark commented on Aug 7, 2026

    @amyspark
    Contributor

    @amyspark, yours (17 MB, MSVC static) is the one furthest from what our CI covers, so I'm particularly interested in whether it helps there.

    I can confirm it's back under control. We've already been running opt-level = "s" and can squash the rest of the overhead away by deduplicating the object files manually, or with lto = thin.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions