www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.ldc - Another WebAssembly example: Meta tic-tac-toe

reply Dennis <dkorpel gmail.com> writes:
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!
Aug 22 2018
next sibling parent reply Allen Garvey <allen.garvey gmail.com> writes:
Cool project, and nice job on the readme as well.

On Wednesday, 22 August 2018 at 12:22:34 UTC, Dennis wrote:
 The WebAssembly version was tested in FireFox, in Chrome it 
 seems to be ~1.5x slower for some reason.
Were you using Chrome for Mac by any chance? In my testing with the dithering example Chrome specifically on Mac had by far the slowest WebAssembly implementation.
 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://'.
While instantiateStreaming is definitely the future, be aware that this is not supported on Safari or Edge yet. I believe it is technically in the spec that WebAssembly has to be served with application/wasm mime type for instantiateStreaming, but in my testing Chrome doesn't care while Firefox does. The problem is that most web servers now don't currently serve the correct mime type out of the box (such as npm httpserver or Python simplehttpserver) so I had to use a custom node server (https://github.com/allen-garvey/wasm-dither-example/commit/5cd5baf84b681074de4e 7af4c224103e17a3827 https://gist.github.com/aolde/8104861) so I could set the mime type manually before I switched to instantiate since it has wider browser support.
Aug 22 2018
parent Dennis <dkorpel gmail.com> writes:
On Wednesday, 22 August 2018 at 15:09:36 UTC, Allen Garvey wrote:
 Were you using Chrome for Mac by any chance? In my testing with 
 the dithering example Chrome specifically on Mac had by far the 
 slowest WebAssembly implementation.
I'm using Chrome 68 and FireFox 61 on Windows 10, on Debian I have FireFox ESR 52 which doesn't have WebAssembly support. I just tried Microsoft Edge 42 and it seems to be the same as FireFox. On Wednesday, 22 August 2018 at 15:09:36 UTC, Allen Garvey wrote:
 The problem is that most web servers now don't currently serve 
 the correct mime type out of the box (such as npm httpserver or 
 Python simplehttpserver) so I had to use a custom node server 
 (https://github.com/allen-garvey/wasm-dither-example/commit/5cd5baf84b681074de4e
7af4c224103e17a3827 https://gist.github.com/aolde/8104861) so I could set the
mime type manually before I switched to instantiate since it has wider browser
support.
Thanks for the info.
Aug 22 2018
prev sibling next sibling parent kinke <kinke libero.it> writes:
On Wednesday, 22 August 2018 at 12:22:34 UTC, Dennis wrote:
 [...]
Interesting read, thx! [I've added it as further example to the Wiki page.]
Aug 22 2018
prev sibling next sibling parent reply Trass3r <un known.com> writes:
On Wednesday, 22 August 2018 at 12:22:34 UTC, Dennis wrote:
 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.
It does get vectorized, but it is a lot of code: https://d.godbolt.org/z/zRgHuR
Aug 22 2018
parent Trass3r <un known.com> writes:
I guess  noalias and  nonnull LLVM parameter attributes would be 
useful here as memcpy does not allow overlapping arrays and 
passing null is undefined behavior.
Aug 22 2018
prev sibling next sibling parent Mike Franklin <slavo5150 yahoo.com> writes:
On Wednesday, 22 August 2018 at 12:22:34 UTC, Dennis wrote:
 Try it: https://dkorpel.github.io/tictac/
 Source: https://github.com/dkorpel/tictac
 Overall it was very pleasant, kudos to the LDC team!
And kudos to you! Very nice work, I hope to see more. Mike
Aug 24 2018
prev sibling next sibling parent Arun Chandrasekaran <aruncxy gmail.com> writes:
On Wednesday, 22 August 2018 at 12:22:34 UTC, Dennis wrote:
 Try it: https://dkorpel.github.io/tictac/
 Source: https://github.com/dkorpel/tictac
Didn't knew about Meta Tic Tac Toe. This is wonderful and then to see it written in D and Webassembly. Thank you and LDC team!
Aug 29 2018
prev sibling parent reply Arun Chandrasekaran <aruncxy gmail.com> writes:
On Wednesday, 22 August 2018 at 12:22:34 UTC, Dennis wrote:
 Try it: https://dkorpel.github.io/tictac/
 Source: https://github.com/dkorpel/tictac

 [...]
This could make a nice article for D blog.
Aug 29 2018
parent Johan Engelen <j j.nl> writes:
On Wednesday, 29 August 2018 at 19:35:46 UTC, Arun Chandrasekaran 
wrote:
 On Wednesday, 22 August 2018 at 12:22:34 UTC, Dennis wrote:
 Try it: https://dkorpel.github.io/tictac/
 Source: https://github.com/dkorpel/tictac

 [...]
This could make a nice article for D blog.
Really cool indeed! Definitely nice for a blog post. Cheers, Johan
Aug 30 2018