Angband Forums

Angband Forums (http://angband.oook.cz/forum/index.php)
-   Vanilla (http://angband.oook.cz/forum/forumdisplay.php?f=3)
-   -   Preparing for 4.2 release (http://angband.oook.cz/forum/showthread.php?t=9455)

Pete Mack July 31, 2019 23:27

Gwarl--
Custom loop iterator functions don't make a lot of sense in C. They are great in C# and other languages with anonymous and/or lambda functions.

Quote:

Originally Posted by Gwarl (Post 139452)
For my part the nested for loops are intuitive and I know what they do but the custom iterators look unreadable


Derakon August 1, 2019 00:25

Quote:

Originally Posted by Pete Mack (Post 139453)
Kusunose--
Notice that the macro definition requires no subroutine calls at all. It is just a transliteration of existing code idiom into a single location. So there should be no performance hit at all.

It wouldn't surprise me if modern compilers are capable of saying "Ah, you're invoking this simple function here, we can just inline it" and get the same performance as a macro. In any case, the performance hit of invoking a function is miniscule in this day and age.

Diego Gonzalez August 1, 2019 02:11

Quote:

Originally Posted by Pete Mack (Post 139453)
In any case, there is only a single place in the code where performance matters: in determining visible monsters, walls, and objects. No other loop matters.

You are right. Early optimization was always a hidden enemy in programming...

I remember that noise and smell tracking was a big bottleneck in NPP. Vanilla use those?

Pete Mack August 1, 2019 02:35

Yeah, that is sometimes a problem, too. But it was the illumination code that used to have "show reduced light radius while running" performance optimization. And it is running--and only runnning--where performance matters.

PowerWyrm August 1, 2019 10:46

Quote:

Originally Posted by Kusunose (Post 139440)
It's nice but I think something like this is nicer because you can keep using for loop, though bit wordy.
Code:

struct loc_iterator {
        struct loc cur;
        struct loc begin;
        struct loc end;
};

struct loc_iterator loc_iterator(struct loc begin, struct loc end)
{
        struct loc_iterator iter;
        iter.cur = iter.begin = begin;
        iter.end = end;
        return iter;
}

bool loc_iterator_test(const struct loc_iterator* iter)
{
        return iter->cur.y != iter->end.y;
}

void loc_iterator_next(struct loc_iterator* iter)
{
        iter->cur.x++;
        if (iter->cur.x == iter->end.x) {
                iter->cur.x = iter->begin.x;
                iter->cur.y++;
        }
}

This code
Code:

        for (y = y1; y < y2; y++) {
                for (x = x1; x < x2; x++) {

can be translated as
Code:

        for (struct loc_iterator iter = loc_iterator(loc(x1, y1), loc(x2, y2));
                loc_iterator_test(&iter); loc_iterator_next(&iter)) {
                        /* use iter.cur */
                        int x = iter.cur.x;
                        int y = iter.cur.y;

and this
Code:

        for (y = y1 - 1; y < y2 + 1; y++) {
                for (x = x1 - 1; x < x2 + 1; x++) {

can be translated as
Code:

        for (struct loc_iterator iter = loc_iterator(loc(x1 - 1, y1 - 1), loc(x2 + 1, y2 + 1));
                loc_iterator_test(&iter); loc_iterator_next(&iter)) {

Values for initializers and conditions can be directly translated, provided conditions are exclusive (if inclusive, add +1 for x and y for loc end).

It is indeed much nicer. I've updated my iterator to reflect on this, keeping pointers instead of structures because I don't like passing structs to functions.

Gwarl August 1, 2019 10:48

Quote:

Originally Posted by Pete Mack (Post 139458)
Yeah, that is sometimes a problem, too. But it was the illumination code that used to have "show reduced light radius while running" performance optimization. And it is running--and only runnning--where performance matters.

Not quite true, resting near a pack of hounds that you can't see also take a while.

But what you're saying makes sense and is interesting.

Pete Mack August 1, 2019 14:44

Fair enough. Running, resting and digging near a vault. They all share the same issue: multiple turns in a single command. Running is the one most used, and digging the one most likely to be slowed by monsters.

Diego Gonzalez August 1, 2019 14:56

Quote:

Originally Posted by Pete Mack (Post 139464)
Fair enough. Running, resting and digging near a vault. They all share the same issue: multiple turns in a single command. Running is the one most used, and digging the one most likely to be slowed by monsters.

The amount of visible subwindows (monsters, objetcs) also affects the performance of running. Sometimes too many redraws is a problem. Perhaps this was solved long ago with an optimization. I don't remember.

Pete Mack August 1, 2019 15:00

Hmm. Redrawing subwindows when the command line is inactive seems particularly useless. Definitely worth checking.

khearn August 1, 2019 17:41

Quote:

Originally Posted by Derakon (Post 139455)
It wouldn't surprise me if modern compilers are capable of saying "Ah, you're invoking this simple function here, we can just inline it" and get the same performance as a macro. In any case, the performance hit of invoking a function is miniscule in this day and age.

Back in the early 90's, I was working in a group doing compiler optimization, and function inlining was definitely a thing way back then.


All times are GMT +1. The time now is 04:07.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2022, vBulletin Solutions Inc.