JavaScript is pretty limited in sharing things across threads and the choices are to either pass around actual objects (terrible for the performance a chess engine needs) or using a "shared array buffer" (basically a byte array that can be accessed by multiple threads without having to pass it around).
Because the shared array buffer works on raw bytes, it's a bit tedious to work with. But it looks something like this:
Code: Select all
// You have to create a buffer and then, to work on it, create a view around it
const sharedBuffer = new SharedArrayBuffer((size * 1024 * 1024) / 16)); // size is defaulted to 32MB
const sharedDataView = new DataView(sharedBuffer);
// Setting an entry in the TT
function Set() {
// hash is a 64-bit value. Conversions to Number and BigInt here because of how Javascript handles the two
const index = Number(hash % BigInt(this.sharedDataView.byteLength)); // For 32MB, byteLength = 2097152
if (score > this.Checkmate) {
score += ply;
}
if (score < -this.Checkmate) {
score -= ply;
}
// For all these functions, the first parameter is the place in the buffer at which the value should be set, the "byte offset"
sharedDataView.setUint32(index, move, true);
sharedDataView.setUint8(index + 4, depth); // + 4 to offset from the 32-bit entry above (the offset is in bytes)
sharedDataView.setUint8(index + 5, flag);
sharedDataView.setBigUint64(index + 6, hash, true);
sharedDataView.setInt16(index + 14, score, true);
}
For the most part, this actually seems to work. Getting and setting TT entries in the byte array works. But...
Sometimes, the "byte offset" in the set or get methods (e.g. "setUint32(byteOffset, ...)") is greater than 2097152 (or whatever the byteLength of the buffer is). So for example, sometimes "index + 6" is greater than the byteLength of the buffer (it's not always the "index + 6" one, just using that as an example).
I'm sort of lost as to why the index/byte offset I'm getting is larger than it apparently should be. Am I missing something obvious?