私のテストによると、はパフォーマンスに大きな違いがありませんです。
各実行では、各シナリオで1,000万回の試行が行われ、実行時間がナノ秒単位と同様に丸められた秒単位で比較されます。これは実際に私の元の仮説に反しています。私はThrowable
を捕まえれば、目に見える改善が見られると考えていました。
また、この部分がオプティマイザの影響を受けている可能性があることもわかり始めたので、オプティマイザが持つ潜在的な影響を緩和するため、疑似乱数を含む複雑な例を作成しました。コード上に
(質問は具体的には約パフォーマンス、ではないのベストプラクティスであると私は、catch
ブロックの適切な使用についてご講義はありません。)この点以下のデータの
たくさん!
ラン1の結果:
Exception: 7196141955 (7.196s)
NumberFormatException: 7736401837 (7.736s)
Throwable: 6818656505 (6.819s)
ラン2件の結果:
Exception: 7262897545 (7.263s)
NumberFormatException: 7056116050 (7.056s)
Throwable: 7108232206 (7.108s)
実験3件の結果:
Exception: 7088967045 (7.089s)
NumberFormatException: 7020495455 (7.020s)
Throwable: 7192925684 (7.193s)
の
実験4件の結果:
Exception: 6916917328 (6.917s)
NumberFormatException: 7690084994 (7.690s)
Throwable: 6906011513 (6.906s)
ラン5件の結果:
Exception: 7247571874 (7.248s)
NumberFormatException: 6818511040 (6.819s)
Throwable: 6813286603 (6.813s)
コード
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Test {
private static final int TRIALS = 10000000;
private static final int NANOS_IN_SECOND = 1000000000;
private static final int DECIMAL_PRECISION = 3;
private static final RoundingMode ROUNDING_MODE = RoundingMode.HALF_UP;
public static void main(String[] args) {
long firstStart = System.nanoTime();
for(int i = 0; i < TRIALS; i++) {
try {
throw new NumberFormatException();
}
catch(Exception e) {
}
}
long firstEnd = System.nanoTime();
long secondStart = System.nanoTime();
for(int i = 0; i < TRIALS; i++) {
try {
throw new NumberFormatException();
}
catch(NumberFormatException e) {
}
}
long secondEnd = System.nanoTime();
long thirdStart = System.nanoTime();
for(int i = 0; i < TRIALS; i++) {
try {
throw new NumberFormatException();
}
catch(Throwable e) {
}
}
long thirdEnd = System.nanoTime();
long exception = firstEnd - firstStart;
long numberFormatException = secondEnd - secondStart;
long throwable = thirdEnd - thirdStart;
BigDecimal exceptionSeconds = new BigDecimal((double)exception/(double)NANOS_IN_SECOND);
BigDecimal numberFormatExceptionSeconds = new BigDecimal((double)numberFormatException/(double)NANOS_IN_SECOND);
BigDecimal throwableSeconds = new BigDecimal((double)throwable/(double)NANOS_IN_SECOND);
exceptionSeconds = exceptionSeconds.setScale(DECIMAL_PRECISION, ROUNDING_MODE);
numberFormatExceptionSeconds = numberFormatExceptionSeconds.setScale(DECIMAL_PRECISION, ROUNDING_MODE);
throwableSeconds = throwableSeconds.setScale(DECIMAL_PRECISION, ROUNDING_MODE);
System.out.println("Exception: " + exception + " (" + exceptionSeconds + "s)");
System.out.println("NumberFormatException: " + numberFormatException + " (" + numberFormatExceptionSeconds + "s)");
System.out.println("Throwable: " + throwable + " (" + throwableSeconds + "s)");
}
}
より回旋、擬似ランダムコード
コードブロックが常にcatch
に流れることを認識して、オプティマイザがスロー/キャッチプロセス全体を単に「無視する」のではないことを確認するために、これを作成しました。無作為に選択されたString
(しかし常に無効なもの)上でInteger.parseInt()
を試行することによって、コンパイラは実行時までfor()
ループを介した実行が有効かどうかを知ることができません。
第1の実験から予想されるように、3つのシナリオの間には大きな違いはありません。
ラン1の結果:
Exception: 10988431371 (10.988s)
NumberFormatException: 11360698958 (11.361s)
Throwable: 10539041505 (10.539s)
ラン2件の結果:
Exception: 12468860076 (12.469s)
NumberFormatException: 11852429194 (11.852s)
Throwable: 11859547560 (11.860s)
実験3件の結果:
Exception: 10618082779 (10.618s)
NumberFormatException: 10718252324 (10.718s)
Throwable: 10327709072 (10.328s)
実験4の結果:
Exception: 11031135405 (11.031s)
NumberFormatException: 10689877480 (10.690s)
Throwable: 10668345685 (10.668s)
ラン5つの結果:この場合
Exception: 11513727192 (11.514s)
NumberFormatException: 11581826079 (11.582s)
Throwable: 12488301109 (12.488s)
コード
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Random;
public class Test {
private static final int TRIALS = 10000000;
private static final int NANOS_IN_SECOND = 1000000000;
private static final int DECIMAL_PRECISION = 3;
private static final RoundingMode ROUNDING_MODE = RoundingMode.HALF_UP;
private static final String[] TEST_STRINGS = {
"lawl",
"rofl",
"trololo",
"foo",
"bar"
};
private static final Random RANDOM = new Random();
public static void main(String[] args) {
long firstStart = System.nanoTime();
for(int i = 0; i < TRIALS; i++) {
try {
Integer.parseInt(TEST_STRINGS[RANDOM.nextInt(TEST_STRINGS.length)]);
}
catch(Exception e) {
}
}
long firstEnd = System.nanoTime();
long secondStart = System.nanoTime();
for(int i = 0; i < TRIALS; i++) {
try {
Integer.parseInt(TEST_STRINGS[RANDOM.nextInt(TEST_STRINGS.length)]);
}
catch(NumberFormatException e) {
}
}
long secondEnd = System.nanoTime();
long thirdStart = System.nanoTime();
for(int i = 0; i < TRIALS; i++) {
try {
Integer.parseInt(TEST_STRINGS[RANDOM.nextInt(TEST_STRINGS.length)]);
}
catch(Throwable e) {
}
}
long thirdEnd = System.nanoTime();
long exception = firstEnd - firstStart;
long numberFormatException = secondEnd - secondStart;
long throwable = thirdEnd - thirdStart;
BigDecimal exceptionSeconds = new BigDecimal((double)exception/(double)NANOS_IN_SECOND);
BigDecimal numberFormatExceptionSeconds = new BigDecimal((double)numberFormatException/(double)NANOS_IN_SECOND);
BigDecimal throwableSeconds = new BigDecimal((double)throwable/(double)NANOS_IN_SECOND);
exceptionSeconds = exceptionSeconds.setScale(DECIMAL_PRECISION, ROUNDING_MODE);
numberFormatExceptionSeconds = numberFormatExceptionSeconds.setScale(DECIMAL_PRECISION, ROUNDING_MODE);
throwableSeconds = throwableSeconds.setScale(DECIMAL_PRECISION, ROUNDING_MODE);
System.out.println("Exception: " + exception + " (" + exceptionSeconds + "s)");
System.out.println("NumberFormatException: " + numberFormatException + " (" + numberFormatExceptionSeconds + "s)");
System.out.println("Throwable: " + throwable + " (" + throwableSeconds + "s)");
}
}
「Throwable」をキャッチする場合を除いて、パフォーマンスが同じであることは、プログラムが「Throwable」の型をチェックする必要があるより具体的なものです。しかし、これは単なる推測です。 – asteri
あなた自身でベンチマークを行い、ここに結果を投稿してみませんか? – anubhava
@anubhava何かをベンチマークしようとするたびに、私はベンチマークが適切ではないと言われます。母: – asteri