Portability of compiled code
Ashutosh Mehra
asmehra at redhat.com
Fri Dec 23 21:11:01 UTC 2022
Brian, thanks for your comments!
- Generate perfectly portable everything, even if that means generating
> worse everything. This is the route you are suggesting, but obviously this
> has limits that will be reached pretty quickly anyway
>
I wouldn't call for generating perfectly portable code. Portability would
depend on what micro-architectures we are willing to support and finding
the common set of cpu features supported by them.
-Record environmental dependencies, but be willing to toss them if they
> don’t match the runtime environment. For things like an AOT’ed code cache,
> the code cache could be flushed and we could fall back to dynamic code
> generation.
>
I agree that recording the environmental dependencies would always be
required. Even when generating the portable code, we should record the
dependencies, at the least to verify the AOT'ed code can be executed in the
runtime environment.
To expand a bit more on the portability aspect, the idea behind choosing a
set of cpu features is to make the code executable on a broader range of
micro architectures.
Let's say the application needs to be deployed on a cloud where
the user may not know the micro-architecture of the systems where the code
would eventually be executed.
In such a case if the ahead-of-time condensation produces code using a
specific cpu feature available on the system it is running on, then the
AOT'ed code may not be usable on deployment systems.
We can fall back to dynamic code generation, but we lose the startup
benefits we could get if only the code had been more portable.
Even if the portable code is inferior in quality, it can do the job of
providing comparatively quicker start up. At runtime the code can be
upgraded (I guess based on profiling) to a more efficient version to
exploit all the cpu features of the underlying architecture.
- Ashutosh Mehra
On Fri, Dec 23, 2022 at 3:15 PM Brian Goetz <brian.goetz at oracle.com> wrote:
> You identify a problem (generated code has environmental dependencies
> which may not carry into other environments) and a solution (detune the
> generated code to something generic.) I agree with the problem, but there
> are many other possible solutions, and we shouldn’t prematurely snap to one
> of them.
>
> Moving some work from runtime to earlier phases (whether through a Leyden
> condenser, a classfile rewriter, etc) always creates the possibility that
> this work depends on some environmental characteristic of the early
> execution environment. The list is endless: hardware, operating system,
> environment variables, time and time zone, JDK and other dependency
> versions, etc.
>
> Strategies for dealing with this include:
>
> - Record environmental dependencies, and fail if the code is restarted
> when the dependencies are not met. This is entirely reasonable when
> applied to things like “you ran your checkpoint on Intel/Windows, but
> you’re resuming on ARM/MacOS”; it is merely a matter of judgment how
> fine-grained to record and enforce.
>
> - Generate perfectly portable everything, even if that means generating
> worse everything. This is the route you are suggesting, but obviously this
> has limits that will be reached pretty quickly anyway. Nothing is going to
> save you from trying to resume on a different architecture / OS /
> incompatible JVM version / wrong class path / etc.
>
> - Record environmental dependencies, but be willing to toss them if they
> don’t match the runtime environment. For things like an AOT’ed code cache,
> the code cache could be flushed and we could fall back to dynamic code
> generation.
>
> - Train on a variety of architectures and include multiple versions of
> the AOT’ed code in the binary.
>
> … and plenty of others.
>
> A key aspect of Leyden is not only ahead-of-time condensation, but
> recording constraints that capture assumptions inherent in those
> condensations, and prevent operations that would contradict those
> assumptions (e.g., prohibit redefinition of classes that have been used to
> generate AOT’ed code.)
>
>
> On Dec 23, 2022, at 12:46 PM, Ashutosh Mehra <asmehra at redhat.com> wrote:
>
> Hello,
>
> Early this year we were doing some experiments on portability of
> checkpoints under project CRaC and prepared a document [0] on our findings.
> We feel parts of it would be relevant under Project Leyden as well, as it
> *may* enable ahead-of-time compilation in future (I know we are not there
> yet!)
>
> For the CRaC checkpoints, we found the code generated by C1/C2 compiler is
> not always portable due to the use of architecture specific instructions.
> The same would hold true in the context of AoT compilations as well.
> To make the code portable C1/C2 compilers should be provided with a
> minimal set of cpu features that they are allowed to exploit during codegen
> phase.
> However, this can also negatively impact the performance of the generated
> code as it would now not be utilizing all the features of the underlying
> architecture.
> So the performance may have to be traded for gaining portability.
>
> If anyone has thoughts on this aspect of the problem, please share them.
>
> [0]
> http://cr.openjdk.java.net/~heidinga/crac/Portability_of_checkpoints.pdf
>
> - Ashutosh Mehra
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/leyden-dev/attachments/20221223/29e571f9/attachment.htm>
More information about the leyden-dev
mailing list