Vertispan / j2clmavenplugin

Maven plugin to launch new J2CL compilation
https://vertispan.github.io/j2clmavenplugin/
Apache License 2.0
53 stars 26 forks source link

java bytecode ijar/turbine research work #150

Closed niloc132 closed 2 years ago

niloc132 commented 2 years ago

When a dependency changes in any way, we currently recompile all downstream projects and dependencies, as we can't detect if the changes matter or not. That is, a given task specifies its inputs (the project it depends on, and the file patterns that matter), and the contents of those inputs are hashed - when the hash of the inputs is different, we assume that the task must be re-run on those inputs.

For some things like running closure-compiler with compilationLevel=ADVANCED, this is true, practically any JS change could matter, plus or minus some whitespace changes. (The likelihood of whitespace-only changes is fairly low, though the cost of compilation is high, so this might possibly be a reasonable use case to test for if we can get it for free from https://github.com/Vertispan/j2clmavenplugin/issues/119.)

For javac and j2cl, this isn't the case, we can break down changes like this:

For at least the second two bulletpoints, we may be able to save ourselves from some recompiles by adding some work. Two basic plans to consider:

Evaluating performance of javac+ijar relative to turbine effectively requires implementing both options, but if we assume for the sake of argument that ijar costs no time/memory at all, we can pit turbine directly against javac. If performance of turbine is comparable or better, it seems easy enough to just use turbine for now (since we never use this stripped bytecode output). If it is substantially worse, we could still adopt it for projects in the current reactor, until ijar is evaluated.

Finally, turbine apparently is capable of running annotation processors, but it isn't clear to me what form that output would take. If the output is full source code and minimal bytecode, we would still need a custom step to strip GwtIncompatible types and members, but this starts to be a possible option to entirely replace unstripped javac as well.

treblereel commented 2 years ago

1) ijar: i have taken a look at sources and it can be rewritten to java, but the complexity of the task is medium to hard. What is nice, ijar has good tests so we can check that java port is one to one compatible with the original. As i can see, ijar is just a tool to process stripped bytecode, so no apt. 2) i did several turbine tests, it acts pretty much like javac, producing bytecode, but as far as i remember for j2cl we still need .java. 3) it's possible to write our own stripper, but i think it's better to investigate solutions we have at this moment, so i think, we should try turbine first.

niloc132 commented 2 years ago

See notes from https://github.com/Vertispan/j2clmavenplugin/pull/165#issuecomment-1118081459 for perf - for a production build from a clean checkout (i.e no cache, etc), the performance improvement seems to be something like 3-5% faster with no other changes made, only replacing the stripped-bytecode tasks. By itself, that seems like a clear win. Note that in this case is about the worst possible scenario for a build, since closure is still dominating the build times for an ADVANCED build.

That said, this means that the gains will be much higher (percentage wise) when doing BUNDLE_JAR builds, and should be tested at least lightly for j2cl:watch, but more heavily for clean builds with just optimizationLevel=BUNDLE_JAR to see what a "cold start" would look like. Without the ADVANCED build dominating the build times, they might drop from 100s down to, say, 30s, and that 5s is no longer a 5% improvement, but a 15% improvement.