Skip to content

Commit

Permalink
Merge pull request #45 from salesforce/languagedictionary-refactor-2
Browse files Browse the repository at this point in the history
Perf improvement fixes
  • Loading branch information
yoikawa authored Oct 19, 2023
2 parents a208023 + 068e1e0 commit 76ac139
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 85 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*/
public class IniFileUtil {

private static final Interner<String> INTERNER = Interners.newWeakInterner();
private static final Interner<String> INTERNER = Interners.newBuilder().weak().concurrencyLevel(16).build();

/**
* For the given {@link String}, return reference to equal String. Useful for {@link String} deduping.
Expand Down
30 changes: 13 additions & 17 deletions src/main/java/com/force/i18n/grammar/GrammaticalTerm.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@

import static com.force.i18n.commons.util.settings.IniFileUtil.intern;

import java.io.*;
import java.util.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Map;
import java.util.Objects;

import com.force.i18n.HumanLanguage;
import com.force.i18n.LanguageProviderFactory;
import com.force.i18n.grammar.impl.LanguageDeclensionFactory;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableMap;

/**
* Represents a grammatical term; generally one that is declined based on a noun form or other
Expand Down Expand Up @@ -119,13 +123,13 @@ public int hashCode() {

private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(this.declension.getLanguage().getLocaleString());
out.writeInt(this.declension.getLanguage().ordinal());
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
this.name = intern(name);
HumanLanguage ul = LanguageProviderFactory.get().getProvider().getLanguage((String)in.readObject());
HumanLanguage ul = LanguageProviderFactory.get().getProvider().getAll().get(in.readInt());
this.declension = LanguageDeclensionFactory.get().getDeclension(ul);
}

Expand All @@ -138,25 +142,17 @@ public void makeSkinny() {
}

/**
* Utility method used to convert static {@link Map}'s concrete type to a {@link ImmutableSortedMap}.
* {@link ImmutableSortedMap} have a 8 byte overhead per element and are useful for reducing the per element
* overhead, that is traditionally high on most {@code Map} implementations.
* Utility method used to convert static {@link Map}'s concrete type to a {@link ImmutableMap}.
* This copy could take a lot of cost. Used to use SortedMap but hash is way more cheaper.
*
* @param <T>
* the type of the grammatical form for this term
* @param map
* the map to make skinny
* @return A {@link ImmutableSortedMap} created from a {@link Map} of {@link GrammaticalForm}'s (key) to
* @return A {@link ImmutableMap} created from a {@link Map} of {@link GrammaticalForm}'s (key) to
* {@link String}'s (value).
*/
protected <T extends GrammaticalForm> Map<T, String> makeSkinny(Map<T, String> map) {
return ImmutableSortedMap.copyOf(map, new KeyComparator<T>());
}

private static class KeyComparator<T extends GrammaticalForm> implements Comparator<T>, Serializable {
@Override
public int compare(T o1, T o2) {
return o1.getKey().compareTo(o2.getKey());
}
return ImmutableMap.copyOf(map);
}
}
35 changes: 26 additions & 9 deletions src/main/java/com/force/i18n/grammar/impl/BengaliDeclension.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,35 @@

import static com.force.i18n.commons.util.settings.IniFileUtil.intern;

import java.io.*;
import java.util.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import com.force.i18n.HumanLanguage;
import com.force.i18n.grammar.*;
import com.force.i18n.grammar.Adjective;
import com.force.i18n.grammar.AdjectiveForm;
import com.force.i18n.grammar.Article;
import com.force.i18n.grammar.ArticleForm;
import com.force.i18n.grammar.ArticledDeclension;
import com.force.i18n.grammar.LanguageArticle;
import com.force.i18n.grammar.LanguageCase;
import com.force.i18n.grammar.LanguageDeclension;
import com.force.i18n.grammar.LanguageGender;
import com.force.i18n.grammar.LanguageNumber;
import com.force.i18n.grammar.LanguagePosition;
import com.force.i18n.grammar.LanguagePossessive;
import com.force.i18n.grammar.LanguageStartsWith;
import com.force.i18n.grammar.Noun;
import com.force.i18n.grammar.Noun.NounType;
import com.force.i18n.grammar.NounForm;
import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexNounForm;
import com.google.common.collect.ImmutableList;

Expand Down Expand Up @@ -137,11 +160,6 @@ protected boolean validateValues(String name, LanguageCase _case) {
return defaultValidate(name, getDeclension().getFieldForms());
}

