-
Notifications
You must be signed in to change notification settings - Fork 9
Activity
Hi nickdrozd,
Thanks for your detailed analysis write up!
It is useful indeed.
I'm planning to rewrite the eboy-write-display-unicode to use with-temp-buffer and buffer-string as was suggested in an earlier comment. This will remove the cons'ing and write directly to a buffer.
As for your first point. Earlier I had a big case switch, looking like this:
(defun eboy-process-opcode (opcode flags)
"Process OPCODE, cpu FLAGS state."
(cl-case opcode
(#x00 (incf eboy-clock-cycles 4))
;; LD nn,n
(#x06
(setq eboy-rB (eboy-get-byte))
(eboy-inc-pc 1)
(incf eboy-clock-cycles 8))
(#x0E
(setq eboy-rC (eboy-get-byte))
(eboy-inc-pc 1)
(incf eboy-clock-cycles 8))and when I switched to the vector jump table with O(1) access, it was quite a speed improvement.
But maybe I could have done something in a more clever way in the switch case, since I read somewhere that it should be automatically be compiled into a jumptable.
Because the lamda functions are also causing a performance penalty, it is interesting to revisit this.
If you are welcome to investigate this if you like.
I tried running Eboy under the new Emacs native compile branch. The speedup is substantial, with the reported FPS going from 0.2 to 1.1. From the user perspective, this means Tetris is almost playable! That doesn't sound like much, but it's a big step up from "Is this thing frozen?"
Here's a little bit of recent CPU profiling data:
37800 95% - eboy-load-rom
36061 90% - eboy-run
15709 39% - eboy-lcd-cycle
15684 39% - eboy-debug-update-fps
15004 37% - eboy-write-display-unicode
4184 10% - eboy-get-color-xy
822 2% eboy-get-tile-id
485 1% eboy-get-color
142 0% eboy-display-sprites
16 0% eboy-get-color
10567 26% + eboy-process-opcode
2 0% + eboy-process-interrupts
Yo! This project is awesome. I don't know much about hardware or
low-level programming in general, so I'm excited to find out how the
whole thing works.
As I'm sure you're aware, performance is an issue at the moment. On my
crappy little Thinkpad, it takes several minutes to go from loading
Tetris to the second piece appearing during gameplay.
So I profiled for CPU time, running the interpreted code (commit
937e63c) from loading until the second Tetris piece appears. Here are
the results, with irrelevant stuff cut out:
48% of CPU time spent in garbage collection, ouch! That means that too
much garbage is being created. Cutting down on that should have a
significant impact on performance.
So I profiled for memory.
Those numbers are for the interpreted code. Byte compiling makes a big
difference. Here is the memory profile for the byte compiled code
running all the way until the Tetris pieces reach the top of the
screen:
And the CPU profile for the byte compiled code:
Based on this data, I have some ideas on how to improve some critical
sections:
The CPU is currently vector filled with argument-less lambdas. This
could be replaced with a big case switch statement. That would be
uglier, but I think it would consume less memory.
eboy-write-display-unicodecontains this section:Multiple conses are made in a very tight loop, and this consumes a lot
of memory. This would more efficient with vectors instead of lists.
I hope this is useful.