基本的に、この投稿は挑戦です。私は今日、HTML エスケープ関数を最適化しようとしてきましたが、中程度の成功を収めています。しかし、おそらく私よりもうまくこの方法を実行できる真面目な Java ハッカーが何人かいることを私は知っています。
Java Web アプリのプロファイリングを行ったところ、主要なホットスポットは String エスケープ関数であることがわかりました。現在、このタスクにはApache Commons Langを使用し、StringEscapeUtils.escapeHtml() を呼び出しています。非常に広く使用されているため、かなり高速であると想定していましたが、私の最も単純な実装でさえ、大幅に高速でした。
以下は、Naive 実装と共に使用したベンチマーク コードです。さまざまな長さの文字列をテストします。プレーン テキストのみを含むものもあれば、エスケープが必要な HTML を含むものもあります。
public class HTMLEscapeBenchmark {
public static String escapeHtml(String text) {
if (text == null) return null;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
if (c == '&') {
sb.append("&");
} else if (c == '\'') {
sb.append("'");
} else if (c == '"') {
sb.append(""");
} else if (c == '<') {
sb.append("<");
} else if (c == '>') {
sb.append(">");
} else {
sb.append(c);
}
}
return sb.toString();
}
/*
public static String escapeHtml(String text) {
if (text == null) return null;
return StringEscapeUtils.escapeHtml(text);
}
*/
public static void main(String[] args) {
final int RUNS = 5;
final int ITERATIONS = 1000000;
// Standard lorem ipsum text.
String loremIpsum = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut " +
"labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " +
"aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum " +
"dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia " +
"deserunt mollit anim id est laborum. ";
while (loremIpsum.length() < 1000) loremIpsum += loremIpsum;
// Add some characters that need HTML escaping. Bold every 2 and 3 letter word, quote every 5 letter word.
String loremIpsumHtml = loremIpsum.replaceAll("[A-Za-z]{2}]", "<b>$0</b>").replaceAll("[A-Za-z]{5}", "\"$0\"");
System.out.print("\nNormal-10");
String text = loremIpsum.substring(0, 10);
for (int run = 1; run <= RUNS; run++) {
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
escapeHtml(text);
}
System.out.printf("\t%.3f", (System.nanoTime() - start) / 1e9);
}
System.out.print("\nNormal-100");
text = loremIpsum.substring(0, 100);
for (int run = 1; run <= RUNS; run++) {
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
escapeHtml(text);
}
System.out.printf("\t%.3f", (System.nanoTime() - start) / 1e9);
}
System.out.print("\nNormal-1000");
text = loremIpsum.substring(0, 1000);
for (int run = 1; run <= RUNS; run++) {
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
escapeHtml(text);
}
System.out.printf("\t%.3f", (System.nanoTime() - start) / 1e9);
}
System.out.print("\nHtml-10");
text = loremIpsumHtml.substring(0, 10);
for (int run = 1; run <= RUNS; run++) {
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
escapeHtml(text);
}
System.out.printf("\t%.3f", (System.nanoTime() - start) / 1e9);
}
System.out.print("\nHtml-100");
text = loremIpsumHtml.substring(0, 100);
for (int run = 1; run <= RUNS; run++) {
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
escapeHtml(text);
}
System.out.printf("\t%.3f", (System.nanoTime() - start) / 1e9);
}
System.out.print("\nHtml-1000");
text = loremIpsumHtml.substring(0, 1000);
for (int run = 1; run <= RUNS; run++) {
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS; i++) {
escapeHtml(text);
}
System.out.printf("\t%.3f", (System.nanoTime() - start) / 1e9);
}
}
}
私の 2 年前の MacBook Pro では、次の結果が得られました。
Commons Lang StringEscapeUtils.escapeHtml
Normal-10 0.439 0.357 0.351 0.343 0.342
Normal-100 2.244 0.934 0.930 0.932 0.931
Normal-1000 8.993 9.020 9.007 9.043 9.052
Html-10 0.270 0.259 0.258 0.258 0.257
Html-100 1.769 1.753 1.765 1.754 1.759
Html-1000 17.313 17.479 17.347 17.266 17.246
単純な実装
Normal-10 0.111 0.091 0.086 0.084 0.088
Normal-100 0.636 0.627 0.626 0.626 0.627
Normal-1000 5.740 5.755 5.721 5.728 5.720
Html-10 0.145 0.138 0.138 0.138 0.138
Html-100 0.899 0.901 0.896 0.901 0.900
Html-1000 8.249 8.288 8.272 8.262 8.284
私自身の最善の最適化の試みを回答として投稿します。それで、私の質問は、あなたはもっとうまくやれるでしょうか?HTML をエスケープする最速の方法は何ですか?