From fc59fc75733581e93a26a2d27dfc3a028544d7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Janiszewski?= Date: Tue, 18 Jul 2017 15:18:15 +0200 Subject: [PATCH] Cache last visited node in paint_arrange_structs This commit caches the last visited node in paint_arrange_structs and in paint_arrange_structs_helper, which allows skipping iterating over long linked lists that don't work well with modern CPU caches. This is especially useful, if the list is walked just to be discarded in the end. This improves performance across the board, the busier the park, the higher performance improvement. I have verified this producing pixel-perfect results with ones before this change by dumping giant screenshot on various parks in all zooms, all rotations. Results collected running before and after this change with `benchgfx` command (https://github.com/OpenRCT2/OpenRCT2/pull/5655) on current title sequence, YMMV. **Park**|**Before**|**After**|**Delta** :-----:|:-----:|:-----:|:-----: Maian\_SOSDragon.sv6|2.80|2.43|-13.2% Maian\_SOSFrosty.sv6|3.53|3.02|-14.4% Maian\_SOSParabola.sv6|4.16|3.45|-17.1% MrB.sv6|5.52|4.52|-18.1% SpacekKing.sv6|8.53|6.52|-23.6% SpacekMaple.sv6|7.18|5.75|-19.9% SpacekMission.sv6|4.41|3.43|-22.2% SpacekParadise.sv6|9.01|6.36|-29.4% SpacekSwimmers.sv6|4.11|2.97|-27.7% Stosky.sv6|3.34|2.36|-29.3% | | | **Average**|**5.26**|**4.08**|**-21.5%** --- src/openrct2/paint/paint.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/openrct2/paint/paint.c b/src/openrct2/paint/paint.c index fecac29b02..f9f4df4ecf 100644 --- a/src/openrct2/paint/paint.c +++ b/src/openrct2/paint/paint.c @@ -732,16 +732,19 @@ void paint_generate_structs(rct_drawpixelinfo * dpi) } } -static void paint_arrange_structs_helper(paint_struct * ps_next, uint16 ax, uint8 flag) +static paint_struct * paint_arrange_structs_helper(paint_struct * ps_next, uint16 ax, uint8 flag) { paint_struct * ps; paint_struct * ps_temp; do { ps = ps_next; ps_next = ps_next->next_quadrant_ps; - if (ps_next == NULL) return; + if (ps_next == NULL) return ps; } while (ax > ps_next->var_18); + // Cache the last visited node so we don't have to walk the whole list again + paint_struct * ps_cache = ps; + ps_temp = ps; do { ps = ps->next_quadrant_ps; @@ -763,8 +766,8 @@ static void paint_arrange_structs_helper(paint_struct * ps_next, uint16 ax, uint while (true) { while (true) { ps_next = ps->next_quadrant_ps; - if (ps_next == NULL) return; - if (ps_next->var_1B & (1 << 7)) return; + if (ps_next == NULL) return ps_cache; + if (ps_next->var_1B & (1 << 7)) return ps_cache; if (ps_next->var_1B & (1 << 0)) break; ps = ps_next; } @@ -857,11 +860,11 @@ paint_struct paint_arrange_structs() } } while (++quadrantIndex <= _paintQuadrantFrontIndex); - paint_arrange_structs_helper(&psHead, _paintQuadrantBackIndex & 0xFFFF, 1 << 1); + paint_struct * ps_cache = paint_arrange_structs_helper(&psHead, _paintQuadrantBackIndex & 0xFFFF, 1 << 1); quadrantIndex = _paintQuadrantBackIndex; while (++quadrantIndex < _paintQuadrantFrontIndex) { - paint_arrange_structs_helper(&psHead, quadrantIndex & 0xFFFF, 0); + ps_cache = paint_arrange_structs_helper(ps_cache, quadrantIndex & 0xFFFF, 0); } } return psHead;