niklasf / python-chess

A chess library for Python, with move generation and validation, PGN parsing and writing, Polyglot opening book reading, Gaviota tablebase probing, Syzygy tablebase probing, and UCI/XBoard engine communication
https://python-chess.readthedocs.io/en/latest/
GNU General Public License v3.0
2.45k stars 531 forks source link

PGN: introduce add_line_by_san #999

Closed dubslow closed 1 year ago

dubslow commented 1 year ago

copied, essentially, from add_line

However, upon reviewing the source, I discovered that GameNode.board() is in fact a grossly expensive function, and rebuilding the entire variation history for every move added is just intensely wasteful. I intend to use this add_line_by_san function on many thousands of games, where each move in each game has a (lengthy) pv line stored as a comment (rather than properly in a variation), so the waste in GameNode.board() would actually cost potentially many seconds of run time, or otherwise force me to write my own traversal code, which would kinda defeat the point of having the pgn module anyways.

I suggest adding a @cache decorator to GameNode.board and thereafter rewriting the method body to simply refer to parent.board(). The result would be the same only much, much more efficient. Please let me know if this is an acceptable plan, and I can make a separate PR. In fact I might anyways

niklasf commented 1 year ago

This can be more concisely implemented as follows, without relying on https://github.com/niklasf/python-chess/pull/1000:

board = node.board()
node.add_line(board.push_san(san) for san in sans)