Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Stockfish.js (github.com/nmrugg)
135 points by tosh on Feb 24, 2022 | hide | past | favorite | 32 comments


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


NNUE is heavier but considered better


That's not the distinction here: these are two different Stockfish JS projects, both of which port the NNUE version.


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)


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.


Thanks, corrected link!


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.


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.


For me it's:

Chrome: 15 threads, 1 GB memory

Firefox: 1 thread, 256 MB

Brave: 2 threads, 128 MB


What a puzzle. I have:

Firefox: 7 threads, 256 MB

Brave: 3 threads, 1 GB


Lichess doesn’t?

There’s reference to thread support in the library documentation.

https://github.com/hi-ogawa/Stockfish#threads


You can configure how many CPUs and memory to use under settings


I know, that's what I'm talking about


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?


It uses WASM which has 64bit integers.


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;
    }




I believe JS has access to 64-bit.


JS has access to 64-bit floating point, not int.


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...


BigInt is often orders of magnitude less performant than int32 so it's unlikely to be helpful in this situation.


Unless you're compiling from something like Cheerp.


Opened a random cpp source file, saw goto statements, and noped out of there real quick.


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.


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?


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/d96c98872103c60b...


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;


There are a total of 5 gotos in the codebase¹. That's not bad for a chess engine which is heavily optimized for runtime performance above all other considerations.

¹ https://github.com/nmrugg/stockfish.js/search?q=goto&type=


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.


I can still appreciate it no matter how bad the code quality is, because it works amazingly well and I don't have to maintain it myself.

If it works for the devs, then it's fine. Chess engines have a fairly low attack surface, all you have is moving pieces. Security is probably fine. Performance and strength are clearly fine.


Your loss.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: