jordanbray / chess

A rust library to manage chess move generation
https://jordanbray.github.io/chess/
MIT License
234 stars 54 forks source link

Only compile and expose selected features #32

Closed marmistrz closed 3 years ago

marmistrz commented 4 years ago

The crate currently takes a very long time to build. It would probably be a good idea to feature-guard the most compile-time-consuming parts of the crate and make it possible to disable their compilation. (opt-out) or possibly even move to opt-in in 4.x.

jordanbray commented 4 years ago

Currently, the slowest part of compilation is the build.rs which generates the lookup tables for the engine. Most chess (library/engine) developers don't build these at compile time, and just generate them once. That may be a smart thing to. Something about that bothers me, though with the whole "Don't put compiled objects in version control." rule.

It's worth noting it builds much faster in release as compared to debug builds.

There are a few options though:

  1. Thanks to newer versions of Rust, I believe that structures like BtBoard no longer need to be a struct, but can instead be a simple u64. This would drastically improve build-time in debug builds (and performance in debug builds), due to some optimizations that aren't done in debug builds. I don't think it would affect release builds, though.

  2. It's likely possible to optimize the lookup table generation. One simple trick is to try various seeds for the RNG, and simply pick the fastest one.

  3. Compile the lookup tables in like a normal person.

This would likely have to be a 4.x release.

marmistrz commented 4 years ago

You can query features in build.rs, just like in https://github.com/alexcrichton/curl-rust/blob/master/curl-sys/build.rs So a good start would be to put lookup table support behind a feature guard. And if the feature is a default one, we could avoid a 4.x release for now.

jordanbray commented 4 years ago

One question that remains un-answered is if you are doing debug builds (without optimizations) or not.

As for the rest, the lookup tables are really needed for the library in general. They are used for very core functionality (like move generation), and there are really no alternative algorithms that match them.

The question of generating the tables is more interesting. Should they be generated at compile time? If so, can that process be optimized?

The second part is why is building these lookup tables slow? I believe (based on research from years ago) the reason is that the structures (like BitBoard), are structures, and don't map natively to rust types (like u64). (BitBoard is a struct BitBoard(u64)). This causes rust to need optimizations turned on to optimize the operations on BitBoard.

The reason this was done is because in prior rust versions, it was not possible to implement a local trait on a built-in type. That's no longer true (IIRC), and the whole thing could be re-evaluated.

I'll take a look at the code this week sometime and see if there is anything that can reasonably be done.

marmistrz commented 4 years ago

If someone doesn't use move generation and only makes moves/parses FEN/just works with the board, then the tables are redundant. (for instance: if someone implements a chess client and delegates all the work to a UCI engine)

jordanbray commented 4 years ago

I'm not 100% sure even that is valid. The FEN-parser still needs to check sanity on the board, which means that it needs to ensure the current player is not in check. This uses the lookup tables as well.

These are used a lot throughout the library. I'm not sure feature-gating them is even possible in general, much less something I want to do. In addition, I think there may be other avenues to resolve this issue.

marmistrz commented 4 years ago

It looks like shakmaty has much shorter build times, (at least in debug mode it's < 12s) therefore if the compilation time is more important than runtime performance, shakmaty is probably preferred over chess.