Skip to content

Commit 2ead6d8

Browse files
sparhamicopybara-github
authored andcommitted
Make Soy+Incrementaldom key comparison a bit faster in some cases.
PiperOrigin-RevId: 910224583
1 parent bd6b16a commit 2ead6d8

1 file changed

Lines changed: 27 additions & 10 deletions

File tree

javascript/api_idom.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -688,27 +688,44 @@ export class NullRenderer extends IncrementalDomRendererImpl {
688688
* proposedKey -> 1c1b, currentPointerKey -> 1d1c1b1a
689689
*/
690690
export function isMatchingKey(
691-
proposedKey: unknown,
692-
currentPointerKey: unknown,
691+
proposedKey: incrementaldom.Key,
692+
currentPointerKey: incrementaldom.Key,
693693
): boolean {
694694
// Using "==" instead of "===" is intentional. SSR serializes attributes
695695
// differently than the type that keys are. For example "0" == 0.
696696
// tslint:disable-next-line:triple-equals
697697
if (proposedKey == currentPointerKey) {
698698
return true;
699699
}
700-
// This is always true in Soy-IDOM, but Incremental DOM believes that it may
700+
701+
// This is always false in Soy-IDOM, but Incremental DOM believes that it may
701702
// be null or number.
702703
if (
703-
typeof proposedKey === 'string' &&
704-
typeof currentPointerKey === 'string'
704+
typeof proposedKey !== 'string' ||
705+
typeof currentPointerKey !== 'string'
705706
) {
706-
return (
707-
proposedKey.startsWith(currentPointerKey) ||
708-
currentPointerKey.startsWith(proposedKey)
709-
);
707+
return false;
708+
}
709+
710+
const proposedKeyLength = proposedKey.length;
711+
const currentPointerKeyLength = currentPointerKey.length;
712+
// If these have the same length, then they must be different or we would
713+
// have returned true already. This is a cheap check and xids used for keys
714+
// are usually(?) the same length.
715+
if (proposedKeyLength === currentPointerKeyLength) {
716+
return false;
710717
}
711-
return false;
718+
719+
// See if one string starts with the other. In order for this to be true, the
720+
// shorter string must be a prefix of the longer string.
721+
// Slice is fast (string views) and this is faster than using startsWith even
722+
// with just one comparison in each direction. Perhaps the string views get
723+
// reused with a computed hashcode?
724+
if (proposedKeyLength > currentPointerKeyLength) {
725+
return proposedKey.slice(0, currentPointerKeyLength) === currentPointerKey;
726+
}
727+
728+
return currentPointerKey.slice(0, proposedKeyLength) === proposedKey;
712729
}
713730

714731
function debugReplacerHashingMessages(k: unknown, v: unknown): unknown {

0 commit comments

Comments
 (0)