Simplifying code

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Simplifying code

Post by Henk »

I go for simplicity and testability. Factor it by using a wrapper/functor or something like that. So the 'wrapper' should be able to be tested in Isolation. Also code should only depend on interfaces or abstract classes when possible.
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Simplifying code

Post by Henk »

Maybe next step in my engine's code is to hide (bit)board (representation) if it isn't too late for that.

Looks like I violated many good software engineering principles only to win maybe 20% speed.

Abstract datatypes. A concept already known in the eighties. How stupid can one be to ignore that only to win some cpu cycles.
Even functional programming is from the eighties.

I mean my engine is already so slow. It can almost afford anything.
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: Simplifying code

Post by mvanthoor »

What language are you writing in?

If the engine is slow, then fix that first, after fixing the bugs. In a chess engine, speed is your currency. Because it's slow, you CAN'T afford anything, actually.

When being careful and not haphazardly using any feature I come across, I can just follow programming best practices without speed loss. As you may have seen in the Perft optimization topic, I've been refactoring myself. Case in point: I wanted the move generator out of the board. There are two possibilities to properly do that:

1. Use a global static struct (in Rust, with lazy_static)
2. Build a superstruct that encompasses the smaller components. In this case, it's called "Engine", but in some languages this construction is the default, where such a struct/class is called "App".

I've tried the first option, as it was the easiest. It was implemented in 15 minutes and worked great. Only problem was... lazy_static turned out to be slow. The engine dropped 35% (!) in speed.

Then I tried option 2, create the "Engine" struct. This struct is going to hold all the "global" stuff such as the move generator, evaluation, hash tables... and so on, and the functions to use those things. Then I just throw a board at the struct Engine, with something like this:

Code: Select all

engine.perft(&mut board, 6);
Then the engine calls the underlying "real" perft function and provisions it with everything it needs. This way I've been able to refactor the move generator out of the board. It was about half an hour of work (and I still need to move some functions to a more logical place as a result of this refactor), but the engine retained its original speed. If anything, it is a few tens of seconds faster again as far as I can see.

That is what I meant with "haphazardly using functionality". I could have implemented lazy_static, confirmed that it worked, and call it a day; that would have cost me 35% speed. For Rust and my engine, the second solution is a somewhat more complex (but still a best-practice) option, that is much faster.

What I'm trying to say is that refactoring a code base into something that uses good programming practices, doesn't HAVE to cost a huge amount of speed.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
Dann Corbit
Posts: 12537
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: Simplifying code

Post by Dann Corbit »

Don't forget the famous Einstein quote: "Things should be made as simple as possible, but no simpler."
The most important thing for your code is for you to understand it at a glance.
But don't cut functionality to make it simpler, unless it is buggy. In such a case, simplify to the simplest possible base case and work up
Taking ideas is not a vice, it is a virtue. We have another word for this. It is called learning.
But sharing ideas is an even greater virtue. We have another word for this. It is called teaching.
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Simplifying code

Post by Henk »

mvanthoor wrote: Mon May 11, 2020 9:05 pm What language are you writing in?
C# so it does not force you to create a .h file like in C++.

So when in a hurry you omit that. Result bad code.

Looks like hiding bitboard representation difficult. Much code using bitboards.
[Other things to do. Like learning for instance .Net core Entity Framework etc]
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Simplifying code

Post by Sven »

Again. Focus on finding and fixing bugs. Not on language, not on speed. And I would not focus on simplification as well at this very moment, since you would probably replace old, complex, buggy code by new, less complex but still buggy code. Finding bugs and understanding why they happened will help a lot for the future, including to learn how to avoid them. And to learn how to find bugs ...

A bug can also be to use a wrong concept, of course. In that case you actually need to rewrite some code.

Simplification is a good preparation for making changes later on without breaking the code. It helps to understand correct code better, and to make it easier to maintain. But it does not necessarily help to see the bugs in the old code.
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Simplifying code

Post by Henk »

I don't care about bugs for now. Bitboards is an implementation detail. A representation. So it should be hidden.
Bugs is result of missing test cases.
Don't know how to fix bad interpreted algorithm descriptions or bad algorithms, bad ideas or visions.
Dann Corbit
Posts: 12537
Joined: Wed Mar 08, 2006 8:57 pm
Location: Redmond, WA USA

Re: Simplifying code

Post by Dann Corbit »

Henk wrote: Wed May 13, 2020 8:59 am I don't care about bugs for now.
This is a mistake.
The great lesson of Fabian Letouzy is to write clear correct code and then build on that.
Building upon buggy code is a house of cards, and eventually the breeze will blow.
Taking ideas is not a vice, it is a virtue. We have another word for this. It is called learning.
But sharing ideas is an even greater virtue. We have another word for this. It is called teaching.
Henk
Posts: 7216
Joined: Mon May 27, 2013 10:31 am

Re: Simplifying code

Post by Henk »

You forget I wrote: Bugs is result of missing test cases.
Writing clear code is first thing to do.

O wait that won't help if algorithms, ideas or visions are bad.
JohnWoe
Posts: 491
Joined: Sat Mar 02, 2013 11:31 pm

Re: Simplifying code

Post by JohnWoe »

Henk wrote: Wed May 13, 2020 9:52 am You forget I wrote: Bugs is result of missing test cases.
Writing clear code is first thing to do.

O wait that won't help if algorithms, ideas or visions are bad.
Yes! Clear code is usually the best choice. Like Stroutstrup said:
Simple code is usually fast code.
Recently I removed KPK Bitbases from my engine. That clearly hurts ELO-wise. But simplifications ftw. I try to keep my engine pretty simple.

I recommend cloc to keep bloat under control.
Some examples:
Sapeli 1.88 (The whole project just 2250 lines):

Code: Select all

-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
C                                1            273            105           2018
Python                           1             34              6            124
Markdown                         1             15              0             71
make                             1             15             29             37
-------------------------------------------------------------------------------
SUM:                             4            337            140           2250
-------------------------------------------------------------------------------


Others
lc0: 31788
Crafty: 27497
Rodent IV: 22526
Stockfish-dev: 8320

The worst offender BOOST has over 6.3M lines :)

Non chess:
Vue.js: 142187
BOOS: 6351090