Merge lp:~widelands-dev/widelands/bug-986611-cppcheck_performance-ui into lp:widelands

Proposed by GunChleoc
Status: Merged
Merged at revision: 8043
Proposed branch: lp:~widelands-dev/widelands/bug-986611-cppcheck_performance-ui
Merge into: lp:widelands
Diff against target: 424 lines (+88/-65)
24 files modified
src/ui_basic/listselect.cc (+1/-1)
src/ui_basic/listselect.h (+1/-1)
src/ui_basic/slider.cc (+1/-1)
src/ui_basic/slider.h (+1/-1)
src/ui_basic/table.h (+1/-1)
src/ui_fsmenu/base.cc (+3/-4)
src/wui/field_overlay_manager.cc (+1/-1)
src/wui/field_overlay_manager.h (+1/-1)
src/wui/game_debug_ui.cc (+1/-1)
src/wui/game_debug_ui.h (+1/-1)
src/wui/interactive_base.h (+1/-1)
src/wui/interactive_gamebase.h (+1/-1)
src/wui/interactive_player.cc (+1/-1)
src/wui/interactive_player.h (+2/-2)
src/wui/interactive_spectator.cc (+1/-1)
src/wui/interactive_spectator.h (+1/-1)
src/wui/mapdata.cc (+54/-34)
src/wui/mapdata.h (+8/-4)
src/wui/plot_area.cc (+1/-1)
src/wui/plot_area.h (+1/-1)
src/wui/vector.h (+2/-2)
src/wui/waresdisplay.cc (+1/-1)
src/wui/watchwindow.cc (+1/-1)
src/wui/watchwindow.h (+1/-1)
To merge this branch: bzr merge lp:~widelands-dev/widelands/bug-986611-cppcheck_performance-ui
Reviewer Review Type Date Requested Status
SirVer Approve
Review via email: mp+300992@code.launchpad.net

Commit message

Fixed performance issues in UI classes that were flagged up by cppcheck and fixed a textdomain issue in wui/mapdata.

Performance issues fixed are:

- Prefer prefix ++ operator in wui/waresdisplay.cc.
- Constructor initialization in ui_fsmenu/base and wui/mapdata.
- Passing parameters per reference.

Description of the change

Fixed performance issues in UI classes that were flagged up by cppcheck and fixed a textdomain issue in wui/mapdata.

Performance issues fixed are:

- Prefer prefix ++ operator in wui/waresdisplay.cc.
- Constructor initialization in ui_fsmenu/base and wui/mapdata.
- Passing parameters per reference.

To post a comment you must log in.
Revision history for this message
bunnybot (widelandsofficial) wrote :

Continuous integration builds have changed state:

Travis build 1207. State: passed. Details: https://travis-ci.org/widelands/widelands/builds/146981830.
Appveyor build 1046. State: failed. Details: https://ci.appveyor.com/project/widelands-dev/widelands/build/_widelands_dev_widelands_bug_986611_cppcheck_performance_ui-1046.

Revision history for this message
SirVer (sirver) wrote :

> - Passing parameters per reference.

I agree with all the other changes and do not feel strongly about this either (i.e. I think this can go in - I doubt any of these changes make any noticeable performance change in Widelands though). I just want to add 2c, because there are more complicated issues here:

1) Passing by reference is only more efficient if a reference is smaller than the datatype. For example RGBColor is a struct of 4bytes which is smaller than he size of a reference (which is he size of a pointer) on a 64 bit system. So passing it by value, i.e. copying it is actually more efficient. Same goes for Coord and some others. So some of the changes will actually decrease performance - though it will never matter, it will never show up on any profile since passing parameters is basically never the bottleneck.

2) Passing a type that manages memory and copying it can be more expensive. Example

struct MyClass {
    MyClass(const vector<int>& a) : a_(a) {}
    vector<int> a_;
}

std::vector<int> millions_of_ints;
MyClass klass(millions_of_ints); // Passing by reference here: millions_of_ints will be copied in a_.
// never use millions of ints again.

Here, the compiler needs to copy a to fulfill our contracts. If we change

MyClass klass(std::move(millions_of_ints));

