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

Expose non-nullable configuration to remove AOT limiting null check #2514

Merged
merged 8 commits into from
Oct 5, 2023

Conversation

JimBobSquarePants
Copy link
Member

Prerequisites

  • I have written a descriptive pull-request title
  • I have verified that there are no overlapping pull-requests open
  • I have verified that I am following the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules 👮.
  • I have provided test coverage for my change (where applicable)

Description

Fixes #2486

As discussed in the linked issue AdvancedImageExtensions.GetConfiguration() causes the AOT compiler to include all image unused formats due to the null check and assignment of Configuration.Default.

Since that null check is unavoidable without an API change, I decided to make it by making IConfigurationProvider public and exposing the property directly.

While developers should be careful to not edit the configuration singleton, I do not consider accessing the configuration an advanced scenario since we already provide means to construct and pass custom configuration to our types.

@JimBobSquarePants JimBobSquarePants added area:aot breaking Signifies a binary breaking change. labels Aug 17, 2023
@JimBobSquarePants JimBobSquarePants added this to the v3.1.0 milestone Aug 17, 2023
@JimBobSquarePants JimBobSquarePants changed the title Expose non-nullable configuration to remove null check Expose non-nullable configuration to remove AOT limiting null check Aug 17, 2023
Copy link
Member

@tocsoft tocsoft left a comment

Choose a reason for hiding this comment

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

seems fine... only concern is the unnesorcery breaking of the public API. (AdvancedImageExtensions.GetConfiguration(...) overloads.

yes we are no longer dependent on them, but they are public api and some else probably is, anyone with custom encoders/decoders for example.

/// </summary>
/// <param name="source">The source image.</param>
/// <returns>Returns the configuration.</returns>
public static Configuration GetConfiguration(this Image source)
Copy link
Member

Choose a reason for hiding this comment

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

we should probably leave these in despite then no longer being needed for backwards compatability, anyone with a dependency on this public API will break otherwise, shoudl mark them Obsolete instead

Copy link
Member

@antonfirsov antonfirsov Oct 4, 2023

Choose a reason for hiding this comment

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

There are several breaking changes coming to 3.1 already without obsoletion eg. #2455 or #2485. I see little point using Obsolete selectively.

What is worrying me is that the net amount of breaking changes between 3.0.* -> 3.1.0 is much bigger than between 2.0.* -> 2.1.0. Maybe we should rename 3.1 to 4.0 to avoid confusion?

Copy link
Member Author

Choose a reason for hiding this comment

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

My plan with major versions has always been to support latest the .NET LTS version. There are breaking changes (unfortunately more than I'd like), but they typically only affect scenarios involving advanced behavior.

@JimBobSquarePants
Copy link
Member Author

@MichalStrehovsky I finally bit the bullet and installed the .NET 8 RC so I could use Sizoscope. With these changes and a tweak to the calling code from the sample project in #2486 we achieve much better results.

/// <summary>
/// Saves the given buffer using the filename extension as format.
/// </summary>
/// <param name="filename">The full pathname for the filename being written</param>
/// <param name="buffer">The image data stored as RGB buffer.</param>
/// <param name="width">The image width in pixels.</param>
/// <param name="height">The image height in pixels.</param>
public static void SaveImage(string filename, ReadOnlySpan<byte> buffer, int width, int height)
{
    // Pass custom Configuration to avoid loading all default formats.
    using var image = Image.LoadPixelData<Rgb24>(new(), buffer, width, height);
    using var stream = new FileStream(filename, FileMode.Create);
    var pngEncoder = new PngEncoder()
    {
        ColorType = PngColorType.Rgb
    };

    image.SaveAsPng(stream, pngEncoder);
}
image

We could probably drop the size by another 40-45kb if we refactored the way the quantizer is loaded in the png encoder, for some reason the compiler cannot trim out the construction of that type but that's beyond the scope of this PR.

@MichalStrehovsky
Copy link

@MichalStrehovsky I finally bit the bullet and installed the .NET 8 RC so I could use Sizoscope. With these changes and a tweak to the calling code from the sample project in #2486 we achieve much better results.

Nice! How big is the resulting sample project? I'm guessing this is a ~30% size reduction? IIRC this app was about 5 MB before.

@JimBobSquarePants
Copy link
Member Author

Nice! How big is the resulting sample project? I'm guessing this is a ~30% size reduction? IIRC this app was about 5 MB before.

The executable? Less than half if I'm following the Twitter thread correctly.

image

@JimBobSquarePants JimBobSquarePants merged commit 8bd273f into main Oct 5, 2023
8 checks passed
@JimBobSquarePants JimBobSquarePants deleted the js/smaller-aot branch October 5, 2023 10:21
@MichalStrehovsky
Copy link

Nice! How big is the resulting sample project? I'm guessing this is a ~30% size reduction? IIRC this app was about 5 MB before.

The executable? Less than half if I'm following the Twitter thread correctly.

image

Better than expected! Looks like C#/.NET matches the Go size now!

@JimBobSquarePants
Copy link
Member Author

Fantastic stuff! I'll be looking at Sizoscope a lot for v4 to see if we can design the library internals to be as trimmable as possible. 😁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area:aot breaking Signifies a binary breaking change.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

JPEG/WebP/... part of the executable even if all I do is save a PNG
4 participants