On Thu, Jul 16, 2020 at 3:46 PM Romain Manni-Bucau <rmannibu...@gmail.com> 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 ;)). > 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? > 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. > Yes, well, I examined that, and I don't think it is possible unfortunately. More specifically, not with the StandardContext, but going straight to the final WebXml [and then figuring out caching for the SCI], which is similar. [Why did I do that ? Because I had added a code generator to the digester, and the digester parses all web.xml files and fragments] This will work just great from Tomcat perspective, the webapp will be just fine however I think there's a major problem: webapps and frameworks get a myriad of callbacks during the deployment process. So right there, going straight for the deployed webapp for sure won't be compliant :( Another factor to consider is if the user (interested in AOT) did his homework and tries to reduce the deployment cost of his webapps. It is possible to avoid SCIs (well, the handles types part), use metadata complete and have a big web.xml without tons of fragments. Then, is web.xml a super inefficient serialization for web.xml ? I'm not that convinced. Since I notice there's interest (well, curiosity mostly), I will try to add code generation to all the digester rules. This way it will generate code equivalent to web.xml files and we can see what it looks like. Rémy > 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. > > 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> a écrit : > >> On Mon, Jul 13, 2020 at 11:59 PM Filip Hanik <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 >>> 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 >> >>