This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
oeed's profile picture

Why does ComputerCraft perform so slowly?

Started by oeed, 03 January 2015 - 05:15 AM
oeed #1
Posted 03 January 2015 - 06:15 AM
As I've been remaking OneOS and trying to boost performance I've noticed both in Minecraft and in Java emulators that for what it's doing everything seems really slow. Things like drawing the screen sometimes result in a noticeable delay and progress from top to bottom.

I could probably improve it a little, but not by a ton. Is it just 'bad' coding, or is it actually just slow? If it is 'just slow', which I'm pretty sure it is given that the screen only has less than 1000 pixels, what's the cause? It doesn't seem to be Minecraft, at least significantly. Is it Java? LuaJ? Or just because Lua is a scripting language? It just seems that compared to the computer running the emulator or Minecraft, ComputerCraft is incredibly slow (noticeably in animations).
Bomb Bloke #2
Posted 03 January 2015 - 07:12 AM
Back in the day, I had an Amstrad system which took a notable fraction of a second to perform echo statements from within a batch file. Granted, that was a little while ago now, and technology has improved; but still… it amazes me that a Lua VM running within a Java VM which is also handling the rest of the MineCraft world whilst passing information between client/server threads can perform as well as it does.

There's a heck of a work-load involved.
oeed #3
Posted 03 January 2015 - 07:38 AM
Back in the day, I had an Amstrad system which took a notable fraction of a second to perform echo statements from within a batch file. Granted, that was a little while ago now, and technology has improved; but still… it amazes me that a Lua VM running within a Java VM which is also handling the rest of the MineCraft world whilst passing information between client/server threads can perform as well as it does.

There's a heck of a work-load involved.
Granted, but even in LuaJ emulators there seems to be bad performance there. It's not just because it's also doing Minecraft 'stuff' in the background.
SquidDev #4
Posted 03 January 2015 - 10:18 AM
I'm not an expert on LuaJ but I know a little, so most of this is an educated guess (thanks to LuaJ/JD-GUI).
  • LuaJLuaMachine uses org.luaj.vm2.lib.jse.JsePlatform (Line 44)
  • This uses the org.luaj.vm2.compiler.LuaC compiler which creates a org.luaj.vm2.Prototype object
  • This is run in the org.luaj.vm2.LuaClosure object with the execute method (Line 180)
  • This code is interpreted, so is quite slow.
This could theoretically be improved by using the org.luaj.vm2.luajc.LuaJC compiler, which compiles to Java bytecode and so is converted to machine code.

Another thing is the constant conversion between LuaString and String, LuaNumber and double, etc… There is probably some performance impact here.

I think this is all correct, but I might be completely wrong.
Edited on 03 January 2015 - 09:22 AM
Bomb Bloke #5
Posted 03 January 2015 - 10:54 AM
It's not just because it's also doing Minecraft 'stuff' in the background.

Didn't say it was - the point I was getting at is that there's a long list of factors. I'd say that the most significant of those are that you're running an interpreted language within the VM of another interpreted language. We're talking "overhead city".

If you simply start counting down through the layers, you can see that there's an extreme amount of cruft between your script and the processor of the computer that eventually executes it. Every computer has bios.lus in memory, usually CraftOS in memory, rednet.run as well (granted, only the last of those is doing anything other than squatting RAM, but)… and these days, if it's an advanced computer, multishell is upping the workload for any rendering calls considerably. And there's yet more Lua-based code in between all of that and the actual VM it's running in!
Edited on 03 January 2015 - 09:55 AM
Lignum #6
Posted 03 January 2015 - 01:44 PM
What's also an issue is that ComputerCraft runs every tick. That's 1/20 of a second. This means that loops are executed 20 times every second, which is not a lot as you can imagine.
SquidDev #7
Posted 03 January 2015 - 02:06 PM
What's also an issue is that ComputerCraft runs every tick. That's 1/20 of a second. This means that loops are executed 20 times every second, which is not a lot as you can imagine.

