Skip to content

Commit

Permalink
Improve performance when getting emoji by alias(#17)
Browse files Browse the repository at this point in the history
Improve performance for getByAlias and sibling methods
  • Loading branch information
freya022 authored Nov 13, 2023
1 parent 5c32de8 commit 8f336b6
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 20 deletions.
17 changes: 13 additions & 4 deletions lib/src/jmh/java/benchmark/EmojiManagerBenchmark.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@
import net.fellbaum.jemoji.EmojiManager;
import net.fellbaum.jemoji.EmojiManagerTest;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

@State(Scope.Benchmark)
public class EmojiManagerBenchmark {

private static final String TEXT = new BufferedReader(new InputStreamReader(Objects.requireNonNull(EmojiManagerBenchmark.class.getClassLoader().getResourceAsStream("ExampleTextFileWithEmojis.txt"))))
Expand Down Expand Up @@ -41,6 +42,14 @@ public static void main(String[] args) throws Exception {

private static final String EMOJIS_RANDOM_ORDER = String.join("", EmojiManager.getAllEmojisLengthDescending().stream().map(Emoji::getEmoji).collect(toShuffledList()));

@Param({":+1:", "nope"})
private String alias;

@Benchmark
public Optional<Emoji> getByAlias() {
return EmojiManager.getByAlias(alias);
}

@Benchmark
//@BenchmarkMode(Mode.AverageTime)
//@Warmup(iterations = 1)
Expand Down
20 changes: 20 additions & 0 deletions lib/src/main/java/net/fellbaum/jemoji/AliasGroup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package net.fellbaum.jemoji;

import java.util.Collection;
import java.util.function.Function;

enum AliasGroup {
DISCORD(Emoji::getDiscordAliases),
GITHUB(Emoji::getGithubAliases),
SLACK(Emoji::getSlackAliases);

private final Function<Emoji, Collection<String>> aliasCollectionSupplier;

AliasGroup(Function<Emoji, Collection<String>> aliasCollectionSupplier) {
this.aliasCollectionSupplier = aliasCollectionSupplier;
}

public Function<Emoji, Collection<String>> getAliasCollectionSupplier() {
return aliasCollectionSupplier;
}
}
48 changes: 32 additions & 16 deletions lib/src/main/java/net/fellbaum/jemoji/EmojiManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public final class EmojiManager {
private static final Map<Integer, List<Emoji>> EMOJI_FIRST_CODEPOINT_TO_EMOJIS_ORDER_CODEPOINT_LENGTH_DESCENDING;
private static final List<Emoji> EMOJIS_LENGTH_DESCENDING;

// Get emoji by alias
private static final Map<AliasGroup, Map<String, Emoji>> ALIAS_GROUP_TO_EMOJI_ALIAS_TO_EMOJI = new EnumMap<>(AliasGroup.class);

private static Pattern EMOJI_PATTERN;
private static final Pattern NOT_WANTED_EMOJI_CHARACTERS = Pattern.compile("[\\p{Alpha}\\p{Z}]");

Expand Down Expand Up @@ -79,6 +82,18 @@ private static String readFileAsString() {
}
}

private static Map<String, Emoji> getEmojiAliasToEmoji(final AliasGroup aliasGroup) {
return ALIAS_GROUP_TO_EMOJI_ALIAS_TO_EMOJI.computeIfAbsent(aliasGroup, group -> {
final Map<String, Emoji> emojiAliasToEmoji = new HashMap<>();
for (final Emoji emoji : EMOJIS_LENGTH_DESCENDING) {
for (final String alias : group.getAliasCollectionSupplier().apply(emoji)) {
emojiAliasToEmoji.put(alias, emoji);
}
}
return Collections.unmodifiableMap(emojiAliasToEmoji);
});
}

private EmojiManager() {
}

Expand Down Expand Up @@ -152,10 +167,12 @@ public static Optional<Emoji> getByAlias(final String alias) {
if (isStringNullOrEmpty(alias)) return Optional.empty();
final String aliasWithoutColon = removeColonFromAlias(alias);
final String aliasWithColon = addColonToAlias(alias);
return EMOJI_UNICODE_TO_EMOJI.values()
.stream()
.filter(emoji -> emoji.getAllAliases().contains(aliasWithoutColon) || emoji.getAllAliases().contains(aliasWithColon))
.findFirst();
return Arrays.stream(AliasGroup.values())
.map(EmojiManager::getEmojiAliasToEmoji)
.filter(m -> m.containsKey(aliasWithColon) || m.containsKey(aliasWithoutColon))
.map(m -> findEmojiByEitherAlias(m, aliasWithColon, aliasWithoutColon))
.findAny()
.flatMap(Function.identity());
}

/**
Expand All @@ -168,10 +185,7 @@ public static Optional<Emoji> getByDiscordAlias(final String alias) {
if (isStringNullOrEmpty(alias)) return Optional.empty();
final String aliasWithoutColon = removeColonFromAlias(alias);
final String aliasWithColon = addColonToAlias(alias);
return EMOJI_UNICODE_TO_EMOJI.values()
.stream()
.filter(emoji -> emoji.getDiscordAliases().contains(aliasWithoutColon) || emoji.getDiscordAliases().contains(aliasWithColon))
.findFirst();
return findEmojiByEitherAlias(getEmojiAliasToEmoji(AliasGroup.DISCORD), aliasWithColon, aliasWithoutColon);
}

/**
Expand All @@ -184,10 +198,7 @@ public static Optional<Emoji> getByGithubAlias(final String alias) {
if (isStringNullOrEmpty(alias)) return Optional.empty();
final String aliasWithoutColon = removeColonFromAlias(alias);
final String aliasWithColon = addColonToAlias(alias);
return EMOJI_UNICODE_TO_EMOJI.values()
.stream()
.filter(emoji -> emoji.getGithubAliases().contains(aliasWithoutColon) || emoji.getGithubAliases().contains(aliasWithColon))
.findFirst();
return findEmojiByEitherAlias(getEmojiAliasToEmoji(AliasGroup.GITHUB), aliasWithColon, aliasWithoutColon);
}

/**
Expand All @@ -200,10 +211,7 @@ public static Optional<Emoji> getBySlackAlias(final String alias) {
if (isStringNullOrEmpty(alias)) return Optional.empty();
final String aliasWithoutColon = removeColonFromAlias(alias);
final String aliasWithColon = addColonToAlias(alias);
return EMOJI_UNICODE_TO_EMOJI.values()
.stream()
.filter(emoji -> emoji.getSlackAliases().contains(aliasWithoutColon) || emoji.getSlackAliases().contains(aliasWithColon))
.findFirst();
return findEmojiByEitherAlias(getEmojiAliasToEmoji(AliasGroup.SLACK), aliasWithColon, aliasWithoutColon);
}

private static String removeColonFromAlias(final String alias) {
Expand All @@ -214,6 +222,14 @@ private static String addColonToAlias(final String alias) {
return alias.startsWith(":") && alias.endsWith(":") ? alias : ":" + alias + ":";
}

private static <K, V> Optional<V> findEmojiByEitherAlias(final Map<K, V> map, final K aliasWithColon, final K aliasWithoutColon) {
final V firstValue = map.get(aliasWithColon);
if (firstValue != null) return Optional.of(firstValue);
final V secondValue = map.get(aliasWithoutColon);
if (secondValue != null) return Optional.of(secondValue);
return Optional.empty();
}

/**
* Gets the pattern checking for all emojis.
*
Expand Down

0 comments on commit 8f336b6

Please sign in to comment.