@Override
public void makeSkinny() {
values = makeSkinny(values);
}

/**
* Need to override so that a cloned BengaliNoun's values map is a HashMap.
* Else, if you clone() after makeSkinny() has been called, you won't
Expand All @@ -163,7 +181,6 @@ private void writeObject(ObjectOutputStream out) throws IOException {
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
this.values = ComplexGrammaticalForm.deserializeFormMap(in, getDeclension(), TermType.Noun);
makeSkinny();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,38 @@

import static com.force.i18n.commons.util.settings.IniFileUtil.intern;

import java.io.*;
import java.util.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.force.i18n.HumanLanguage;
import com.force.i18n.LanguageProviderFactory;
import com.force.i18n.grammar.*;
import com.force.i18n.grammar.Adjective;
import com.force.i18n.grammar.AdjectiveForm;
import com.force.i18n.grammar.ArticleForm;
import com.force.i18n.grammar.ArticledDeclension;
import com.force.i18n.grammar.ArticledDeclension.LegacyArticledNoun;
import com.force.i18n.grammar.GrammaticalTerm.TermType;
import com.force.i18n.grammar.LanguageArticle;
import com.force.i18n.grammar.LanguageCase;
import com.force.i18n.grammar.LanguageDeclension;
import com.force.i18n.grammar.LanguageGender;
import com.force.i18n.grammar.LanguageNumber;
import com.force.i18n.grammar.LanguagePosition;
import com.force.i18n.grammar.LanguagePossessive;
import com.force.i18n.grammar.LanguageStartsWith;
import com.force.i18n.grammar.ModifierForm;
import com.force.i18n.grammar.Noun;
import com.force.i18n.grammar.NounForm;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;

/**
Expand Down Expand Up @@ -232,12 +255,12 @@ public void appendJsFormReplacement(Appendable a, String termFormVar, String gen
*/
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(this.declension.getLanguage().getLocaleString());
out.writeInt(this.declension.getLanguage().ordinal());
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
HumanLanguage ul = LanguageProviderFactory.get().getProvider().getLanguage((String)in.readObject());
HumanLanguage ul = LanguageProviderFactory.get().getProvider().getAll().get(in.readInt());
this.declension = LanguageDeclensionFactory.get().getDeclension(ul);
}

Expand All @@ -250,19 +273,19 @@ static <T extends ComplexGrammaticalForm> void serializeFormMap(ObjectOutputStre
} else {
out.writeByte(values.size());
for (Map.Entry<T,String> entry : values.entrySet()) {
out.writeByte(entry.getKey().getOrdinal());
out.writeObject(entry.getValue()); // Serialize the "object" because it's been uniquefied
out.writeByte(entry.getKey().getOrdinal());
out.writeUTF(entry.getValue()); // Serialize the "object" because it's been uniquefied
}
}
}

@SuppressWarnings("unchecked") // Deserializing a map using trickery
static <T extends ComplexGrammaticalForm> Map<T, String> deserializeFormMap(ObjectInputStream in, LanguageDeclension declension, TermType termType) throws IOException, ClassNotFoundException {
int size = in.readByte();
Map<T, String> result = new HashMap<>(size << 1);
if (size == 0) {
return result;
return ImmutableMap.of();
}
ImmutableMap.Builder<T, String> builder = ImmutableMap.builder();
List<T> formList = null;
switch (termType) {
case Noun: formList = (List<T>)declension.getAllNounForms(); break;
Expand All @@ -272,10 +295,10 @@ static <T extends ComplexGrammaticalForm> Map<T, String> deserializeFormMap(Obje
assert formList != null;
for (int i = 0; i < size; i++) {
int ordinal = in.readByte();
String value = intern((String) in.readObject());
result.put(formList.get(ordinal), value);
String value = intern(in.readUTF());
builder.put(formList.get(ordinal), value);
}
return result;
return builder.build();
}


Expand Down Expand Up @@ -512,12 +535,6 @@ private void writeObject(ObjectOutputStream out) throws IOException {
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
this.values = ComplexGrammaticalForm.deserializeFormMap(in, getDeclension(), TermType.Adjective);
makeSkinny();
}

@Override
public void makeSkinny() {
values = makeSkinny(values);
}
}

Expand Down Expand Up @@ -572,12 +589,6 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
in.defaultReadObject();

this.values = ComplexGrammaticalForm.deserializeFormMap(in, getDeclension(), TermType.Noun);
makeSkinny();
}