this does not help at all. The constructor takes a const ref, so the compiler still needs to copy - it cannot avoid the copy. While if we write:

struct MyClass {
    MyClass(vector<int> a) : a_(std::move(a)) {} // No new memory is allocated, no copy made
    vector<int> a_;
}

std::vector<int> millions_of_ints;
MyClass klass(std::move(millions_of_ints)); // Moving the vector - the pointer to its allocated memory is just passed on, there is no additional copy or allocation.

This is the most efficient version we can write. And you see that const ref actually did harm here.

Just my 2c - in general const ref is the best choice, but it is more complicated.

review: Approve
Revision history for this message
GunChleoc (gunchleoc) wrote :

The vector thing is actually quite counterintuitive - one would expect a reference not to copy all the elements *headdesk*. I'm sure there is some reason for that design, do you know why they did it that way?

I have added your explanation to my notes :)

@bunnybot merge

Revision history for this message
SirVer (sirver) wrote :

The way I like to think about this is along these lines:

func(const vector& blub) means 'I use blub, will not change it and you - the caller - retain ownership'. If I (the function) require 'blub' for longer, I need to make a copy.

func(vector blub) means 'I require my own blub. If you do not need yours anymore, use std::move() and I will use it. Otherwise calling me will copy blub.'

But I find the design choices when to use a per-value and when to use a const ref& not always easy. Generally you could say that if a function copies a value ever, using a per-value argument is preferable.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/ui_basic/listselect.cc'
2--- src/ui_basic/listselect.cc 2016-03-25 17:01:05 +0000
3+++ src/ui_basic/listselect.cc 2016-07-24 11:56:05 +0000
4@@ -249,7 +249,7 @@
5 * index.
6 */
7 void BaseListselect::set_entry_color
8- (const uint32_t n, const RGBColor col)
9+ (const uint32_t n, const RGBColor& col)
10 {
11 assert(n < entry_records_.size());
12
13
14=== modified file 'src/ui_basic/listselect.h'
15--- src/ui_basic/listselect.h 2016-02-09 21:14:53 +0000
16+++ src/ui_basic/listselect.h 2016-07-24 11:56:05 +0000
17@@ -73,7 +73,7 @@
18
19 void switch_entries(uint32_t, uint32_t);
20
21- void set_entry_color(uint32_t, RGBColor);
22+ void set_entry_color(uint32_t, const RGBColor&);
23
24 uint32_t size () const {return entry_records_.size ();}
25 bool empty() const {return entry_records_.empty();}
26
27=== modified file 'src/ui_basic/slider.cc'
28--- src/ui_basic/slider.cc 2016-03-30 07:20:05 +0000
29+++ src/ui_basic/slider.cc 2016-07-24 11:56:05 +0000
30@@ -538,7 +538,7 @@
31 DiscreteSlider::DiscreteSlider
32 (Panel * const parent,
33 const int32_t x, const int32_t y, const uint32_t w, const uint32_t h,
34- const std::vector<std::string> labels_in,
35+ const std::vector<std::string>& labels_in,
36 uint32_t value_,
37 const Image* background_picture_id,
38 const std::string & tooltip_text,
39
40=== modified file 'src/ui_basic/slider.h'
41--- src/ui_basic/slider.h 2016-02-03 18:09:15 +0000
42+++ src/ui_basic/slider.h 2016-07-24 11:56:05 +0000
43@@ -185,7 +185,7 @@
44 DiscreteSlider
45 (Panel * const parent,
46 const int32_t x, const int32_t y, const uint32_t w, const uint32_t h,
47- const std::vector<std::string> labels_in,
48+ const std::vector<std::string>& labels_in,
49 uint32_t value_,
50 const Image* background_picture_id,
51 const std::string & tooltip_text = std::string(),
52
53=== modified file 'src/ui_basic/table.h'
54--- src/ui_basic/table.h 2016-02-21 09:39:30 +0000
55+++ src/ui_basic/table.h 2016-07-24 11:56:05 +0000
56@@ -126,7 +126,7 @@
57 const Image* get_picture(uint8_t col) const;
58 const std::string & get_string(uint8_t col) const;
59 void * entry() const {return entry_;}
60- void set_color(const RGBColor c) {
61+ void set_color(const RGBColor& c) {
62 use_clr = true;
63 clr = c;
64 }
65
66=== modified file 'src/ui_fsmenu/base.cc'
67--- src/ui_fsmenu/base.cc 2016-02-07 18:10:53 +0000
68+++ src/ui_fsmenu/base.cc 2016-07-24 11:56:05 +0000
69@@ -48,10 +48,9 @@
70 * Args: bgpic name of the background picture
71 */
72 FullscreenMenuBase::FullscreenMenuBase(const std::string& bgpic)
73- : UI::Panel(nullptr, 0, 0, g_gr->get_xres(), g_gr->get_yres()) {
74-
75- background_image_ = bgpic;
76-}
77+ : UI::Panel(nullptr, 0, 0, g_gr->get_xres(), g_gr->get_yres()),
78+ background_image_(bgpic)
79+{}
80
81 FullscreenMenuBase::~FullscreenMenuBase()
82 {
83
84=== modified file 'src/wui/field_overlay_manager.cc'
85--- src/wui/field_overlay_manager.cc 2016-01-28 05:24:34 +0000
86+++ src/wui/field_overlay_manager.cc 2016-07-24 11:56:05 +0000
87@@ -117,7 +117,7 @@
88 }
89
90 void FieldOverlayManager::register_overlay
91- (Widelands::TCoords<> const c,
92+ (const Widelands::TCoords<>& c,
93 const Image* pic,
94 int32_t const level,
95 Point hotspot,
96
97=== modified file 'src/wui/field_overlay_manager.h'
98--- src/wui/field_overlay_manager.h 2016-01-24 20:11:53 +0000
99+++ src/wui/field_overlay_manager.h 2016-07-24 11:56:05 +0000
100@@ -85,7 +85,7 @@
101 /// Register an overlay at a location (node or triangle). hotspot is the point
102 /// of the picture that will be exactly over the location. If hotspot is
103 /// Point::invalid(), the center of the picture will be used as hotspot.
104- void register_overlay(const Widelands::TCoords<> coords,
105+ void register_overlay(const Widelands::TCoords<>& coords,
106 const Image* pic,
107 int32_t level,
108 Point hotspot = Point::invalid(),
109
110=== modified file 'src/wui/game_debug_ui.cc'
111--- src/wui/game_debug_ui.cc 2016-05-17 16:40:22 +0000
112+++ src/wui/game_debug_ui.cc 2016-07-24 11:56:05 +0000
113@@ -467,7 +467,7 @@
114 ===============
115 */
116 void show_field_debug
117- (InteractiveBase & parent, Widelands::Coords const coords)
118+ (InteractiveBase& parent, const Widelands::Coords& coords)
119 {
120 new FieldDebugWindow(parent, coords);
121 }
122
123=== modified file 'src/wui/game_debug_ui.h'
124--- src/wui/game_debug_ui.h 2014-09-10 08:55:04 +0000
125+++ src/wui/game_debug_ui.h 2016-07-24 11:56:05 +0000
126@@ -28,6 +28,6 @@
127
128 // Open debug window for the given coordinates
129 void show_mapobject_debug(InteractiveBase & parent, Widelands::MapObject &);
130-void show_field_debug(InteractiveBase & parent, Widelands::Coords coords);
131+void show_field_debug(InteractiveBase & parent, const Widelands::Coords& coords);
132
133 #endif // end of include guard: WL_WUI_GAME_DEBUG_UI_H
134
135=== modified file 'src/wui/interactive_base.h'
136--- src/wui/interactive_base.h 2016-05-03 08:45:23 +0000
137+++ src/wui/interactive_base.h 2016-07-24 11:56:05 +0000
138@@ -186,7 +186,7 @@
139 struct SelData {
140 SelData
141 (const bool Freeze = false, const bool Triangles = false,
142- const Widelands::NodeAndTriangle<> Pos =
143+ const Widelands::NodeAndTriangle<>& Pos =
144 Widelands::NodeAndTriangle<>
145 (Widelands::Coords(0, 0),
146 Widelands::TCoords<>
147
148=== modified file 'src/wui/interactive_gamebase.h'
149--- src/wui/interactive_gamebase.h 2016-03-16 09:22:00 +0000
150+++ src/wui/interactive_gamebase.h 2016-07-24 11:56:05 +0000
151@@ -77,7 +77,7 @@
152
153 protected:
154 void draw_overlay(RenderTarget &) override;
155- virtual int32_t calculate_buildcaps(const Widelands::TCoords<Widelands::FCoords> c) = 0;
156+ virtual int32_t calculate_buildcaps(const Widelands::TCoords<Widelands::FCoords>& c) = 0;
157
158 GameMainMenuWindows main_windows_;
159 ChatProvider * chat_provider_;
160
161=== modified file 'src/wui/interactive_player.cc'
162--- src/wui/interactive_player.cc 2016-04-02 08:28:29 +0000
163+++ src/wui/interactive_player.cc 2016-07-24 11:56:05 +0000
164@@ -266,7 +266,7 @@
165 return player_number_;
166 }
167
168-int32_t InteractivePlayer::calculate_buildcaps(const Widelands::TCoords<Widelands::FCoords> c) {
169+int32_t InteractivePlayer::calculate_buildcaps(const Widelands::TCoords<Widelands::FCoords>& c) {
170 assert(get_player());
171 return get_player()->get_buildcaps(c);
172 }
173
174=== modified file 'src/wui/interactive_player.h'
175--- src/wui/interactive_player.h 2016-01-24 20:11:53 +0000
176+++ src/wui/interactive_player.h 2016-07-24 11:56:05 +0000
177@@ -77,12 +77,12 @@
178 void cleanup_for_load() override;
179 void think() override;
180
181- void set_flag_to_connect(Widelands::Coords const location) {
182+ void set_flag_to_connect(const Widelands::Coords& location) {
183 flag_to_connect_ = location;
184 }
185
186 void popup_message(Widelands::MessageId, const Widelands::Message &);
187- int32_t calculate_buildcaps(const Widelands::TCoords<Widelands::FCoords> c) override;
188+ int32_t calculate_buildcaps(const Widelands::TCoords<Widelands::FCoords>& c) override;
189
190 private:
191 void cmdSwitchPlayer(const std::vector<std::string> & args);
192
193=== modified file 'src/wui/interactive_spectator.cc'
194--- src/wui/interactive_spectator.cc 2016-03-16 10:32:50 +0000
195+++ src/wui/interactive_spectator.cc 2016-07-24 11:56:05 +0000
196@@ -143,7 +143,7 @@
197 }
198
199
200-int32_t InteractiveSpectator::calculate_buildcaps(const Widelands::TCoords<Widelands::FCoords> c) {
201+int32_t InteractiveSpectator::calculate_buildcaps(const Widelands::TCoords<Widelands::FCoords>& c) {
202 const Widelands::PlayerNumber nr_players = game().map().get_nrplayers();
203
204 iterate_players_existing(p, nr_players, game(), player) {
205
206=== modified file 'src/wui/interactive_spectator.h'
207--- src/wui/interactive_spectator.h 2016-01-24 20:11:53 +0000
208+++ src/wui/interactive_spectator.h 2016-07-24 11:56:05 +0000
209@@ -51,7 +51,7 @@
210 void toggle_statistics();
211 void exit_btn();
212 void save_btn();
213- int32_t calculate_buildcaps(const Widelands::TCoords<Widelands::FCoords> c) override;
214+ int32_t calculate_buildcaps(const Widelands::TCoords<Widelands::FCoords>& c) override;
215 bool can_see(Widelands::PlayerNumber) const override;
216 bool can_act(Widelands::PlayerNumber) const override;
217 Widelands::PlayerNumber player_number() const override;
218
219=== modified file 'src/wui/mapdata.cc'
220--- src/wui/mapdata.cc 2016-06-07 07:13:03 +0000
221+++ src/wui/mapdata.cc 2016-07-24 11:56:05 +0000
222@@ -21,42 +21,62 @@
223
224 #include "io/filesystem/filesystem.h"
225
226-MapData::MapData() : authors(""), nrplayers(0), width(0), height(0),
227- maptype(MapData::MapType::kNormal), displaytype(MapData::DisplayType::kMapnamesLocalized) {}
228-
229- MapData::MapData(const Widelands::Map& map, const std::string& init_filename,
230- const MapData::MapType& init_maptype,
231- const MapData::DisplayType& init_displaytype) :
232- MapData() {
233- i18n::Textdomain td("maps");
234- filename = init_filename;
235- name = map.get_name().empty() ? _("No Name") : map.get_name();
236- localized_name = _(name);
237- // Localizing this, because some author fields now have "edited by" text.
238- const std::string& author = map.get_author();
239- authors = MapAuthorData(author.empty() ? _("No Author") : _(author));
240- description = map.get_description().empty() ? "" : _(map.get_description());
241- hint = map.get_hint().empty() ? "" : _(map.get_hint());
242- nrplayers = map.get_nrplayers();
243- width = map.get_width();
244- height = map.get_height();
245- suggested_teams = map.get_suggested_teams();
246- tags = map.get_tags();
247- maptype = init_maptype;
248- displaytype = init_displaytype;
249-
250- if (maptype == MapData::MapType::kScenario) {
251- tags.insert("scenario");
252- }
253- }
254+MapData::MapData(const std::string& init_filename,
255+ const std::string& init_localized_name,
256+ const std::string& init_author,
257+ const MapData::MapType& init_maptype,
258+ const MapData::DisplayType& init_displaytype) :
259+ filename(init_filename),
260+ name(init_localized_name),
261+ localized_name(init_localized_name),
262+ authors(init_author),
263+ description(""),
264+ hint(""),
265+ nrplayers(0),
266+ width(0),
267+ height(0),
268+ maptype(init_maptype),
269+ displaytype(init_displaytype)
270+{}
271+
272+MapData::MapData(const Widelands::Map& map, const std::string& init_filename,
273+ const MapData::MapType& init_maptype,
274+ const MapData::DisplayType& init_displaytype) :
275+ MapData(init_filename,
276+ _("No Name"),
277+ _("No Author"),
278+ init_maptype,
279+ init_displaytype) {
280+
281+ i18n::Textdomain td("maps");
282+ if (!map.get_name().empty()) {
283+ name = map.get_name();
284+ }
285+ localized_name = _(name);
286+ // Localizing this, because some author fields now have "edited by" text.
287+ if (!map.get_author().empty()) {
288+ authors = map.get_author();
289+ }
290+ description = map.get_description().empty() ? "" : _(map.get_description());
291+ hint = map.get_hint().empty() ? "" : _(map.get_hint());
292+ nrplayers = map.get_nrplayers();
293+ width = map.get_width();
294+ height = map.get_height();
295+ suggested_teams = map.get_suggested_teams();
296+ tags = map.get_tags();
297+
298+ if (maptype == MapData::MapType::kScenario) {
299+ tags.insert("scenario");
300+ }
301+}
302
303 MapData::MapData(const std::string& init_filename, const std::string& init_localized_name) :
304- MapData() {
305- filename = init_filename;
306- name = init_localized_name;
307- localized_name = init_localized_name;
308- maptype = MapData::MapType::kDirectory;
309- }
310+ MapData(init_filename,
311+ init_localized_name,
312+ "",
313+ MapData::MapType::kDirectory,
314+ MapData::DisplayType::kMapnamesLocalized)
315+{}
316
317 bool MapData::compare_names(const MapData& other) {
318 // The parent directory gets special treatment.
319
320=== modified file 'src/wui/mapdata.h'
321--- src/wui/mapdata.h 2016-05-15 09:03:01 +0000
322+++ src/wui/mapdata.h 2016-07-24 11:56:05 +0000
323@@ -71,10 +71,14 @@
324 kMapnamesLocalized
325 };
326
327-
328- /// For incomplete data
329- MapData();
330-
331+private:
332+ /// For common properties
333+ MapData(const std::string& init_filename,
334+ const std::string& init_localized_name,
335+ const std::string& init_author,
336+ const MapData::MapType& init_maptype,
337+ const MapData::DisplayType& init_displaytype);
338+public:
339 /// For normal maps and scenarios
340 MapData(const Widelands::Map& map, const std::string& init_filename,
341 const MapData::MapType& init_maptype,
342
343=== modified file 'src/wui/plot_area.cc'
344--- src/wui/plot_area.cc 2016-05-20 07:01:10 +0000
345+++ src/wui/plot_area.cc 2016-07-24 11:56:05 +0000
346@@ -491,7 +491,7 @@
347 */
348 void WuiPlotArea::draw_plot_line
349 (RenderTarget & dst, std::vector<uint32_t> const * dataset,
350- uint32_t const highest_scale, float const sub, RGBColor const color, int32_t const yoffset)
351+ uint32_t const highest_scale, float const sub, const RGBColor& color, int32_t const yoffset)
352 {
353 if (!dataset->empty()) {
354 float posx = get_inner_w() - kSpaceRight;
355
356=== modified file 'src/wui/plot_area.h'
357--- src/wui/plot_area.h 2016-05-20 07:01:10 +0000
358+++ src/wui/plot_area.h 2016-07-24 11:56:05 +0000
359@@ -96,7 +96,7 @@
360 uint32_t highest_scale);
361 void draw_plot_line
362 (RenderTarget & dst, std::vector<uint32_t> const * dataset,
363- uint32_t const highest_scale, float const sub, RGBColor const color, int32_t yoffset);
364+ uint32_t const highest_scale, float const sub, const RGBColor& color, int32_t yoffset);
365 uint32_t get_plot_time() const;
366 /// Recalculates the data
367 virtual void update();
368
369=== modified file 'src/wui/vector.h'
370--- src/wui/vector.h 2014-07-05 16:41:51 +0000
371+++ src/wui/vector.h 2016-07-24 11:56:05 +0000
372@@ -39,12 +39,12 @@
373 }
374
375 // vector addition
376- Vector operator+ (Vector const other) const {
377+ Vector operator+ (const Vector& other) const {
378 return Vector(x + other.x, y + other.y, z + other.z);
379 }
380
381 // inner product
382- float operator* (Vector const other) const {
383+ float operator* (const Vector& other) const {
384 return x * other.x + y * other.y + z * other.z;
385 }
386
387
388=== modified file 'src/wui/waresdisplay.cc'
389--- src/wui/waresdisplay.cc 2016-03-08 21:14:48 +0000
390+++ src/wui/waresdisplay.cc 2016-07-24 11:56:05 +0000
391@@ -464,7 +464,7 @@
392 std::vector<Widelands::DescriptionIndex>::iterator j;
393 Widelands::TribeDescr::WaresOrder order = tribe.wares_order();
394
395- for (i = order.begin(); i != order.end(); i++)
396+ for (i = order.begin(); i != order.end(); ++i)
397 for (j = i->begin(); j != i->end(); ++j)
398 if ((c = map.find(*j)) != map.end()) {
399 ret += "<sub width=30 padding=2><p align=center>"
400
401=== modified file 'src/wui/watchwindow.cc'
402--- src/wui/watchwindow.cc 2016-04-03 16:18:24 +0000
403+++ src/wui/watchwindow.cc 2016-07-24 11:56:05 +0000
404@@ -386,7 +386,7 @@
405 ===============
406 */
407 void show_watch_window
408- (InteractiveGameBase & parent, Widelands::Coords const coords)
409+ (InteractiveGameBase & parent, const Widelands::Coords& coords)
410 {
411 if (g_options.pull_section("global").get_bool("single_watchwin", false)) {
412 if (g_watch_window)
413
414=== modified file 'src/wui/watchwindow.h'
415--- src/wui/watchwindow.h 2014-09-10 08:55:04 +0000
416+++ src/wui/watchwindow.h 2016-07-24 11:56:05 +0000
417@@ -24,6 +24,6 @@
418
419 class InteractiveGameBase;
420
421-void show_watch_window(InteractiveGameBase &, Widelands::Coords);
422+void show_watch_window(InteractiveGameBase &, const Widelands::Coords&);
423
424 #endif // end of include guard: WL_WUI_WATCHWINDOW_H

Subscribers

People subscribed via source and target branches

to status/vote changes: