Skip to content

fix(firestore): Further improved performance of UTF-8 string comparison logic #7098

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 35 commits into
base: main
Choose a base branch
from

Conversation

dconeybe
Copy link
Contributor

@dconeybe dconeybe commented Jul 3, 2025

Further improved performance of UTF-8 string ordering logic, which had degraded in v25.1.2 due to the fix #6615 and received some improvements in v25.1.3 by the fix #6706. Even with these improvements, customers still observed a material performance degradation (#7053), which this PR addresses.

This PR was ported to the web sdk in firebase/firebase-js-sdk#9143

Fixes: #7053

Copy link
Contributor

github-actions bot commented Jul 3, 2025

Firebase AI Mock Responses Check ⚠️

A newer major version of the mock responses for Firebase AI unit tests is available. update_responses.sh should be updated to clone the latest version of the responses: v14.2

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary of Changes

Hello @dconeybe, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers a critical performance enhancement for Firestore's UTF-8 string ordering logic, which had previously regressed and caused customer-reported issues. It introduces a new, highly optimized comparison utility that avoids memory allocations, ensuring faster and more efficient string operations. This change also refactors the codebase by centralizing the comparison logic and updating existing components to leverage the new, improved implementation, alongside adding robust test coverage.

Highlights

  • Performance Improvement: Implemented a highly optimized, allocation-free UTF-8 string comparison logic to address significant performance degradation in Firestore's string ordering, specifically fixing issue #7053.
  • Code Refactoring: Extracted the UTF-8 string comparison logic into a new dedicated Utf8Compare utility class, centralizing the functionality and removing the less efficient, previous implementation from Util.java.
  • Test Coverage: Introduced a new comprehensive test suite for the Utf8Compare class, including extensive random string generation to validate correctness across various Unicode characters and surrogate pairs.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@dconeybe dconeybe requested a review from Copilot July 3, 2025 05:21
Copilot

This comment was marked as outdated.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The pull request introduces a new Utf8Compare class to improve the performance of UTF-8 string comparisons. The changes involve replacing calls to Util.compareUtf8Strings with Utf8Compare.compareUtf8Strings in BasePath and Values classes. Additionally, a new test class Utf8CompareTest is added to verify the correctness of the new comparison logic. The old implementation of compareUtf8Strings is removed from Util class. The debug checks in Utf8Compare class could be improved by logging errors instead of throwing exceptions.

@dconeybe dconeybe requested a review from Copilot July 3, 2025 05:27
Copilot

This comment was marked as outdated.

@google-oss-bot
Copy link
Contributor

google-oss-bot commented Jul 3, 2025

Coverage Report 1

Affected Products

  • firebase-firestore

    Overall coverage changed from 45.78% (ec904ec) to 45.75% (a59e638) by -0.03%.

    FilenameBase (ec904ec)Merge (a59e638)Diff
    LruGarbageCollector.java97.27%93.64%-3.64%
    Util.java75.80%74.67%-1.13%

Test Logs

  1. https://storage.googleapis.com/firebase-sdk-metric-reports/idXtzwkt36.html

Copy link
Contributor

github-actions bot commented Jul 3, 2025

Test Results

  186 files   -   797    186 suites   - 797   4m 42s ⏱️ - 29m 1s
1 235 tests  - 4 317  1 219 ✅  - 4 311  16 💤  -  5  0 ❌  - 1 
2 494 runs   - 8 486  2 462 ✅  - 8 475  32 💤  - 10  0 ❌  - 1 

Results for commit 02c2371. ± Comparison against base commit ec904ec.

This pull request removes 4317 tests.
com.google.android.datatransport.cct.CctBackendFactoryTest ‑ create_returnCCTBackend_WhenBackendNameIsCCT
com.google.android.datatransport.cct.CctDestinationTest ‑ cctDestination_shouldOnlySupportProtoAndJson
com.google.android.datatransport.cct.CctDestinationTest ‑ cctDestination_shouldSupportProtoAndJson
com.google.android.datatransport.cct.CctTransportBackendTest ‑ decorate_whenOffline_shouldProperlyPopulateNetworkInfo
com.google.android.datatransport.cct.CctTransportBackendTest ‑ decorate_whenOnline_shouldProperlyPopulateNetworkInfo
com.google.android.datatransport.cct.CctTransportBackendTest ‑ schedule_shouldAddCookieOnPseudonymousIds
com.google.android.datatransport.cct.CctTransportBackendTest ‑ schedule_shouldDropCookieOnMixedPseudonymousIds
com.google.android.datatransport.cct.CctTransportBackendTest ‑ send_CompressedResponseIsUncompressed
com.google.android.datatransport.cct.CctTransportBackendTest ‑ send_whenBackendRedirectsMoreThan5Times_shouldOnlyRedirect4Times
com.google.android.datatransport.cct.CctTransportBackendTest ‑ send_whenBackendRedirects_shouldCorrectlyFollowTheRedirectViaPost
…

♻️ This comment has been updated with latest results.

@google-oss-bot
Copy link
Contributor

