[Mono-dev] Long execution time on first execution (in AOT case)

Martin Däumler mdae at cs.tu-chemnitz.de
Mon Aug 2 11:02:39 EDT 2010

On Fri, Jul 9, 2010 at 2:51 PM, Rodrigo Kumpera wrote:

> On Fri, Jul 9, 2010 at 4:06 AM, Martin Däumler <mdae at cs.tu-chemnitz.de
> <mailto:mdae at cs.tu-chemnitz.de>> wrote:
>     [...]
>     So, my question is: Is the method "mini_method_compile()" the only
>     place in Mono that triggers the JIT compiler on that level? Is there
>     way to trigger the JIT compiler that does not use the method
>     "mini_method_compile()"?
> No, there isn't.


thank you for that answer! It helped me a lot. Now, I have
a question about handling call instructions in AOT case.

In the standard JIT case, calling a method (in the assembly to be
executed) the first time actually means calling trampoline code
that triggers the JIT compiler and patches the call instruction.
Then, a second execution of the same call instruction directly
jumps to the JIT compiled code. Another call instruction to the
same (already JIT compiled) method requires patching by the
trampoline code (optimizations by the JIT compiler like inlining
are not considered). That is, every call instruction has to be
patched once in JIT case. Is that right?

Imagine following scenario: There are several methods to be called.
The execution time is measured the first time the methods are called.
In JIT case, this execution times includes JIT compilation, patching
and execution. Then, the same set of methods is called a second time,
however from another line of code. The resulting execution time would
include patching and execution, because JIT compilation was already
done in scope of the first execution. So, the second execution time is
much lower than the first one. Then, the method calls used in the
second execution are executed once more (maybe by using a loop or a
goto). The resulting execution time is even lower than the second
execution time because patching is already done so that the pure
execution time should be measured.

According to the documentation [1], calls from AOT code might use
the PLT (I am not sure if the abbreviation PLT does mean two different
tables in the documentation). However, "If the called method is in the
same assembly, and does not need initialization (i.e. it doesn't have
GOT slots etc), then the call is made directly, bypassing the PLT".
I want to know, what this "directly" means. Does a "direct" call
in AOT case require patching of call instructions? I am asking the
question, because I would expect a two stage timing behaviour in
the above-mentioned scenario. In scope of the first execution, the
AOTed code has to be loaded from disk, resulting in a high execution
time. The second execution should run very fast (comparable to the third
execution time in JIT case, that is, pure execution time). I would
also expect a two stage timing behaviour if calls to methods in the
same assembly go through a table, because the table has to be
initialized during the first execution.

In the above-mentioned scenario, however in AOT case, I found a three
stage timing behaviour very similar to JIT case. I am wondering,
because I observe the expected two stage behaviour if the set of
executed methods does not exceed 100 methods (or something like that).
If I measure the execution time of 1000 methods, there is a three stage
behaviour. Does call instructions have to be patched even in AOT case?
Or there are some compiler optimizations that work only to a certain
number of different call instruction?

I am thankful for every little help :-).

With kind regards,
Martin Däumler

[1] http://mono-project.com/Mono:Runtime:Documentation:AOT

More information about the Mono-devel-list mailing list