{"action":"created","issue":{"url":"https://api.github.com/repos/niklasf/python-chess/issues/97","repository_url":"https://api.github.com/repos/niklasf/python-chess","labels_url":"https://api.github.com/repos/niklasf/python-chess/issues/97/labels{/name}","comments_url":"https://api.github.com/repos/niklasf/python-chess/issues/97/comments","events_url":"https://api.github.com/repos/niklasf/python-chess/issues/97/events","html_url":"https://github.com/niklasf/python-chess/issues/97","id":187110664,"number":97,"title":"slow Engine.position","user":{"login":"vondele","id":4202567,"avatar_url":"https://avatars.githubusercontent.com/u/4202567?v=3","gravatar_id":"","url":"https://api.github.com/users/vondele","html_url":"https://github.com/vondele","followers_url":"https://api.github.com/users/vondele/followers","following_url":"https://api.github.com/users/vondele/following{/other_user}","gists_url":"https://api.github.com/users/vondele/gists{/gist_id}","starred_url":"https://api.github.com/users/vondele/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vondele/subscriptions","organizations_url":"https://api.github.com/users/vondele/orgs","repos_url":"https://api.github.com/users/vondele/repos","events_url":"https://api.github.com/users/vondele/events{/privacy}","received_events_url":"https://api.github.com/users/vondele/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":3,"created_at":"2016-11-03T16:09:29Z","updated_at":"2016-11-03T19:52:32Z","closed_at":null,"body":"Hi,\r\n\r\nI'm using the (nice!) library to replay some games from a pgn file, basically going through all moves in a loop like:\r\n\r\n```python\r\ndef replay_game(engine, info_handler, game)\r\n    engine.ucinewgame()\r\n    node = game\r\n    while not node.is_end():\r\n        next_node = node.variation(0)\r\n        engine.position(node.board())\r\n        move, ponder = engine.go(nodes=engine_nodes)\r\n        node = next_node\r\n```\r\n\r\nat low depth (~10000s of nodes), the code seems dominated in time not by the engine but by 'engine.position()', (see also below for a profile) which is really surprising. Is there anyway to speed this up on the user side or library side ?\r\n\r\nThanks.\r\n\r\n```\r\nname                                  ncall  tsub      ttot      tavg      \r\n..hon3.5/threading.py:851 Thread.run  10     0.000209  18.28100  1.828100\r\nextract.py:75 worker                  2      0.000259  17.17624  8.588118\r\nextract.py:10 replay_game             10     0.035269  17.16669  1.716669\r\n../chess/uci.py:1038 Engine.position  487    0.243273  10.51870  0.021599\r\n../chess/__init__.py:3705 Board.copy  3967   0.074076  7.029697  0.001772\r\n..es/chess/pgn.py:107 GameNode.board  347..  0.015112  6.414442  0.001846\r\n..python3.5/copy.py:269 _reconstruct  7934   0.072472  6.178674  0.000779\r\n..lib/python3.5/copy.py:137 deepcopy  278..  1.855328  6.117882  0.000022\r\n..hon3.5/copy.py:222 _deepcopy_tuple  3967   0.033468  5.929677  0.001495\r\n..b/python3.5/copy.py:223 <listcomp>  3967   0.009123  5.894235  0.001486\r\n..thon3.5/copy.py:214 _deepcopy_list  3967   0.485407  5.845265  0.001473\r\n../chess/__init__.py:1993 Board.push  36358  0.713044  4.847851  0.000133\r\n.._init__.py:3656 Board.zobrist_hash  74048  0.496221  4.846481  0.000065\r\n..s/chess/__init__.py:2096 Board.pop  33690  0.510521  4.141982  0.000123\r\n..Board.has_kingside_castling_rights  148..  0.717624  2.366447  0.000016\r\n..ges/chess/__init__.py:248 bit_scan  446..  1.287791  2.123643  0.000005\r\n..oard.has_queenside_castling_rights  148..  0.583547  1.918082  0.000013\r\n../__init__.py:773 Move.__deepcopy__  266..  0.604402  1.842414  0.000007\r\n..hess/__init__.py:770 Move.__copy__  266..  0.715446  1.109438  0.000004\r\n../python3.5/copy.py:253 _keep_alive  278..  0.626977  0.898871  0.000003\r\n..y:2896 Board.clean_castling_rights  317..  0.885411  0.885411  0.000003\r\n..it__.py:916 Board._remove_piece_at  143..  0.562241  0.742095  0.000005\r\n..collections/__init__.py:581 update  48325  0.223677  0.694931  0.000014\r\n.._init__.py:952 Board._set_piece_at  77808  0.389374  0.643550  0.000008\r\n..enProcess._receiving_thread_target  2      0.041662  0.612874  0.306437\r\n```"},"comment":{"url":"https://api.github.com/repos/niklasf/python-chess/issues/comments/258254852","html_url":"https://github.com/niklasf/python-chess/issues/97#issuecomment-258254852","issue_url":"https://api.github.com/repos/niklasf/python-chess/issues/97","id":258254852,"user":{"login":"niklasf","id":402777,"avatar_url":"https://avatars.githubusercontent.com/u/402777?v=3","gravatar_id":"","url":"https://api.github.com/users/niklasf","html_url":"https://github.com/niklasf","followers_url":"https://api.github.com/users/niklasf/followers","following_url":"https://api.github.com/users/niklasf/following{/other_user}","gists_url":"https://api.github.com/users/niklasf/gists{/gist_id}","starred_url":"https://api.github.com/users/niklasf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/niklasf/subscriptions","organizations_url":"https://api.github.com/users/niklasf/orgs","repos_url":"https://api.github.com/users/niklasf/repos","events_url":"https://api.github.com/users/niklasf/events{/privacy}","received_events_url":"https://api.github.com/users/niklasf/received_events","type":"User","site_admin":false},"created_at":"2016-11-03T19:52:32Z","updated_at":"2016-11-03T19:52:32Z","body":"That's probably about the best that can be done without a larger rewrite and/or API breakage.\r\n\r\n---\r\n\r\nYou might be able to squeeze a bit more out of the PGN handling by using visitors (which avoid an expensive copy that `node.board()` has to make).\r\n\r\n```python\r\nclass MyVisitor(chess.pgn.BaseVisitor):\r\n    def visit_move(self, board, move):\r\n        # called in order for each move of the game \r\n        pass\r\n\r\ngame.accept(Visitor())\r\n```\r\n\r\nOr even skipping the creation of the game representation in memory and analysing moves directly as they get parsed:\r\n\r\n```python\r\nclass MyVisitor(chess.pgn.BaseVisitor):\r\n    def __init__(self):\r\n        self.found_game = False\r\n\r\n    def begin_game(self):\r\n        self.found_game = True\r\n\r\n    def visit_move(self, board, move):\r\n        # called in order for each move of the game \r\n        pass\r\n\r\n    def result(self):\r\n        return self.found_game\r\n\r\nmore_games = True\r\nwhile more_games:\r\n    more_games = chess.pgn.read_game(Visitor=MyVisitor)\r\n```"}}
{"actor":{"display_login":"niklasf"}}