Live data from Hacker News

GoSpeccy: A concurrent ZX Spectrum Emulator Written in Go

github.com

1–9 of 9 posts

Re: GoSpeccy: A concurrent ZX Spectrum Emulator Written in Go

#4
Every month or so, somebody drops by the bsnes[3] forums asking why bsnes pegs one CPU core and leaves the others idle, instead of using each core equally. The answer, of course, is that a SNES has a number of different processing units all running at different speeds, and it's much more efficient to design the emulation core with coöperative multi-tasking[4] than with OS threads. Since bsnes is implemented in C++, I've wondered whether a language more focussed on concurrency could make a multi-threaded emulator possible, but it looks like GoSpeccy isn't a particularly useful example of it.

From the "Architecture" page[5]: In consequence, the whole emulation core is basically just one goroutine

[3]: http://byuu.org/bsnes/

[4]: Like, ridiculously more efficient, making it possible to sync millions of times per second. The system bsnes uses is called "libco", and although it doesn't have its own web-site, you can browse the code here: http://gitorious.org/bsnes/bsnes/blobs/master/bsnes/libco/

[5]: https://github.com/remogatto/gospeccy/wiki/Architecture

Re: GoSpeccy: A concurrent ZX Spectrum Emulator Written in Go

#5

Every month or so, somebody drops by the bsnes[3] forums asking why bsnes pegs one CPU core and leaves the others idle, instead of using each core equally. The answer, of course, is that a SNES has a number of different processing units all running at different speeds, and it's much more efficient to design the emulation core with coöperative multi-tasking[4] than with OS threads. Since bsnes is implemented in C++, I…

One OS thread per task is not the only way to parallelize a program. If you have a runtime system that allows the creation of light-weight tasks that can be executed by pre-existing OS threads, you can exploit very fine grain task parallelism. See The Implementation of the Cilk-5 Multithreaded Language: http://supertech.csail.mit.edu/papers/cilk5.pdf

Re: GoSpeccy: A concurrent ZX Spectrum Emulator Written in Go

#6
post #5

Every month or so, somebody drops by the bsnes[3] forums asking why bsnes pegs one CPU core and leaves the others idle, instead of using each core equally. The answer, of course, is that a SNES has a number of different processing units all running at different speeds, and it's much more efficient to design the emulation core with coöperative multi-tasking[4] than with OS threads. Since bsnes is implemented in C++, I…

One OS thread per task is not the only way to parallelize a program. If you have a runtime system that allows the creation of light-weight tasks that can be executed by pre-existing OS threads, you can exploit very fine grain task parallelism. See The Implementation of the Cilk-5 Multithreaded Language: http://supertech.csail.mit.edu/papers/cilk5.pdf

That's right. In Go such light-weight tasks are called goroutines.

Quoting from Effective Go[1]:

A goroutine has a simple model: it is a function executing in parallel with other goroutines in the same address space. It is lightweight, costing little more than the allocation of stack space. And the stacks start small, so they are cheap, and grow by allocating (and freeing) heap storage as required.

Goroutines are multiplexed onto multiple OS threads so if one should block, such as while waiting for I/O, others continue to run. Their design hides many of the complexities of thread creation and management.

[1] - http://golang.org/doc/effective_go.html#goroutines

Re: GoSpeccy: A concurrent ZX Spectrum Emulator Written in Go

#7
In the real speccy, you could double the horizontal resolution from 192 lines to 384 lines, and also get different colors for each 8x1 (or 8x0.5 if extending to 384) by changing the screen bitmap while the scanline is being generated.

Pixel timing accurate emulators exist -- in fact, C64 games written after ~1990 are useless without it.

Re: GoSpeccy: A concurrent ZX Spectrum Emulator Written in Go

#8
post #7

In the real speccy, you could double the horizontal resolution from 192 lines to 384 lines, and also get different colors for each 8x1 (or 8x0.5 if extending to 384) by changing the screen bitmap while the scanline is being generated. Pixel timing accurate emulators exist -- in fact, C64 games written after ~1990 are useless without it.

The "8x1 mode" and border effects do work in GoSpeccy. You can try the Overscan demo (http://www.worldofspectrum.org/infoseekid.cgi?id=0007636).

GoSpeccy does not support any 384 line mode. As far as I know, the horizontal resolution is 256 pixels, so doubling that would yield 512 horizontal pixels.

Re: GoSpeccy: A concurrent ZX Spectrum Emulator Written in Go

#9

Every month or so, somebody drops by the bsnes[3] forums asking why bsnes pegs one CPU core and leaves the others idle, instead of using each core equally. The answer, of course, is that a SNES has a number of different processing units all running at different speeds, and it's much more efficient to design the emulation core with coöperative multi-tasking[4] than with OS threads. Since bsnes is implemented in C++, I…

"I've wondered whether a language more focussed on concurrency could make a multi-threaded emulator possible, but it looks like GoSpeccy isn't a particularly useful example of it."

I think you are wrong. OK, it is true that the "emulation core" in GoSpeccy is not using any parallelism (the emulation core is fast enough, so what would be the reason for a parallel implementation there?), but it has a more concurrent design than (all?) other Spectrum emulators.

The part where you are wrong is that all video and audio postprocessing in GoSpeccy is designed to run in parallel to the hardware emulation (Z80 CPU, ULA chip). As I explained in [https://github.com/remogatto/gospeccy/wiki/Architecture], there are not many things which actually run in parallel, because the emulator is fast enough (50 frames per second).

But you can try the following: load some Spectrum game or demo that is painting to the screen a lot. Set scale to 2. Then increase FPS from 50 to 150 (or more, if you have a faster computer) and observe that the GoSpeccy Linux process will be automatically using more than 1 x86 CPU core. And it will manage to play sound without any hiccups. (But, of course, if you increase the FPS even more, you will reach a point where sound buffer underruns start to happen.)