Skip to content

Commit 430bbba

Browse files
rijnbclaude
andcommitted
perf: A1 — cache flags per loop iteration in hot paths
In encoderEngine and decoderEngine inner loops, read TERRITORY_BOUNDARIES[i].flags once per iteration into a const local and extract bit fields from it, instead of using flag-extraction macros that each re-dereference the same memory. Same change in firstNamelessRecord and countNamelessRecords. Bit-exact: macros stay defined and used in cold paths; only the inner loop body call sites were rewritten to local reads. time ./unittest (best of 3, user): baseline (T0) = 114.13s after A1 (T2) = 111.78s delta = 2.06% cumulative Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent f1cb736 commit 430bbba

1 file changed

Lines changed: 31 additions & 12 deletions

File tree

mapcodelib/mapcoder.c

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,13 @@ static int firstNamelessRecord(const int m, const int firstcode) {
824824
const int codexm = coDex(m);
825825
ASSERT((0 <= m) && (m <= MAPCODE_BOUNDARY_MAX));
826826
ASSERT((0 <= firstcode) && (firstcode <= MAPCODE_BOUNDARY_MAX));
827-
while (i >= firstcode && coDex(i) == codexm && IS_NAMELESS(i)) {
827+
while (i >= firstcode) {
828+
const int flags = TERRITORY_BOUNDARIES[i].flags;
829+
const int c = flags & 31;
830+
const int codexi = 10 * (c / 5) + ((c % 5) + 1);
831+
if (codexi != codexm || !(flags & 64)) {
832+
break;
833+
}
828834
i--;
829835
}
830836
return (i + 1);
@@ -838,7 +844,12 @@ static int countNamelessRecords(const int m, const int firstcode) {
838844
int last = m;
839845
ASSERT((0 <= m) && (m <= MAPCODE_BOUNDARY_MAX));
840846
ASSERT((0 <= firstcode) && (firstcode <= MAPCODE_BOUNDARY_MAX));
841-
while (coDex(last) == codexm) {
847+
while (1) {
848+
const int c = TERRITORY_BOUNDARIES[last].flags & 31;
849+
const int codexLast = 10 * (c / 5) + ((c % 5) + 1);
850+
if (codexLast != codexm) {
851+
break;
852+
}
842853
last++;
843854
}
844855
ASSERT((0 <= last) && (last <= MAPCODE_BOUNDARY_MAX));
@@ -1486,10 +1497,14 @@ static void encoderEngine(const enum Territory ccode, const EncodeRec* enc, cons
14861497
*result = 0;
14871498
for (i = from; i <= upto; i++) {
14881499
if (fitsInsideBoundaries(&enc->coord32, TERRITORY_BOUNDARY(i))) {
1489-
if (IS_NAMELESS(i)) {
1500+
const int flags = TERRITORY_BOUNDARIES[i].flags;
1501+
const int isNameless = (flags & 64);
1502+
const int recType = (flags >> 7) & 3;
1503+
const int isRestricted = (flags & 512);
1504+
if (isNameless) {
14901505
encodeNameless(result, enc, ccode, extraDigits, i);
14911506
}
1492-
else if (REC_TYPE(i) > 1) {
1507+
else if (recType > 1) {
14931508
encodeAutoHeader(result, enc, i, extraDigits);
14941509
}
14951510
else if ((i == upto) && isSubdivision(ccode)) {
@@ -1501,9 +1516,11 @@ static void encoderEngine(const enum Territory ccode, const EncodeRec* enc, cons
15011516
else // must be grid
15021517
{
15031518
// skip IS_RESTRICTED records unless there already is a result
1504-
if (result_counter || !IS_RESTRICTED(i)) {
1505-
if (coDex(i) < 54) {
1506-
char headerletter = (char)((REC_TYPE(i) == 1) ? HEADER_LETTER(i) : 0);
1519+
if (result_counter || !isRestricted) {
1520+
const int c = flags & 31;
1521+
const int codexLocal = 10 * (c / 5) + ((c % 5) + 1);
1522+
if (codexLocal < 54) {
1523+
const char headerletter = (char)((recType == 1) ? ENCODE_CHARS[(flags >> 11) & 31] : 0);
15071524
encodeGrid(result, enc, i, extraDigits, headerletter);
15081525
}
15091526
}
@@ -2708,10 +2725,12 @@ static enum MapcodeError decoderEngine(DecodeRec* dec, int parseFlags) {
27082725
// try all ccode rectangles to decode s (pointing to first character of proper mapcode), assume not decodable
27092726
err = ERR_MAPCODE_UNDECODABLE;
27102727
for (i = from; i <= upto; i++) {
2711-
const int codexi = coDex(i);
2712-
const int r = REC_TYPE(i);
2728+
const int flags = TERRITORY_BOUNDARIES[i].flags;
2729+
const int c = flags & 31;
2730+
const int codexi = 10 * (c / 5) + ((c % 5) + 1);
2731+
const int r = (flags >> 7) & 3;
27132732
if (r == 0) {
2714-
if (IS_NAMELESS(i)) {
2733+
if (flags & 64) { // IS_NAMELESS
27152734
if (((codexi == 21) && (codex == 22)) ||
27162735
((codexi == 22) && (codex == 32)) ||
27172736
((codexi == 13) && (codex == 23))) {
@@ -2726,7 +2745,7 @@ static enum MapcodeError decoderEngine(DecodeRec* dec, int parseFlags) {
27262745
// first of all, make sure the zone fits the country
27272746
restrictZoneTo(&dec->zone, &dec->zone, TERRITORY_BOUNDARY(upto));
27282747

2729-
if ((err == ERR_OK) && IS_RESTRICTED(i)) {
2748+
if ((err == ERR_OK) && (flags & 512)) { // IS_RESTRICTED
27302749
int nrZoneOverlaps = 0;
27312750
int j;
27322751

@@ -2784,7 +2803,7 @@ static enum MapcodeError decoderEngine(DecodeRec* dec, int parseFlags) {
27842803
}
27852804
}
27862805
else if (r == 1) {
2787-
if (codex == codexi + 10 && HEADER_LETTER(i) == *s) {
2806+
if (codex == codexi + 10 && ENCODE_CHARS[(flags >> 11) & 31] == *s) {
27882807
err = decodeGrid(dec, i, 1);
27892808
break;
27902809
}

0 commit comments

Comments
 (0)