Skip to content

Commit

Permalink
ICU-22419 Performance improvements of collated string comparison
Browse files Browse the repository at this point in the history
  • Loading branch information
Krechals committed Jun 18, 2023
1 parent 388b768 commit c1883c8
Showing 1 changed file with 54 additions and 0 deletions.
54 changes: 54 additions & 0 deletions icu4c/source/i18n/rulebasedcollator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -987,6 +987,33 @@ RuleBasedCollator::doCompare(const char16_t *left, int32_t leftLength,
++equalPrefixLength;
}
} else {
if ((uint32_t)leftLength >= sizeof(uint64_t)
&& (uint32_t)rightLength >= sizeof(uint64_t)
&& (uintptr_t)left % sizeof(uint64_t) == (uintptr_t)right % sizeof(uint64_t)) {
int32_t i = 0;
int32_t limit = leftLength < rightLength ? leftLength : rightLength;

// Memory alignment step.
while(i < limit && left[i] == right[i]
&& (uintptr_t)(left + i) % sizeof(uint64_t) != 0) {
++i;
}
equalPrefixLength += i;

// Double word baesd comparison.
if (i < limit && (uintptr_t)(left + i) % sizeof(uint64_t) == 0) {
const uint64_t *dWordLeft = (const uint64_t *)left;
const uint64_t *dWordRight = (const uint64_t *)right;
int32_t dWordLength = (leftLength < rightLength ? leftLength : rightLength) / sizeof(uint64_t);
i = 0;

while(i < dWordLength && dWordLeft[i] == dWordRight[i]) {
++i;
}
equalPrefixLength = i != 0 ? i * sizeof(uint64_t) / 2 - 1 : 0;
}
}

leftLimit = left + leftLength;
rightLimit = right + rightLength;
for(;;) {
Expand Down Expand Up @@ -1102,6 +1129,33 @@ RuleBasedCollator::doCompare(const uint8_t *left, int32_t leftLength,
++equalPrefixLength;
}
} else {
if ((uint32_t)leftLength >= sizeof(uint64_t)
&& (uint32_t)rightLength >= sizeof(uint64_t)
&& (uintptr_t)left % sizeof(uint64_t) == (uintptr_t)right % sizeof(uint64_t)) {
int32_t i = 0;
int32_t limit = leftLength < rightLength ? leftLength : rightLength;

// Memory alignment step.
while(i < limit && left[i] == right[i]
&& (uintptr_t)(left + i) % sizeof(uint64_t) != 0) {
++i;
}
equalPrefixLength += i;

// Double word baesd comparison.
if (i < limit && (uintptr_t)(left + i) % sizeof(uint64_t) == 0) {
const uint64_t *dWordLeft = (const uint64_t *)left;
const uint64_t *dWordRight = (const uint64_t *)right;
int32_t dWordLength = (leftLength < rightLength ? leftLength : rightLength) / sizeof(uint64_t);
i = 0;

while(i < dWordLength && dWordLeft[i] == dWordRight[i]) {
++i;
}
equalPrefixLength = i != 0 ? i * sizeof(uint64_t) - 1 : 0;
}
}

for(;;) {
if(equalPrefixLength == leftLength) {
if(equalPrefixLength == rightLength) { return UCOL_EQUAL; }
Expand Down

0 comments on commit c1883c8

Please sign in to comment.