Skip to content

Check NI size after it is built #12996

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

Merged
merged 6 commits into from
May 6, 2025
Merged

Conversation

Akirathan
Copy link
Member

@Akirathan Akirathan commented Apr 30, 2025

Pull Request Description

Size of the generated enso NI executable is checked right after it was built. The size bounds for the production NI are set to 150 MB <= x <= 450 MB, explained in #12996 (comment).

Important Notes

Checklist

Please ensure that the following checklist has been satisfied before submitting the PR:

  • The documentation has been updated, if necessary.
  • Screenshots/screencasts have been attached, if there are any visual changes. For interactive or animated visual changes, a screencast is preferred.
  • All code follows the
    Scala,
    Java,
    TypeScript,
    and
    Rust
    style guides. In case you are using a language not listed above, follow the Rust style guide.
  • Unit tests have been written where possible.
  • If meaningful changes were made to logic or tests affecting Enso Cloud integration in the libraries,
    or the Snowflake database integration, a run of the Extra Tests has been scheduled.
    • If applicable, it is suggested to paste a link to a successful run of the Extra Tests.

@Akirathan Akirathan added the CI: No changelog needed Do not require a changelog entry for this PR. label Apr 30, 2025
@Akirathan Akirathan self-assigned this Apr 30, 2025
@Akirathan
Copy link
Member Author

Akirathan commented Apr 30, 2025

The test is currently failing - size should be 150MB < size < 450MB, but is 489MB. The reason for that is that the NI built for the test is built with ENSO_LAUNCHER=native,test, which means that it is not optimized for size. That is done for NI build for the production.

Two possible solutions for that:

  1. Move this test to nightly checks, that build NI for production.
  2. Increase allowed size to 500 MB and leave the test here.

I personally prefer solution (1).

@enso-bot enso-bot bot mentioned this pull request Apr 30, 2025
@Akirathan
Copy link
Member Author

Akirathan commented May 5, 2025

In c324144, the check is implemented directly in sbt, during buildEngineDistribution.

Example of NI build failing due to unexpected size:

$ env ENSO_LAUNCHER=native,-ls,fast sbt buildEngineDistribution
...
[info] ------------------------------------------------------------------------------------------------------------------------
[info]                         8.3s (6.0% of total time) in 665 GCs | Peak RSS: 8.28GB | CPU load: 9.28
[info] ------------------------------------------------------------------------------------------------------------------------
[info] Build artifacts:
[info]  /home/pavel/dev/enso/built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/bin/enso (executable)
[info] ========================================================================================================================
[info] Finished generating 'enso' in 2m 17s.
[info] built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/bin/enso native image build successful.
[error] Generated binary built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/bin/enso has unexpected size: 151 MB. Expected size is between 200 and 550 MB.
[error] java.lang.RuntimeException: Generated binary built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/bin/enso is too large
[error] 	at NativeImage$.$anonfun$checkNativeImageSize$1(NativeImage.scala:349)
[error] 	at NativeImage$.$anonfun$checkNativeImageSize$1$adapted(NativeImage.scala:326)
[error] 	at scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error] 	at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:63)
[error] 	at sbt.std.Transform$$anon$4.work(Transform.scala:69)
[error] 	at sbt.Execute.$anonfun$submit$2(Execute.scala:283)
[error] 	at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:24)
[error] 	at sbt.Execute.work(Execute.scala:292)
[error] 	at sbt.Execute.$anonfun$submit$1(Execute.scala:283)
[error] 	at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
[error] 	at sbt.CompletionService$$anon$2.call(CompletionService.scala:65)
[error] 	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328)
[error] 	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545)
[error] 	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328)
[error] 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1095)
[error] 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:619)
[error] 	at java.base/java.lang.Thread.run(Thread.java:1447)
[error] (engine-runner / checkNativeImageSize) Generated binary built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/bin/enso is too large

Successful build of NI:

$ env ENSO_LAUNCHER=native,-ls,fast sbt buildEngineDistribution
...
[info] Build artifacts:
[info]  /home/pavel/dev/enso/built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/bin/enso (executable)
[info] ========================================================================================================================
[info] Finished generating 'enso' in 2m 25s.
[info] built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/bin/enso native image build successful.
[info] Generated binary built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/bin/enso is within the expected size: 151 MB.
[info] Generating index for built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/lib/Standard/AWS 
[info] Generating index for built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/lib/Standard/Base 
[info] Generating index for built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/lib/Standard/Database 
[info] Generating index for built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/lib/Standard/Examples 
[info] Generating index for built-distribution/enso-engine-0.0.0-dev-linux-amd64/enso-0.0.0-dev/lib/Standard/Geo 
...

)
}
val bytes = generatedBin.attributes.size()
val productionNIBounds = (150, 450)
Copy link
Member Author

Choose a reason for hiding this comment

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

Based on latest nightly build:

  • Linux production NI has 433 MB
  • Windows production NI has 390 MB
  • MacOS aarch64 production NI has 393 MB
  • MacOS x64 production NI has 378 MB

Copy link
Member

Choose a reason for hiding this comment

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

Maybe the maxImageSizeInMb function should return different value for different OS to allow incremental individual improvements on each platform

@Akirathan Akirathan changed the title Add unit test for NI size Check NI size after it is built May 5, 2025
Copy link
Member

@JaroslavTulach JaroslavTulach left a comment

Choose a reason for hiding this comment

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

Put it in, so the size never regresses (too much) again!

"Ensure that the dependency on `buildNativeImage` is properly set."
)
}
val bytes = generatedBin.attributes.size()
Copy link
Member

Choose a reason for hiding this comment

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

  • the constant should be more prominent
  • def GraalVM.EnsoLauncher.maxImageSizeInMb = 450 maybe?
  • it shouldn't be hidden here

)
}
val bytes = generatedBin.attributes.size()
val productionNIBounds = (150, 450)
Copy link
Member

Choose a reason for hiding this comment

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

Maybe the maxImageSizeInMb function should return different value for different OS to allow incremental individual improvements on each platform

@Akirathan
Copy link
Member Author

Akirathan commented May 6, 2025

With ee07a3c, the expected sizes of the native image are defined in GraalVM.NativeImageSize:

enso/project/GraalVM.scala

Lines 99 to 106 in ee07a3c

// Expected production NI sizes deduced from sizes on latest
// nightly builds: https://github.com/enso-org/enso/pull/12996#discussion_r2073742680
// With maximal size relaxed by 30 MB.
private val windowsX64Release = NativeImageSize(200, 420)
private val linuxX64Release = NativeImageSize(200, 463)
private val macX64Release = NativeImageSize(200, 408)
private val macARM64Release = NativeImageSize(200, 423)
private val testNISize = NativeImageSize(100, 550)

cc @JaroslavTulach

@Akirathan Akirathan merged commit cc60c25 into develop May 6, 2025
79 of 81 checks passed
@Akirathan Akirathan deleted the wip/akirathan/ni-size-unit-test branch May 6, 2025 16:55
@JaroslavTulach
Copy link
Member

As of May 10, 2025 the sizes are: Linux 404MB, MacOSX Arm 392MB, MacOSX Intel 377MB, Windows 390MB

Frizi pushed a commit that referenced this pull request May 13, 2025
* Add Enso test for NI size

* better test clue

* Revert "better test clue"

This reverts commit cb94968.

* Revert "Add Enso test for NI size"

This reverts commit 48bf3cf.

* NI size is checked in sbt during buildEngineDistribution

* NativeImageSize constants are more visible, and platform specific
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI: No changelog needed Do not require a changelog entry for this PR.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants