Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve FleetWnd split fleet #863

Merged
merged 19 commits into from Aug 15, 2016

Conversation

LGM-Doyle
Copy link
Contributor

This PR improves the run time of FleetWndsplit fleet.

It will also improve update times for any maps which contain fleets.

It does not change any game rules, or UI elements. I think it is suitable for inclusion in 0.4.6.

On my test example merging all the fleets in a fleet button with many fleets and then splitting them. The splitting took 19 seconds before this PR and 3 seconds after.

You can compare the results yourself with any save with a large fleet. The PR is save compatible.

The first commit efa00c3 contains the FleetWnd::SplitFleet ScopedTimer for split fleet. If you checkout efa00c3 and split a big fleet, the time will be in the freeorion.log as FleetWnd::SplitFleet time: xxxx.xx. You can compare the results with the whole PR. The changes are large enough to be noticeable without the timer.

The PR makes several changes in MapWnd that cumulatively produce the improvement.

  • it creates separate handlers for fleet insert and remove events.
  • it defers all work from multiple fleet insert/remove events during a single render interval to a single function DeferredRefreshFleetButtons() run only if needed at the start of Render()
  • it removes some redundancy in fleet movement line drawing.
  • it only examines fleets instead of all objects when considering fleets to draw.
  • it uses unordered sets and maps for unordered sets and maps of fleet related objects.

It makes some code quality changes, by reducing repeated code.

This will determine how often fleet buttons are regenerated multiple
times during a single refresh interval.
Split fleet from the FleetWnd generates one new fleet per friendly ship
in a system.

Currently, that generates one RefreshFleetButton() call per fleet
although only the results from the last RefreshFleetButton() call before
the Render() affect the results.

This commit creates a DeferredRefreshFleetButton() that is called once
if necessary at the start of the next Render() call.
Previously, the code was SetFleetMovementLine(per fleet button) which
meant that fleet buttons with multiple fleets updated each fleet
multiple times.
FleetsAddedOrRemoved() would remove all of the signals from and
reconnect signals for every fleet in the universe.

These two new handlers, FleetsInsertedSignalHandler() and
FleetsRemovedSignalHandler() only deletes/inserts handlers for the
fleets in its input.
By adding boost::hash<TemporaryPtr<T> >, TemporaryPtr<T> can be a member
in boost:unordered_set and a key in boost::unordered_map.
Avoid examining every object in Universe and only inspect fleets when
creating departing, stationary and moving sets of fleets.
MapWnd::CreateFleetButtonsOfType() creates fleet buttons and stores them
in m_stationary_, m_departing_ or m_moving_ fleet_buttons as appropriate.
Now that the deferred update runs at most once per render this is always
less than one.
@MatGB
Copy link
Member

MatGB commented Aug 14, 2016

For reviewers: I've tested this and it works fine on my system, with a noticeable improvement in performance, I cannot comment on the code itself but would recommend inclusion ASAP if possible.

for (std::set<FleetButton*>::iterator it = m_moving_fleet_buttons.begin(); it != m_moving_fleet_buttons.end(); ++it) {
FleetButton* fb = *it;
for (boost::unordered_map<std::pair<double, double>, boost::unordered_set<FleetButton*> >::iterator pos_it = m_moving_fleet_buttons.begin();
pos_it != m_moving_fleet_buttons.end(); ++pos_it) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{ to next line

for (std::set<FleetButton*>::iterator button_it = set.begin(); button_it != set.end(); ++button_it)
for (boost::unordered_map<int, boost::unordered_set<FleetButton*> >::iterator it = m_departing_fleet_buttons.begin(); it != m_departing_fleet_buttons.end(); ++it) {
boost::unordered_set<FleetButton*>& set = it->second;
for (boost::unordered_set<FleetButton*>::iterator button_it = set.begin(); button_it != set.end(); ++button_it)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{

@LGM-Doyle
Copy link
Contributor Author

@geoffthemedio thanks for the prompt review.

I've made all the requested changes.

@Vezzra Vezzra added the category:refactoring The Issue/PR describes or contains an improved implementation. label Aug 15, 2016
@Vezzra Vezzra added this to the Release v0.4.6 milestone Aug 15, 2016
@geoffthemedio geoffthemedio merged commit 5cd8f2c into freeorion:master Aug 15, 2016
@LGM-Doyle LGM-Doyle deleted the improve_FleetWnd_split_fleet branch August 15, 2016 21:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category:refactoring The Issue/PR describes or contains an improved implementation.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants