1322722 937 s net.sdo.StockPriceHistoryImpl::process (248 bytes)
Note that both the OSR-compiled constructor and the standard-compiled methods have been
made not entrant, and some time much later, they are made zombie.
Deoptimization sounds like a bad thing, at least in terms of performance, but that isn't neces-
sarily the case. The first example in this chapter that used the stock servlet application meas-
ured only the performance of the URL that triggers the StockPriceHistoryImpl path. With
a 300-second warm-up, recall that test achieved about 24.4 OPS with tiered compilation.
Suppose that immediately after that test, a test is run that triggers the StockPriceHis-
toryLogger path—that is the scenario I ran to produce the deoptimization examples just lis-
ted. The full output of PrintCompilation shows that all the methods of the Stock-
PriceHistoryImpl class get deoptimized when the requests for the logging implementation
are started. But after deoptimization, if the path that uses the StockPriceHistoryImpl im-
plementation is rerun, that code will get recompiled (with slightly different assumptions),
and we will still end up still seeing about 24.4 OPS (after another warm-up period).
That's the best case, of course. What happens if the calls are intermingled such that the com-
piler can never really assume which path the code will take? Because of the extra logging,
the path that includes the logging gets about 24.1 OPS through the servlet. If operations are
mixed, we get about 24.3 OPS: just about what would be expected from an average. Similar
results are observed in the batch program. So aside from a momentary point where the trap is
processed, deoptimization has not affected the performance in any significant way.
The second thing that can cause code to be made not entrant is due to the way tiered compil-
ation works. In tiered compilation, code is compiled by the client compiler, and then later
compiled by the server compiler (and actually it's a little more complicated than that, as dis-
cussed in the next section). When the code compiled by the server compiler is ready, the
JVM must replace the code compiled by the client compiler. It does this by marking the old
code as not entrant and using the same mechanism to substitute the newly compiled (and
more efficient) code. Hence, when a program is run with tiered compilation, the compilation
log will show a slew of methods that are made not entrant. Don't panic: this “deoptimiza-
tion” is in fact making the code that much faster.
The way to detect this is to pay attention to the tier level in the compilation log:
40915 84 % 3 net.sdo.StockPriceHistoryImpl::<init> @ 48 (156 bytes)
40923 3697 3 net.sdo.StockPriceHistoryImpl::<init> (156 bytes)