As everyone who has played on a big map for many turns noticed, More Naval AI performance suffers a lot in the late game. I would like to work on improving this situation.
To know what methods cause the biggest problems I used the FProfiler included in the dll to profile More Naval AI r1332 for 10 turns in a late game (turn 465) taking place in a Huge Pangaea. The savegame I used and the profiling results for each turn can be found attached to this post.
I checked the source code of each one of the methods that take a lot of time and took some notes of them. I would appreciate any comments with regard to these methods. Once I get a clear idea of some changes to these or any other methods that could improve game speed I plan to start coding and profiling those changes to see if they manage to improve turn speed or not.
CvPlayerAI::AI_doTurnUnitsPost:
This method has a big cost in all turns. Improving its performance should be a priority. Tholal has a ToDo note in this method. The change he proposes should help a lot in improving the performance of this method.
CvPlayerAI::AI_unitValue:
This method has a big cost on all turns. Improving its performance should be a priority. Most of the time cost of this method comes from the huge number of times it is being called. If this value could be cached for each unit and marked as dirty as unfrequently as possible we could see a huge improvement in late game speed. The time cost of the method itself seems to be negligible. Anyways, switching from the bValid magic to a code that bails out from the method as early as possible should improve things a bit.
CvTeamAI::AI_doWar:
This method does not add a lot of cost on all turns, but when it does it has a great cost.
This method calls python "AI_doWar", but since that python function is empty this should not be increasing its cost much. I don't see any obvious way to improve the cost of this method.
CvTeamAI::AI_doWar -> CvPlayerAI::AI_doPeace:
This method does not add a lot of cost on all turns, but when it does it has a great cost. I don't spot any obvious ways to improve this code.
CvTeam::setHasTech:
This method does not add a lot of cost on all turns, but when it does it has a great cost. This method cycles twice through all the plots to check bonus changes even if the technology being set does not change "techReveal", "techCityTrade" or "techObsolete" for any bonus. Since most of its cost comes from calling CvTeam:rocessTech, what I mentioned does not seem like a big issue.
CvTeam::setHasTech -> CvTeam:rocessTech:
This method does not add a lot of cost on all turns, but when it does it has a great cost. I do not see any obvious change that could improve the speed of this code.
CvPlayer::isFullMember:
This method has a noticeable cost in all turns. This cost comes from being called half a million times each turn. Trying to reduce the number of times it is called should help a bit with its cost.
CvUnit::canCast:
This method has a noticeable cost in all turns. The cost comes mostly from the number of times it is being called. Although from my profiling log canCast does not seem like a huge performance drain, I have reasons to suspect that the cost of canCast increases a lot when more spells are added (specially if they have or "unit on stack", "promotion in stack" prerrequisites or they are permanent summoning spells). For example, Snarko mentioned at #erebus that CvUnit::canCast was a big performance problem in Rise from Erebus. Adapting the changes that he made in Rise from Erebus to More Naval AI should help a bit with its performance, and it should also help with the performance of any More Naval AI modmods that add a huge number of spells.
To know what methods cause the biggest problems I used the FProfiler included in the dll to profile More Naval AI r1332 for 10 turns in a late game (turn 465) taking place in a Huge Pangaea. The savegame I used and the profiling results for each turn can be found attached to this post.
I checked the source code of each one of the methods that take a lot of time and took some notes of them. I would appreciate any comments with regard to these methods. Once I get a clear idea of some changes to these or any other methods that could improve game speed I plan to start coding and profiling those changes to see if they manage to improve turn speed or not.
CvPlayerAI::AI_doTurnUnitsPost:
This method has a big cost in all turns. Improving its performance should be a priority. Tholal has a ToDo note in this method. The change he proposes should help a lot in improving the performance of this method.
CvPlayerAI::AI_unitValue:
This method has a big cost on all turns. Improving its performance should be a priority. Most of the time cost of this method comes from the huge number of times it is being called. If this value could be cached for each unit and marked as dirty as unfrequently as possible we could see a huge improvement in late game speed. The time cost of the method itself seems to be negligible. Anyways, switching from the bValid magic to a code that bails out from the method as early as possible should improve things a bit.
CvTeamAI::AI_doWar:
This method does not add a lot of cost on all turns, but when it does it has a great cost.
This method calls python "AI_doWar", but since that python function is empty this should not be increasing its cost much. I don't see any obvious way to improve the cost of this method.
CvTeamAI::AI_doWar -> CvPlayerAI::AI_doPeace:
This method does not add a lot of cost on all turns, but when it does it has a great cost. I don't spot any obvious ways to improve this code.
CvTeam::setHasTech:
This method does not add a lot of cost on all turns, but when it does it has a great cost. This method cycles twice through all the plots to check bonus changes even if the technology being set does not change "techReveal", "techCityTrade" or "techObsolete" for any bonus. Since most of its cost comes from calling CvTeam:rocessTech, what I mentioned does not seem like a big issue.
CvTeam::setHasTech -> CvTeam:rocessTech:
This method does not add a lot of cost on all turns, but when it does it has a great cost. I do not see any obvious change that could improve the speed of this code.
CvPlayer::isFullMember:
This method has a noticeable cost in all turns. This cost comes from being called half a million times each turn. Trying to reduce the number of times it is called should help a bit with its cost.
CvUnit::canCast:
This method has a noticeable cost in all turns. The cost comes mostly from the number of times it is being called. Although from my profiling log canCast does not seem like a huge performance drain, I have reasons to suspect that the cost of canCast increases a lot when more spells are added (specially if they have or "unit on stack", "promotion in stack" prerrequisites or they are permanent summoning spells). For example, Snarko mentioned at #erebus that CvUnit::canCast was a big performance problem in Rise from Erebus. Adapting the changes that he made in Rise from Erebus to More Naval AI should help a bit with its performance, and it should also help with the performance of any More Naval AI modmods that add a huge number of spells.