This project is dedicated to the memory of William Morris (aka Frags), who was the main contributor to the bounty but was unable to see the final result.

Sunday, February 17, 2013

Watch for the LED

Since there were too many complaints (too many > 2) about that it is hard to tell whether the JIT compiled code is active or not, I decided to implement a small on-screen indicator for it in this tiny update.

How does it work?

I extended the already available on-screen status line with one more "LED" which says: JIT.
If you turn on the OSD status line by adding the following lines into the configuration:

show_leds=true

Then you will find one more block at the end of the status line. This "LED" will lit up in bright greenish color as soon as the emulator executes JIT compiled code (instead of interpreted code).

Now, since the emulation is (and always will be) a mixture of JIT compiled and interpreted execution, it is not a simple task to find out how much of the executed code was JIT compiled and how much is interpreted.
To overcome of this complication the block will show you the ratio between the compiled and the interpreted code by changing the background color:
  • If more compiled code was executed then it is more vivid light green.
  • If the interpreted code dominated the execution then the color dims toward black
  • When the JIT is inactive (turned off by the configuration) or for any reason the compiled code is not used (cache turned off, blocks are too short, etc.) then the background color will be completely black.

Here you can see some example screenshots:

The indicator lits up light green: JIT compiled code is running mostly.

The indicator is still green, but more dark green:
a mixture of JIT compiled code and interpreted code is executed.
The darker means less JIT code.

The indicator is black:
JIT is turned off or the compiled code is not executed for some reason.
So, now you can tell by simply looking at the screen if the JIT is active and how much of the executed code makes use of the JIT compiling.

Tiny-tiny catch

I didn't want to add extensive statistical data collection into the compiled code, it would make it run a lot slower.
This implementation slows down the emulation a tiny bit, but not that much. Probably later on I will either remove it completely or add some configuration around it, so it could be turned off.

How does it really work?

To tell you the truth: the indicator doesn't show you exactly how much of the actual instructions are executed by the JIT or the interpretive, but it collects the data from executed code block types. This is cheating beacuse:
  1. The length of the blocks vary between 1 instruction and 20-30 (or sometimes even more) instructions. Still one block counts exactly once in the calculation, regardless of the size.
    This could be improved, but I didn't want to put too much effort into this implementation.
  2. Even inside the compiled blocks not all of the instructions are JIT compiled (as I described this in earlier posts). Thus it is possible that none of the instructions in the "compiled" block consist of actual JIT code, but simply calls to the interpretive implementation. It would be more fair to calculate the ration based on the executed instruction types instead of the block types.
    Now, I would rather not change this for sake of performance. As long as most of the instructions are implemented, this won't affect the results too much. (And that is not true just yet, but will be improved overtime.)
So, bottom line: take this indicator results with a grain of salt.

Still cool, eh? :)

