On 7/20/20 8:47 AM, Romain Manni-Bucau wrote:


Le lun. 20 juil. 2020 à 17:41, Filip Hanik <fi...@hanik.com <mailto:fi...@hanik.com>> a écrit :

    Thanks for chiming in:

    On 7/16/20 6:46 AM, Romain Manni-Bucau wrote:
    Hi everyone,

    I think the generation is the sanest option since code stay clean
    but it shouldn't be done in tomcat IMHO but in user code and with
    a nice wrapper (mvn tomcat:dump/gradle tomcatDump etc, or
    whatever name you like ;)).
    That's always an option, but it would become an external artifact
    and easily end up out of sync.


Was thinking to keep the dumper in tomcat code base and the plugin to consume it so it would stay in sync, but agree it is a small risk.

    This build phase would dump the descriptors in plain java and
    would load them with an unique - ie single for the whole webapp -
    plain SPI - ServiceLoader - maybe?
    The goal of this artifact was to reduce the size and classes from
    a full tomcat (already available in tomcat-embed-core), down to a
    code base where XML/digester/descriptors aren't used, hence
    tomcat-embed-programmatic
    This kind of build tool assumes you have all the runtime state in
    the build - which is typically the case for graalvm - so you can
    completely dump StandardContext state after start phase there and
    just reload it from the precomputed model.
    Only trick is about file paths which must either be recomputed or
    be configurable to another base but it does not sound crazy.

    The less tool-ed option would be to extract all
    "reflectionfull" code in methods and use graalvm substitutions to
    drop them and use plain java instead (with a good naming
    convention, it can be generated as well).
    Keeps the duplication but at least the main code stays clean and
    optimizations stays together.

    That's pretty much what we're doing right now. Many of these feel
    like hacks simply to mitigate how GraalVM/AOT does code
    initialization (all code loaded initialized at startup)


Reviewing the hacks, all can be done cleanly if extracted in methods. Pushing the logic next step - I don't know if worth it but trying to use this picture to explain:

1. A noxml module can be done with protected methods/extension-points for XML loading - even usable in java standalone mode
2. Current tomcat can extend noxml module
3. Graal can be based on 1

This would benefit both jvm and graal users at the end.
Today 1 is possible with some hacks on tomcat embedded but it is highly not natural so this can be an opportunity to make it a feature maybe?

I believe that tomcat-embed-programmatic is a viable interim solution, it's a low risk. The question for you, and the rest of the community, is the reward itself enough? ie, is it worth it?

There is some talk about making "native-ness" part of the Java itself, and that could change a lot of assumptions. Making it a feature, refactoring code to satisfy 1, is a bit more intrusive at this point in time. I believe it introduces more risk than reward.


Filip


    Filip



    Romain Manni-Bucau
    @rmannibucau <https://twitter.com/rmannibucau> | Blog
    <https://rmannibucau.metawerx.net/> | Old Blog
    <http://rmannibucau.wordpress.com> | Github
    <https://github.com/rmannibucau> | LinkedIn
    <https://www.linkedin.com/in/rmannibucau> | Book
    
<https://www.packtpub.com/application-development/java-ee-8-high-performance>


    Le jeu. 16 juil. 2020 à 14:31, Rémy Maucherat <r...@apache.org
    <mailto:r...@apache.org>> a écrit :

        On Mon, Jul 13, 2020 at 11:59 PM Filip Hanik
        <fha...@vmware.com <mailto:fha...@vmware.com>> wrote:

            for discussion, all feedback and questions welcome:


            I've created a concept of having Apache Tomcat, embedded,
            run without reflection in a native image.
            This concept creates a jar,
            tomcat-embedded-programmatic.jar, that can be fine tuned
            to only include what is needed in a default configuration
            when an embedded tomcat instance is used and configured
            programatically.

            Steps to run Apache Tomcat using Java 8 without reflection

             1. Make sure you have native-image (from the graal
                installation) on your path
             2. git clone -b
                feature/embed-minimal-programmatic-jar-file-master
                g...@github.com:fhanik/tomcat.git
                <mailto:g...@github.com:fhanik/tomcat.git>
             3. cd tomcat/res/graal/
             4. ./build-tomcat-native-image.sh && ./graal-measure.sh

            Should yield an output similar to (Graal 20.1):
            SUCCESS: the servlet is working
            RSS memory: 20.7M
            Image size: 20.5M


            or using an older graal, 19.2
            SUCCESS: the servlet is working
            RSS memory: 18.0M
            Image size: 16.7M


            This also leaves a file named
            ${java.io.tmpdir}/XReflectionIntrospectionUtils.java so
            that you can review the solution to IntrospectionUtils.java

            Goals of this concept

             1. Do not break anything
             2. Create a new and optimized for size artifact,
                tomcat-embedded-programmatic
             3. Remove reflection by introspecting classes that are
                currently passed into
                IntrospectionUtils.set/getProperty by generating
                setters/getters at build time

            How it's done

             1. I've build out a small introspection tool in the
                package org.apache.tomcat.util.xreflect
             2. During build time, it analyses a set of known classes
                that are used with IntrospectionUtils.java, and
                generates XReflectionIntrospectionUtils.java
             3. When it packages tomcat-embed-programmatic.jar it
                uses the generated code when calling setProperty and
                getProperty

            A PR would look like this:
            
https://github.com/apache/tomcat/compare/master...fhanik:feature/embed-minimal-programmatic-jar-file-master?expand=1


        Well, this is a bit complex and hard to maintain (like, for
        example, storeconfig), so that's a downside.

        So starting with Tomcat and its initial server.xml, the
        process would be:
        server.xml -> equivalent Tomcat embedded code -> equivalent
        Tomcat embedded code with custom IntrospectionUtils code
        The concrete benefits may be limited though.

        I looked at more code generation for web.xml since the
        digester is nice for that, but the benefit becomes even more
        questionable. It is harder to manage, and the generated
        classes have to be loaded dynamically [unless even more code
        is generated]. If there are tons of fragments, there is a
        good intuitive reason why it becomes useless. so I didn't
        want to do it. I prefer if things remain a bit EE-ish,
        ultimately.

        Rémy

Reply via email to