What is the technology behind virtual machines?

Asked

Viewed 287 times

14

Besides Java and the environment .NET various other environments such as Python, Ruby, Moon, etc interpret bytecodes. In the first versions Java left to be desired in terms of performance, but the environment has evolved a lot and today has a good performance...

Of course the technology JIT helps a lot, and I also know that there are conceptual differences between the Vms (for example the VM Lua is based on registers, and not on stack, like the others), but is it just that? Or asking otherwise... theoretically using technology JIT, all the Vms could have similar performance?

1 answer

12


TL;DR - no, JIT is a weight factor, but it’s not the only one that influences the performance of a VM-based program.

Fundamentals

In general, any computer program goes through several steps of transformation from source code to machine code. The machine code itself usually also undergoes transformations - the one made by the CPU itself - in order to convert its instructions to microcode. Only this is actually executed. Still, it is not possible to program directly into a microcode, because what the processor expects - the type of input it can handle - is a machine language program, with its own format and characteristics.

What defines what can be in the machine code is what we call computer architecture. On the simplest machines - those without microinstructions - the architecture describes a real machine, with components that actually exist in physical form. In the others, it can be said that it describes a virtual machine (although this expression is not commonly used in this context). For what really exists is a machine capable of behaving as described in architecture, although underneath the scenes it is doing different things.

The x86 is an architecture. The System/360 also. Both employ microcode, meaning that each instruction in machine code is first converted into microinstructions and then executed by the CPU. This allows the same program to work on several successive generations of computers (e.g.: 386, 486, 586/Pentium, Core Duo), which far from being the same type of machine, implement increasingly advanced features (pipeline, superescalar, parallelism...).

To Maquina Virtual Java is simply another architecture: it defines a set of instructions, a processing model, etc., as if describing a real machine. The difference is that it was conceived primarily thinking of being implemented through software, although in principle it is perfectly possible to implement it in hardware - see picoJava.

Translation and Performance

As has already been said, what actually runs on the processor is not the machine code, but the microcode. For this reason, the same machine code can perform radically differently when transported from machine A to machine B, within the same architecture. Historically, when the Assembly Code (Assembly) was used a lot, there was the possibility - at least theoretical - that an optimization that explored a particular characteristic of a processor backfired, when changing the processor and realizingif the performance was even worse than if such optimization had not been done.

Anyway, this is a problem of the hardware designer, not the programmer - ensuring that the machine code translates into a correct and efficient microcode. However, the other transformation steps that lead from source code to machine code, these are done in software - and can lead to better or worse performance depending on the quality of this transformation.

One of the main challenges of designing a compiler is to take a program in the language A (higher level) and translate it into an equivalent program in the language B (lower level), so that it turns out correct and efficient. More sophisticated optimization techniques can produce better results, but will probably slow the compilation itself. This puts a limit on what a JIT compiler is able to do: because the running time of a Jitado program includes not only its execution but also its transformation into machine code. At first, then, I would say that a progrma Jitado will never achieve a performance as good as a pre-compiled program.

On the other hand, the gain in performance with optimizations is not always proportional to the time spent doing the same. A compiler that takes 10 minutes to compile will not produce a code 10x faster than another one that takes 1 minute. The marginal difference in performance becomes smaller and smaller as optimizations are made, until it gets to the point that it doesn’t compensate for more sophistication - not just for the extra compilation time, but for the extra time designing, implementing and testing the compiler.

Add that to Moore’s Law, and we have to overhead a JIT compiler becomes more and more insignificant as time passes, until eventually we reach the point where there is no noticeable difference in the performance of pre-compiled programs and Jitados (we are not there yet, however...)

(Another fact worth mentioning, although not directly asked, is that the JIT compilation offers its own benefits in relation to the traditional compilation, for example the Adaptive Optimization and the Recompilação Dinâmica; for this reason, in certain situations the performance of a Jitado program may be up to superior that of a pre-compiled program)

Stack vs. Register Architectures

As already mentioned, the programs go through a series of transformations until arriving in machine code. Some of these transformations take a complex instruction and break it into smaller instructions (e.g., if the target architecture is RISC), while others take several small instructions and combine them into one instruction. I can’t talk about CLR or VM Lua (or LLVM, Parrot, Squeak...), but I remember reading that something like this happens with JVM bytecodes.

If the end result will be programs with similar performance, I can’t say. My intuition says no: if the VM is stack-based, it loses the chance to make the most of real machine recorders (a common complaint regarding Java is the impossibility of a method returning more than one value - something that would be trivial to do with registers, but impracticable without breaking JVM compatibility). Conversely, if the VM uses registers but the actual machine does not (e.g., Lua running on the picoJava) - or even if the number of registers defined by the VM exceeds those supported by the physical machine - it is possible that a simple set of bytecode instructions will eventually become a much larger and less efficient set of instructions in the machine code.

Note that this is independent of whether the VM is Jitada or not; even a static compiler would have difficulties producing efficient code when translating between radically different architectures. (Again, this is my personal interpretation of the facts - without access to a person with practical knowledge in the implementation of Vms you can’t tell if these obstacles are easy or difficult to overcome)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.