10 comments:

  1. Tested KidChaos on latest build:

    When run, still the same 4 yeallow crashes in loop, then cractro starts. While crashes happens, JIT led from time to time blink by green. But not offten, and its more offten just a black.

    Then cracktro starts, on screen happens some visuall effects, music plays and JIT led fully black at this moment (but in the shell latest string is JIT: change cache emulation: enabled).

    So we can say, that jit is no use when cractro starts, and maybe it is interaptive already (even if we have in the shell output about "enabled").

    Then i press mouse button to start a game itself.

    While loading of game happens, JIT lead blinks a lot. Id say like "hdd-led" when something is loaded from hdd. But when first part of game is shown (who do game, etc), its blinks not very offten. And when menu itself showns (music plays, etc), then JIT led is blinking, yep, but the color of led is more or less dark green (in other words, like jit works "a bit" ).

    Then, i choice "new game". And while game loads, then JIT is blinking pretty much offten. Then, when game actually starts: jit led fully black all the time, never blinks at all and game works the same slow as without jit (music jerky , etc, and game just asks for frame-skips).

    So, as result: in game itself JIT not working at all by some reassons, while working on loading, in menu, and co. The same as for Cractro of the game: for loading jit works, but when actual stuff happens visually, jit make nothing.

    ReplyDelete
    Replies
    1. Thanks. Interesting results. I have no explanation why the JIT is not working much while the game is loaded. What about the console? Is there any indication if the cache was enabled while the actual game was running?

      Delete
  2. @Almost
    I just make more tests with better explains, and in brief: JIT never works in any games (i.e. when i actually start to play), but works in menus, on loading, etc. Check this out:

    -----Brion The Lion AGA:
    jit enables at begining, led blinks (mostly dark and a bit light green), and when first images showsn, in shel we have: JIT: Change cache emulation: disabled and since then, not in menu, not in game JIT never blinks

    -----Lion King AGA:
    jit enables at begining, led blinks (mostly dark and a bit light green), yellow crash in loop (3-4 times), then cractro starts. When visuall effects happens and music plays, jit never blinks always black. Only when by mouse change screens in cractro JIT a bit blinks. Then exit from cracktro, jit a bit blinks, game start to loads: jit mostly black at this loading, sometime blinks a bit. At the end of loading blinks a lot. Then when menu of game showns, jit stays fully black and a bit, a very little bit sometime blinks. Just its even not noticable, but if check closer, then visibly that some very small blink from black to a bit more light black happens. Then "start game". While loading JIT blink quite ok. When game starts, jit fully black. I play about 10 minuts , and JIT never blinks at all.

    ----SlamTilt AGA:
    jit enables at begining, led blinks at loading, then when cractro starts in shell "jit: cachen cache emulation: disabled". So in cractro of course jit since then no blinking at all. Then game starts, in the shell its again bring me few "jit: cache emualtion disabled", then game starts , but JIT never blinks and never enables.

    ---Technologic Death demo.

    Sure it is not AGA, but i still use the same settings as for other games (020/AGA and so on), so should be ok as caches is here and co. So, It starts, jit enables, blinks pretty ok on loading and loading happens pretty fast. Then when it starts, music start to plays, first effect come out, and EUAE solid freezes by itself. OS4 is ok, but euae itself can't be even closed. Thats of course pretty understanable and expected, as demos quite heavy use every single instructions and if there is any bug, its will be very visibly. I even think that testing with demos which works on interraptive with 020/aga and enabled caches even better in compare with games. I tryed of course the same config 1:1 just with disabled cachesize=8192 line, and demo works fine , so its good enough for JIT testings imho. Btw, to add: while JIT is really disabled and led not blinks when i do tests with disabled cachesize, then in the shell i still have "JIT: change cache emulation: enabled", while in reality it is not and that all make me think that its even not so matter to check what shell output says :) ).

    ReplyDelete
    Replies
    1. @kas1e

      Note that the LEDs are affected by the frame refresh rate. If the JIT LED blinks 25 times per second and you have gfx_framerate=2 in the config, then you might see it as solid green or solid black, instead of it blinking. The JIT LED blinks here on the Lion King AGA's main title screen, but if I fiddle with the frameskip hotkeys a couple of times I can get it to look like it's staying black.

      During gameplay, it is actually black though, but blinks a little if you die and respawn.

      Delete
  3. @mick
    I do all tests without frame skips, so we can say that in games itself it not working mostly. Maybe because of non implementing instructions, maybe because by some reassons caches disables (but we have no notice about in shell), or maybe just some small bugs :)

    ReplyDelete
  4. Thanks for the testing, guys. At the moment I have no clear explanation why the JIT is disabled too often. It has nothing to do with the not implemented instructions, as I explained in the last part of the post: even if none of the instructions are implemented in the block still the block considered as compiled code.

    There are only a handful of conditions that would prevent the JIT compiled code from running:

    1. The block is too short (less than 4 instructions): the overhead of calling the compiled code is too much, so I disabled the compiling of these blocks.

    2. The block is not compiled before it was executed at least 4 times by the interpretive, this way we can avoid of compiling the initialization code which won't be run more than once, the self-modifying code is more close to the final form and some data can be collected for the JIT compiled code.

    3. When the instruction cache is flushed then all the compiled code is thrown away.

    As it seems to me at the moment we are dealing with the 3. option here. The cache handling is not done yet fully, the blocks doesn't need recompiling all the time and there is no need for flushing the whole buffer just because some parts of the memory was flushed out of the cache. There is room to improve this piece, definitely.

    But I need to test this, so I will check it soon.

    ReplyDelete
    Replies
    1. @Almos
      Btw, just in case, i tryed on latest "led" build also whdload games again, and they the same as before give me red-gurus:

      ----
      Software Failure , Press left mouse button to continue
      Error: 0000 0006 Task: 00202258
      ----

      What mean that it wasn't because of "move" bug, but something else..

      Delete
  5. I tested some games on MorphOS e-uae:
    Lotus2: No (markable) speedup, even if the JIT LED is (dark) green. If you set cycle exact, the game is smoother with the sound. JIT LED is blinking like a HDD LED (as kas1e also explained)
    Apidya: With Activated JIT the game runs until the action starts. The background of the scene will be rendered, but the wasp doesn't show up. No blobs at all and then it crashes. Without JIT, it works.
    Lemmings: No chance to use the JIT, because it won't run with 68020 or higher.
    Workbench 3.5: with JIT: Guru Meditation. Without JIT: works.

    ReplyDelete
    Replies
    1. Cycle exact setting for the CPU is ignored when the CPU type is not M68000. However, it is linked with the Blitter cycle exact mode, which might cause the smoother graphics probably.
      Thanks for the reports, I will check some of the crashed programs, maybe I can fix some bugs.

      Delete
  6. I have checked what is going on with the JIT, why the LED stays dark while the demos/games are running.
    As it turned out: the JIT is working, but there is a simple rule that generates the confusion. Any block consists of less than 4 instructions won't be compiled. Now, when these demos/games are running there is only very small amount of time spent on doing anything useful, mostly these are waiting for some special event (interrupts mostly).
    Wait cycles are usually small, just a loop, or even only one instruction to jump back to its own address. The rest is happening in the interrupt context, for example when the screen refreshing hits the invisible area (vertical blank).

    So, the simple answer to this question is: because most of the time is spent in these waiting loops which are not emulated by the JIT compiled code due to the 4 instructions rule, these are outbalance the JIT code for the indication. It doesn't mean that the executed code is running slow, it is just hard to show.

    There are three ways to fix this:

    1. Fix the calculation by taking account if there was any JIT compiled code and set the LED halfway lit at least. (Hello Apple! You did this with the antenna problem... ;)

    2. Remove the checking for the tiny blocks and compile them anyway.

    3. Keep the execution inside the blocks if a certain amount of instructions are not executed yet.

    While the first solution would be more like a fix for the perception, second one is a step backward for the sake of measurability.
    As I already explained previously, calling a compiled block takes some effort, therefore it does not worth to call the block for only a few instructions. The overhead of the calling can be more than the execution of the instructions under the interpretive emulation.

    I confirmed that the LED lit bright when I removed the checking for the small blocks. Yet nothing ran faster, which is not surprising knowing that these blocks won't matter anyway.

    There is the third possibility, which would be good for other reasons too: this way the overhead of calling the blocks can be minimized. But that is much more complex to implement, I took a note of that possibility, maybe I can do something for it later on.

    For the next release I am going to remove the checking for the block size, we can do some optimization on this later on.

    ReplyDelete