I don't think that is correct. ComputerCraft runs on a separate thread. Although only one computer can be 'running' at a time (as opposed to waiting for an event), and some things can only happen once per tick (HTTP requests are checked, sleep events etc…).
Bomb Bloke #8
Posted 03 January 2015 - 02:21 PM
It's true that any timer event you request will take at least one tick to fire (eg, sleep uses such an event, so sleep(0) will wait at least a twentieth of a second), but since you don't need to use timer events within every loop you create (even if you want them to yield at least once per iteration just for the sake of yielding), that's not a limitation of the loops themselves.

For example, the Draw() function in OneOS would execute faster if it just queued then pulled some random custom event, as opposed to using sleep(0).
Edited on 03 January 2015 - 01:29 PM
SquidDev #9
Posted 03 January 2015 - 04:51 PM
This really interested me so I've put a little experiment together. I ran ComputerCraft with and without Java bytecode compilation on CCEmuRedux. Running 1lann/GravityScore's benchmark script produces these results:


          | Current | Bytecode
==========|=========|===================
Text      | 16.25   |  7.6
Color     | 46.55   | 24.5
Advanced  | 31.75   | 14.35
Computing |  6.15   |  2.4  (Lower is better)

Overall   |-45.7    | 6.15  (Higher is better)

It is obvious that compiling to bytecode is quicker, but has quirks such as files with hyphens cannot be compiled (but I'm sure that could be avoided).

Without Window API: just in case you wanted it

            Current | Bytecode
==========|=========|===================
Text      |  4.9    |  2.75
Color     |  3.15   |  2.45
Advanced  |  6.1    |  4.85
Computing |  8.85   |  2.4   (Lower is better)

Overall   | 32.0    | 42.55  (Higher is better)
Edited on 03 January 2015 - 04:10 PM
MKlegoman357 #10
Posted 03 January 2015 - 08:22 PM
Wow, compiling to bytecode is more than two times faster. Looks like a good suggestion for ComputerCraft. Now just get Dan to see this.. BTW, compare the 'Computing' scores with and without window API with the current compiler solution.
oeed #11
Posted 03 January 2015 - 08:29 PM
It's true that any timer event you request will take at least one tick to fire (eg, sleep uses such an event, so sleep(0) will wait at least a twentieth of a second), but since you don't need to use timer events within every loop you create (even if you want them to yield at least once per iteration just for the sake of yielding), that's not a limitation of the loops themselves.

For example, the Draw() function in OneOS would execute faster if it just queued then pulled some random custom event, as opposed to using sleep(0).
Well, it work a bit differently now it's using Bedrock. I will certainly look in to removing the sleep calls though and replacing it with a custom event.

This really interested me so I've put a little experiment together. I ran ComputerCraft with and without Java bytecode compilation on CCEmuRedux. Running 1lann/GravityScore's benchmark script produces these results:


		  | Current | Bytecode
==========|=========|===================
Text	  | 16.25   |  7.6
Color	 | 46.55   | 24.5
Advanced  | 31.75   | 14.35
Computing |  6.15   |  2.4  (Lower is better)

Overall   |-45.7	| 6.15  (Higher is better)

It is obvious that compiling to bytecode is quicker, but has quirks such as files with hyphens cannot be compiled (but I'm sure that could be avoided).

Without Window API: just in case you wanted it

			Current | Bytecode
==========|=========|===================
Text	  |  4.9	|  2.75
Color	 |  3.15   |  2.45
Advanced  |  6.1	|  4.85
Computing |  8.85   |  2.4   (Lower is better)

Overall   | 32.0	| 42.55  (Higher is better)
Yes, it's quite evident that using machine bytecode is much faster, especially when running through a buffer such as the windowing API. I'll post a suggestion, if someone hasn't already, linking to this thread about changing.
SquidDev #12
Posted 04 January 2015 - 10:35 AM
Compare the 'Computing' scores with and without window API with the current compiler solution.

Yeah, I doubt that is actually the case, I only ran this test once and didn't repeat it so there will be some variation. Computing should be the same with/without the Window API.
MKlegoman357 #13
Posted 04 January 2015 - 01:32 PM
Yeah, I doubt that is actually the case, I only ran this test once and didn't repeat it so there will be some variation. Computing should be the same with/without the Window API.

I know, it just looked funny to me. I should've put that laughing emoticon there though.. :D/>