google-oss-bot commented Jul 3, 2025

Size Report 1

Affected Products

  • firebase-firestore

    TypeBase (ec904ec)Merge (a59e638)Diff
    aar1.45 MB1.45 MB-193 B (-0.0%)
    apk (release)11.4 MB11.4 MB-84 B (-0.0%)

Test Logs

  1. https://storage.googleapis.com/firebase-sdk-metric-reports/yB1AneUDst.html

@google-oss-bot
Copy link
Contributor

google-oss-bot commented Jul 3, 2025

Startup Time Report 1

Note: Layout is sometimes suboptimal due to limited formatting support on GitHub. Please check this report on GCS.

Notes

Startup Times

  • fire-fst

    DeviceStatisticsDistributions
    oriole-32
    Percentileec904eca59e638DiffSignificant (?)
    p10274 ±9.5 μs272 ±8 μs-1.54 μs (-0.6%)NO
    p25282 ±12 μs279 ±8 μs-3.48 μs (-1.2%)NO
    p50294 ±16 μs289 ±11 μs-5.48 μs (-1.9%)NO
    p75320 ±51 μs314 ±43 μs-6.26 μs (-2.0%)NO
    p90352 ±72 μs334 ±52 μs-17.6 μs (-5.0%)NO

    20 test runs in comparison
    CommitTest Runs
    ec904ec
    • 2025-07-03_16:24:19.199611_pysa
    • 2025-07-03_16:24:19.200364_ndEz
    • 2025-07-03_16:24:19.200373_Yqpm
    • 2025-07-03_16:24:19.200379_Igtb
    • 2025-07-03_16:24:19.200384_HAKd
    • 2025-07-03_16:24:19.200388_MDEB
    • 2025-07-03_16:24:19.200392_iGWT
    • 2025-07-03_16:24:19.200395_CXMT
    • 2025-07-03_16:24:19.200399_kUjW
    • 2025-07-03_16:24:19.200403_iJFD
    a59e638
    • 2025-07-03_20:19:27.492254_uQrE
    • 2025-07-03_20:19:27.493756_AlMM
    • 2025-07-03_20:19:27.493766_jQIs
    • 2025-07-03_20:19:27.493772_jtwX
    • 2025-07-03_20:19:27.493777_qjOn
    • 2025-07-03_20:19:27.493781_NvqW
    • 2025-07-03_20:19:27.493785_cqwV
    • 2025-07-03_20:19:27.493789_MoTJ
    • 2025-07-03_20:19:27.493793_VIaD
    • 2025-07-03_20:19:27.493797_ySvG
    redfin-30
    Percentileec904eca59e638DiffSignificant (?)
    p10491 ±28 μs501 ±29 μs+10.3 μs (+2.1%)NO
    p25513 ±33 μs523 ±30 μs+9.77 μs (+1.9%)NO
    p50539 ±36 μs555 ±34 μs+15.9 μs (+3.0%)NO
    p75569 ±40 μs588 ±40 μs+19.1 μs (+3.4%)NO
    p90608 ±41 μs633 ±49 μs+25.0 μs (+4.1%)NO

    20 test runs in comparison
    CommitTest Runs
    ec904ec
    • 2025-07-03_16:24:19.199611_pysa
    • 2025-07-03_16:24:19.200364_ndEz
    • 2025-07-03_16:24:19.200373_Yqpm
    • 2025-07-03_16:24:19.200379_Igtb
    • 2025-07-03_16:24:19.200384_HAKd
    • 2025-07-03_16:24:19.200388_MDEB
    • 2025-07-03_16:24:19.200392_iGWT
    • 2025-07-03_16:24:19.200395_CXMT
    • 2025-07-03_16:24:19.200399_kUjW
    • 2025-07-03_16:24:19.200403_iJFD
    a59e638
    • 2025-07-03_20:19:27.492254_uQrE
    • 2025-07-03_20:19:27.493756_AlMM
    • 2025-07-03_20:19:27.493766_jQIs
    • 2025-07-03_20:19:27.493772_jtwX
    • 2025-07-03_20:19:27.493777_qjOn
    • 2025-07-03_20:19:27.493781_NvqW
    • 2025-07-03_20:19:27.493785_cqwV
    • 2025-07-03_20:19:27.493789_MoTJ
    • 2025-07-03_20:19:27.493793_VIaD
    • 2025-07-03_20:19:27.493797_ySvG
  • timeToInitialDisplay

    DeviceStatisticsDistributions
    oriole-32
    Percentileec904eca59e638DiffSignificant (?)
    p10200 ±4 ms201 ±3 ms+828 μs (+0.4%)NO
    p25205 ±4 ms207 ±3 ms+1.65 ms (+0.8%)NO
    p50211 ±5 ms213 ±3 ms+1.97 ms (+0.9%)NO
    p75219 ±5 ms221 ±3 ms+1.50 ms (+0.7%)NO
    p90226 ±5 ms232 ±7 ms+6.09 ms (+2.7%)NO

    20 test runs in comparison
    CommitTest Runs
    ec904ec
    • 2025-07-03_16:24:19.199611_pysa
    • 2025-07-03_16:24:19.200364_ndEz
    • 2025-07-03_16:24:19.200373_Yqpm
    • 2025-07-03_16:24:19.200379_Igtb
    • 2025-07-03_16:24:19.200384_HAKd
    • 2025-07-03_16:24:19.200388_MDEB
    • 2025-07-03_16:24:19.200392_iGWT
    • 2025-07-03_16:24:19.200395_CXMT
    • 2025-07-03_16:24:19.200399_kUjW
    • 2025-07-03_16:24:19.200403_iJFD
    a59e638
    • 2025-07-03_20:19:27.492254_uQrE
    • 2025-07-03_20:19:27.493756_AlMM
    • 2025-07-03_20:19:27.493766_jQIs
    • 2025-07-03_20:19:27.493772_jtwX
    • 2025-07-03_20:19:27.493777_qjOn
    • 2025-07-03_20:19:27.493781_NvqW
    • 2025-07-03_20:19:27.493785_cqwV
    • 2025-07-03_20:19:27.493789_MoTJ
    • 2025-07-03_20:19:27.493793_VIaD
    • 2025-07-03_20:19:27.493797_ySvG
    redfin-30
    Percentileec904eca59e638DiffSignificant (?)
    p10224 ±4 ms245 ±5 ms+21.0 ms (+9.4%)YES
    p25230 ±4 ms251 ±4 ms+21.2 ms (+9.2%)MAYBE
    p50239 ±4 ms259 ±4 ms+20.0 ms (+8.4%)MAYBE
    p75247 ±5 ms268 ±5 ms+20.8 ms (+8.4%)MAYBE
    p90256 ±5 ms279 ±6 ms+23.1 ms (+9.0%)MAYBE

    20 test runs in comparison
    CommitTest Runs
    ec904ec
    • 2025-07-03_16:24:19.199611_pysa
    • 2025-07-03_16:24:19.200364_ndEz
    • 2025-07-03_16:24:19.200373_Yqpm
    • 2025-07-03_16:24:19.200379_Igtb
    • 2025-07-03_16:24:19.200384_HAKd
    • 2025-07-03_16:24:19.200388_MDEB
    • 2025-07-03_16:24:19.200392_iGWT
    • 2025-07-03_16:24:19.200395_CXMT
    • 2025-07-03_16:24:19.200399_kUjW
    • 2025-07-03_16:24:19.200403_iJFD
    a59e638
    • 2025-07-03_20:19:27.492254_uQrE
    • 2025-07-03_20:19:27.493756_AlMM
    • 2025-07-03_20:19:27.493766_jQIs
    • 2025-07-03_20:19:27.493772_jtwX
    • 2025-07-03_20:19:27.493777_qjOn
    • 2025-07-03_20:19:27.493781_NvqW
    • 2025-07-03_20:19:27.493785_cqwV
    • 2025-07-03_20:19:27.493789_MoTJ
    • 2025-07-03_20:19:27.493793_VIaD
    • 2025-07-03_20:19:27.493797_ySvG

  1. https://storage.googleapis.com/firebase-sdk-metric-reports/Omz5KtzxeS/index.html

