Another WebAssembly example: Meta tic-tac-toe

Dennis dkorpel at gmail.com
Wed Aug 22 12:22:34 UTC 2018


Try it: https://dkorpel.github.io/tictac/
Source: https://github.com/dkorpel/tictac

I planned to port an assembly Meta tic-tac-toe game to D for a 
while now, and with the recent addition of WebAssembly to LDC I 
saw the opportunity to do some client-side web-development in D. 
I first made the command line version (with -betterC in mind), 
and then added a Javascript back-end to it. Thanks to the image 
dithering example, I already was aware of most issues and 
limitations so it went smoothly. Here are the findings that I had:

1. I saw that my application was expecting 'env.memcpy' and 
'env.memset' to be present, I presume this is because the 
compiler emits these calls for struct/array 
copying/initialization. I solved it by providing simple 
implementations in the D code, hopefully that didn't have too 
much impact on performance.

2. The image dithering example had a JavaScript implementation to 
compare it to. I haven't made a JavaScript implementation, but I 
did compare how long the A.I. took to find a move with the 
command line version. Around 2 million moves were considered, 
here are the results:

| Version       | Time    | Factor |
|---------------|---------|--------|
| Ldc (release) |  357 ms | 1.0    |
| Dmd (release) |  671 ms | 1.9    |
| Wasm (-O3)    |  967 ms | 2.7    |
| Dmd (debug)   | 1651 ms | 4.6    |
| Ldc (debug)   | 2159 ms | 6.0    |
| Wasm (-O0)    | 2807 ms | 7.9    |

The WebAssembly version was tested in FireFox, in Chrome it seems 
to be ~1.5x slower for some reason.

3. Loading WebAssembly in a way that allows for both local 
testing and Github Pages deployment was annoying. The sample code 
from the wiki works on FireFox both locally and online, but 
Chrome complains you're loading a .wasm larger than 4Kb (16 Kb in 
my case) synchronously. I tried using fetch and 
instantiateStreaming, as suggested by:
https://developers.google.com/web/updates/2018/04/loading-wasm
But then when testing with live-server, it would complain about 
the request having an unknown MIME type. So I settled with an 
asynchronous XMLHttpRequest approach that works both offline and 
online, only for Chrome you still need live-server because for 
security it won't load requests using 'File://'.

4. I ran into some betterC issues:
- Final switch can't be used in debug mode since it throws an 
error in the default case. Solution: only compile in -release 
mode. See: https://issues.dlang.org/show_bug.cgi?id=19087
- Indexing `enum string[] messageStrings` with a runtime value 
gives a TypeInfo error. Solution: make it a __gshared immutable 
string[].
Related: https://issues.dlang.org/show_bug.cgi?id=19169, 
https://issues.dlang.org/show_bug.cgi?id=18949
- And, of course, the inability to use some language/library 
features. For this simple game it's okay, but for bigger projects 
I'd like to have some malloc/sprintf/math solutions.

5. Dub doesn't support WebAssembly targets. I solved this by 
making a build script that allows you to execute `rdmd build 
wasm` and then a simple refresh in the browser would show the 
results.

Overall it was very pleasant, kudos to the LDC team!


More information about the digitalmars-d-ldc mailing list