Status Update
Comments
si...@google.com <si...@google.com> #2
I tested the PaintCompat.hasGlyph
performance.
PaintCompat.hasGlyph
has two components:
- before API 23 it uses
measureText
for some heuristics to check if emoji is on the system - on and after API 23 it uses
Paint.hasGlyph
Whenever EmojiCompat matches an emoji in a given CharSequence, it makes a call to an internal hasGlyph
implementation.
- Since the heuristics applied in PaintCompat does not work very well, before API 23, EmojiCompat has a shortcut of
if (CurrentSdk < 23 && emoji.metadata.sdkAdded > CurrentSdk) return false
I suspect the report was comparing this shortcut with the regular check while checking the difference for before SDK 23 and after.
The time Paint.hasGlyph takes is
Device | Version | ns | ms |
---|---|---|---|
Nexus 5X | 6.0.1 | 12014 | 0.012 |
Pixel XL | 7.1.2 | 15220 | 0.015 |
Pixel XL | 8.1 | 13482 | 0.013 |
Pixel XL | 9 | 13544 | 0.014 |
Pixel XL | 10 | 15029 | 0.015 |
On the same devices the measureText is around 2x to 3.5x slower.
Device | Version | ns | ms | mesaure/hasGlyph |
---|---|---|---|---|
Nexus 5X | 6.0.1 | 39292 | 0.039 | 3.27 |
Pixel XL | 7.1.2 | 34128 | 0.034 | 2.24 |
Pixel XL | 8.1 | 36356 | 0.036 | 2.70 |
Pixel XL | 9 | 35544 | 0.036 | 2.62 |
Pixel XL | 10 | 35850 | 0.036 | 2.39 |
no...@google.com <no...@google.com> #3
What string are you querying?
There are shortcut of single code point + variation selector.
Also, if there is no glyph in the Typeface, it is always slow path of the query.
I don't know how EmojiCompat uses hasGlyph APIs but if you querying all emojis (let's say over 1000), maybe it would be good to parse cmap/GSUB table by ourselves. You may still need to hasGlyph API for checking the platform capability though.
si...@google.com <si...@google.com> #4
Hi Nonasan,
Here is the benchmark code I used:
I query random emoji.
I don't know how EmojiCompat uses hasGlyph APIs but if you querying all emojis (let's say over 1000), maybe it would be good to parse cmap/GSUB table by ourselves.
This wouldn't work. I am not interested in the EmojiCompat font, but the platform itself. If we knew that there is only NotoEmoji we might be able to check the system font, but I don't think it is a good idea.
ap...@google.com <ap...@google.com> #5
Branch: androidx-master-dev
commit 1b3056f484ecb3b82e300362d42327dce145205a
Author: Siyamed Sinir <siyamed@google.com>
Date: Sun Oct 11 19:25:27 2020
Expose GlyphChecker interface
EmojiCompat.Config accepts GlyphChecker in the API.
Test: Added new tests
Test: ./gradlew emoji:test
Test: ./gradlew emoji:connectedAndroidTest
Relnote: "Added new API `EmojiCompat.Config#setGlyphChecker` that enables developers
to provide custom emoji glyph check behavior."
Bug: 170587912
Change-Id: Ibc95e158765d392cb8726e53b0f8cac7961f0373
M emoji/core/api/current.txt
M emoji/core/api/public_plus_experimental_current.txt
M emoji/core/api/restricted_current.txt
M emoji/core/src/androidTest/java/androidx/emoji/text/ConfigTest.java
M emoji/core/src/androidTest/java/androidx/emoji/text/EmojiCompatTest.java
M emoji/core/src/androidTest/java/androidx/emoji/text/TestConfigBuilder.java
M emoji/core/src/main/java/androidx/emoji/text/EmojiCompat.java
M emoji/core/src/main/java/androidx/emoji/text/EmojiProcessor.java
si...@google.com <si...@google.com>
se...@google.com <se...@google.com> #6
Leaving closed, but listing another option for developers reading this thread:
hasGlyph
is cached in emojicompat per glyph, so one option would be to process a string containing all emoji in a background thread. This would effectively avoid any calls tohasGlyph
to render user-defined strings later.
Description
We had reports that
EmojiProcessor.hasGlyph
is rather heavy on API 23+ despite the cache where each emoji is checked for rendering only once for each EmojiCompat instance.Investigate the culprit.