@Override
public void makeSkinny() {
values = makeSkinny(values);
}
}

Expand Down Expand Up @@ -634,12 +645,6 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
in.defaultReadObject();

this.values = ComplexGrammaticalForm.deserializeFormMap(in, getDeclension(), TermType.Noun);
makeSkinny();
}

@Override
public void makeSkinny() {
values = makeSkinny(values);
}
}
}
31 changes: 22 additions & 9 deletions src/main/java/com/force/i18n/grammar/impl/DravidianDeclension.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,31 @@

import static com.force.i18n.commons.util.settings.IniFileUtil.intern;

import java.io.*;
import java.util.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.force.i18n.HumanLanguage;
import com.force.i18n.grammar.*;
import com.force.i18n.grammar.AbstractLanguageDeclension;
import com.force.i18n.grammar.Adjective;
import com.force.i18n.grammar.AdjectiveForm;
import com.force.i18n.grammar.LanguageArticle;
import com.force.i18n.grammar.LanguageCase;
import com.force.i18n.grammar.LanguageDeclension;
import com.force.i18n.grammar.LanguageGender;
import com.force.i18n.grammar.LanguageNumber;
import com.force.i18n.grammar.LanguagePosition;
import com.force.i18n.grammar.LanguagePossessive;
import com.force.i18n.grammar.LanguageStartsWith;
import com.force.i18n.grammar.Noun;
import com.force.i18n.grammar.Noun.NounType;
import com.force.i18n.grammar.NounForm;
import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexNounForm;
import com.google.common.collect.ImmutableList;

Expand Down Expand Up @@ -123,11 +142,6 @@ protected boolean validateValues(String name, LanguageCase _case) {
return defaultValidate(name, getDeclension().getFieldForms());
}

@Override
public void makeSkinny() {
values = makeSkinny(values);
}

/**
* Need to override so that a cloned DravidianNoun's values map is a HashMap.
* Else, if you clone() after makeSkinny() has been called, you won't
Expand Down Expand Up @@ -157,7 +171,6 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
in.defaultReadObject();

this.values = ComplexGrammaticalForm.deserializeFormMap(in, getDeclension(), TermType.Noun);
makeSkinny();
}
}

Expand Down
47 changes: 36 additions & 11 deletions src/main/java/com/force/i18n/grammar/impl/GermanicDeclension.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,47 @@

import static com.force.i18n.commons.util.settings.IniFileUtil.intern;

import java.io.*;
import java.util.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Logger;

import com.force.i18n.HumanLanguage;
import com.force.i18n.commons.text.CaseFolder;
import com.force.i18n.grammar.*;
import com.force.i18n.grammar.Adjective;
import com.force.i18n.grammar.AdjectiveForm;
import com.force.i18n.grammar.Article;
import com.force.i18n.grammar.ArticleForm;
import com.force.i18n.grammar.ArticledDeclension;
import com.force.i18n.grammar.LanguageArticle;
import com.force.i18n.grammar.LanguageCase;
import com.force.i18n.grammar.LanguageDeclension;
import com.force.i18n.grammar.LanguageGender;
import com.force.i18n.grammar.LanguageNumber;
import com.force.i18n.grammar.LanguagePosition;
import com.force.i18n.grammar.LanguagePossessive;
import com.force.i18n.grammar.LanguageStartsWith;
import com.force.i18n.grammar.Noun;
import com.force.i18n.grammar.Noun.NounType;
import com.force.i18n.grammar.impl.ComplexGrammaticalForm.*;
import com.google.common.collect.*;
import com.force.i18n.grammar.NounForm;
import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexAdjective;
import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexAdjectiveForm;
import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexArticleForm;
import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexArticledNoun;
import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ComplexNounForm;
import com.force.i18n.grammar.impl.ComplexGrammaticalForm.ModifierFormMap;
import com.force.i18n.grammar.impl.ComplexGrammaticalForm.NounFormMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

/**
* Provide a declension system for a germanic language. Generally, there are
Expand Down Expand Up @@ -341,12 +372,6 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
in.defaultReadObject();

this.values = ComplexGrammaticalForm.deserializeFormMap(in, getDeclension(), TermType.Article);
makeSkinny();
}

@Override
public void makeSkinny() {
values = makeSkinny(values);
}
}

Expand Down
Loading

0 comments on commit 76ac139

Please sign in to comment.