@dconeybe dconeybe requested a review from Copilot July 3, 2025 18:31
@dconeybe
Copy link
Contributor Author

dconeybe commented Jul 3, 2025

/gemini review

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR replaces the previous UTF-8 byte-oriented string comparison with a more efficient surrogate-aware char-by-char algorithm and updates the changelog to document the fix.

  • Simplified compareUtf8Strings to a single-pass char comparison using Character.isSurrogate
  • Removed ByteString fallback and eliminated codePoint/substring overhead
  • Added an unreleased entry in CHANGELOG.md for the performance fix

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
firebase-firestore/src/main/java/com/google/firebase/firestore/util/Util.java Rewrote compareUtf8Strings with optimized surrogate-aware logic; removed helper and ByteString paths
firebase-firestore/CHANGELOG.md Documented the UTF-8 comparison performance improvement under Unreleased
Comments suppressed due to low confidence (2)

firebase-firestore/src/main/java/com/google/firebase/firestore/util/Util.java:90

  • Update this Javadoc to describe the new surrogate-aware, char-by-char comparison algorithm rather than the previous byte-level UTF-8 logic.
  /** Compare strings in UTF-8 encoded byte order */

firebase-firestore/src/main/java/com/google/firebase/firestore/util/Util.java:113

  • Add unit tests covering edge cases around surrogate pairs versus non-surrogate characters to verify the new comparison logic across diverse Unicode inputs.
    for (int i = 0; i < length; i++) {

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a performance improvement to the UTF-8 string comparison logic by avoiding object allocations. Suggestions have been provided to improve code readability.

Copy link
Contributor

@wu-hui wu-hui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wonderful, thanks Denver!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Firestore snapshot read performance hit on Android when upgrading to BoM 33.9.0 (Firestore 25.1.2)
3 participants