[HN Gopher] Stockfish.js
       ___________________________________________________________________
        
       Stockfish.js
        
       Author : tosh
       Score  : 119 points
       Date   : 2022-02-24 12:47 UTC (10 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | tediousdemise wrote:
       | Opened a random cpp source file, saw goto statements, and noped
       | out of there real quick.
        
         | ryeights wrote:
         | IMO, although it is not used in this codebase, the "goto error"
         | pattern for error handling is far more elegant and readable
         | than any non-goto-using alternatives. Goto can have its place
         | sometimes.
        
         | Cpoll wrote:
         | https://github.com/nmrugg/stockfish.js/search?q=goto
         | 
         | Five occurrences of goto, for anyone that's curious. The code
         | is pretty easy to read, good variable names, some explanatory
         | comments. The gotos don't make spaghetti. I'm inclined to think
         | the writers knew what they were doing, though goto offends my
         | sensibilities as much as anyone.
         | 
         | Could anyone with more experience explain the pattern? Why
         | gotos for control flow along with >thousand line functions?
        
           | mhink wrote:
           | Interesting. I was looking at the algorithm in evaluate.cpp
           | [0] and it seems to be the case that the control flow is
           | pretty much just an alternative to if-statements... which,
           | personally, I find to be _more_ readable than it 'd otherwise
           | be if it were heavily nested. I'm open to arguments
           | otherwise, though.
           | 
           | Consider two alternatives (written in pseudo-Javascript, I
           | guess):                   let xyz = 0;         if
           | (!condition1) {           doSomething();           xyz =
           | getValueSomehow();                      if (!condition2) {
           | doSomethingElse();             xyz +=
           | getSomeOtherValueSomehow();           }         }
           | finishUpBusinessLogic();         return xyz;
           | 
           | that seems much less readable than:                   let xyz
           | = 0;         if (condition1)           goto done;
           | doSomething();         xyz = getValueSomehow();
           | if (condition2)           goto done;
           | doSomethingElse();         xyz += getSomeOtherValueSomehow();
           | done:         finishUpBusinessLogic();         return xyz;
           | 
           | 0: https://github.com/nmrugg/stockfish.js/blob/d96c98872103c6
           | 0b...
        
             | kilburn wrote:
             | The hidden side-effects of your example code make it hard
             | to reformat, but in general people don't advocate for your
             | first example. The push is more towards defining smaller
             | logic blocks (with names that hint at what they do):
             | def computeSomething() {         if (condition1) return 0;
             | let value = getValueSomehow();         if (condition2)
             | return value;              doSomethingElse();
             | return value + getSomeOtherValue();       }            let
             | value = computeSomething();       finishUpBusinessLogic();
             | return value;
        
         | daniel-thompson wrote:
         | There are a total of 5 gotos in the codebase1. That's not bad
         | for a chess engine which is heavily optimized for runtime
         | performance above all other considerations.
         | 
         | 1 https://github.com/nmrugg/stockfish.js/search?q=goto&type=
        
         | ComputerGuru wrote:
         | Your loss.
        
         | Koffiepoeder wrote:
         | Thinking in absolutes is never a good idea when it comes to a
         | subjective matter (in this case: code style).
         | 
         | goto statements can and sometimes do have good use cases, for
         | instance finite state machines and error handling.
         | 
         | It's not because something is generally not a recommended
         | construct that you should never consider using it: in my
         | opinion you should use all the tools you have in your belt and
         | consider each use case separately to determine usefulness,
         | practicality and other criteria applicable to your project.
        
       | tromp wrote:
       | Chess engine performance is dependent on fast 64-bit integer
       | operations. How does this implementation deal with javascript
       | ints being limited to 32-bits? Is emscriptem somehow able to
       | generate code using WASM's 64 bit ints?
        
         | Kubuxu wrote:
         | It uses WASM which has 64bit integers.
        
           | brrrrrm wrote:
           | ^ this. Ref: https://webassembly.github.io/spec/core/syntax/t
           | ypes.html#sy...
        
           | johndough wrote:
           | Seems to be true. https://mbebenita.github.io/WasmExplorer/
           | emits i64.mul which is compiled to imul rax, rdi by firefox
           | for the following code snippet:                   #include
           | <stdint.h>                  uint64_t multiply(uint64_t a,
           | uint64_t b){             return a * b;         }
        
         | threatofrain wrote:
         | I believe JS has access to 64-bit.
        
           | petilon wrote:
           | JS has access to 64-bit floating point, not int.
        
             | pwython wrote:
             | Unless you're compiling from something like Cheerp.
        
             | tyleregeto wrote:
             | JS has BigInt support, a quick Google tells me this is
             | supported by wasm. I'm not sure if they are doing that here
             | or not.
             | 
             | https://developer.mozilla.org/en-
             | US/docs/Web/JavaScript/Refe...
        
               | tempay wrote:
               | BigInt is often orders of magnitude less performant than
               | int32 so it's unlikely to be helpful in this situation.
        
         | Cthulhu_ wrote:
         | Probably using JS's BigInt https://developer.mozilla.org/en-
         | US/docs/Web/JavaScript/Refe...
        
       | tiffanyh wrote:
       | How does this compare to stockfish-nnue.wasm [0] which is used on
       | Lichess.org [1]
       | 
       | [0] https://github.com/hi-ogawa/Stockfish
       | 
       | [1] https://lichess.org/source
        
         | jokethrowaway wrote:
         | NNUE is heavier but considered better
        
           | perihelions wrote:
           | That's not the distinction here: these are two different
           | Stockfish JS projects, both of which port the NNUE version.
        
       | perihelions wrote:
       | A related fork [0] powers the web-based tool on Lichess [1]. It's
       | a notable example of WASM in widespread use (I believe it's WASM-
       | by-default on every browser now).
       | 
       | [0] https://github.com/hi-ogawa/Stockfish
       | 
       | [1] https://lichess.org/analysis (in the top-right corner:
       | "Stockfish 14+ NNUE in local browser")
       | 
       | (edit: fixed link to the correct fork)
        
         | tiffanyh wrote:
         | FYI - the version you linked to is the "Slower fallback
         | versions of Stockfish for browsers (C++, WebAssembly,
         | JavaScript)" according to Lichess.
         | 
         | https://lichess.org/source
         | 
         | EDIT: nevermind, looks like you changed the link.
        
           | perihelions wrote:
           | Thanks, corrected link!
        
         | WithinReason wrote:
         | I wonder why Lichess doesn't use multithreading, it was working
         | in a previous version. I mean Brave can use 2 threads but I've
         | seen 8/16 max threads before.
        
           | [deleted]
        
           | JacobLinney wrote:
           | Lichess on chrome let's me use however many logical
           | processors I have. For whatever reason I can only get a
           | single thread on Firefox.
           | 
           | I'm not sure why either, because a while back I could use how
           | ever many threads I wanted on Firefox.
        
             | WithinReason wrote:
             | For me it's:
             | 
             | Chrome: 15 threads, 1 GB memory
             | 
             | Firefox: 1 thread, 256 MB
             | 
             | Brave: 2 threads, 128 MB
        
               | perihelions wrote:
               | What a puzzle. I have:
               | 
               | Firefox: 7 threads, 256 MB
               | 
               | Brave: 3 threads, 1 GB
        
           | tiffanyh wrote:
           | Lichess doesn't?
           | 
           | There's reference to thread support in the library
           | documentation.
           | 
           | https://github.com/hi-ogawa/Stockfish#threads
        
           | archseer wrote:
           | You can configure how many CPUs and memory to use under
           | settings
        
             | WithinReason wrote:
             | I know, that's what I'm talking about
        
       ___________________________________________________________________
       (page generated 2022-02-24 23:01 UTC)