apache / apache/lucene

ASCIIFoldingFilter.foldToASCII performance issue due to large compiled method size [LUCENE-7525]

Open
#8,576 20 comments 0 reactions 0 assignees View on GitHub
affects-version:6.2.1 legacy-jira-priority:Major module:analysis type:enhancement
Dominant language
Java
Stars
3.6k
Forks
1.4k
Avg merge
2d 11h
Merged PRs (30d)
88

Description

The `ASCIIFoldingFilter.foldToASCII` method has an enormous switch statement and is too large for the HotSpot compiler to compile; causing a performance problem.

The method is about 13K compiled, versus the 8KB HotSpot limit. So splitting the method in half works around the problem.

In my tests splitting the method in half resulted in a 5X performance increase.

In the test code below you can see how slow the fold method is, even when it is using the shortcut when the character is less than 0x80, compared to an inline implementation of the same shortcut.

So a workaround is to split the method. I'm happy to provide a patch. It's a hack, of course. Perhaps using the `MappingCharFilterFactory` with an input file as per [SOLR-2013](https://issues.apache.org/jira/browse/SOLR-2013) would be a better replacement for this method in this class?

```java
public class ASCIIFoldingFilterPerformanceTest {

private static final int ITERATIONS = 1_000_000;

`@Test`
public void testFoldShortString() {
char[] input = "testing".toCharArray();
char[] output = new char[input.length * 4];

for (int i = 0; i < ITERATIONS; i++) {
ASCIIFoldingFilter.foldToASCII(input, 0, output, 0, input.length);
}
}

`@Test`
public void testFoldShortAccentedString() {
char[] input = "éúéúøßüäéúéúøßüä".toCharArray();
char[] output = new char[input.length * 4];

for (int i = 0; i < ITERATIONS; i++) {
ASCIIFoldingFilter.foldToASCII(input, 0, output, 0, input.length);
}
}

`@Test`
public void testManualFoldTinyString() {
char[] input = "t".toCharArray();
char[] output = new char[input.length * 4];

for (int i = 0; i < ITERATIONS; i++) {
int k = 0;
for (int j = 0; j < 1; ++j) {
final char c = input[j];
if (c < '\u0080') {
output[k++] = c;
} else {
Assert.assertTrue(false);
}
}
}
}
}
```

---
Migrated from [LUCENE-7525](https://issues.apache.org/jira/browse/LUCENE-7525) by Karl von Randow, 1 vote, updated Mar 26 2017
Attachments: [ASCIIFolding.java](https://apache.github.io/lucene-jira-archive/attachments/LUCENE-7525/ASCIIFolding.java), [ASCIIFoldingFilter.java](https://apache.github.io/lucene-jira-archive/attachments/LUCENE-7525/ASCIIFoldingFilter.java), [LUCENE-7525.patch](https://apache.github.io/lucene-jira-archive/attachments/LUCENE-7525/LUCENE-7525.patch) (versions: 2), [TestASCIIFolding.java](https://apache.github.io/lucene-jira-archive/attachments/LUCENE-7525/TestASCIIFolding.java)

Contributor guide

Open the contributing guide

Research direction

Start with ASCIIFoldingFilter.foldToASCII and read the attached ASCIIFolding.java, ASCIIFoldingFilter.java, and TestASCIIFolding.java; run the supplied performance tests to reproduce the HotSpot method-size effect. Compare the attached LUCENE-7525.patch and verify that any accepted change preserves folding behavior while improving the benchmark.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
performance, search
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.