So I have code that currently looks like this
public boolean in(TransactionType... types)
{
if (types == null || types.length == 0)
return false;
for (int i = 0; i < types.length; ++i)
if (types[i] != null && types[i] == this)
return true;
return false;
}
I changed it to this
public boolean in(TransactionType... types)
{
if (types == null || types.length == 0)
return false;
for (int i = 0; i < types.length; ++i)
if (types[i] == this)
return true;
return false;
}
(TransactionType
is an enum with roughly 30 values in it)
The results shocked me. In all of my tests, the second was an order of magnitude faster. I expected maybe 2x faster, but not an order of magnitude. Why the difference? Is it the nullcheck that is that much slower or is something strange happening with the extra array access?
My benchmark code looks like this
public class App
{
public enum TransactionType
{
A(1, "A", "A"),
B(3, "B", "B"),
C(5, "C", "C"),
D(6, "D", "D"),
E(7, "E", "E"),
F(8, "F", "F"),
G(9, "G", "G"),
H(10, "H", "H"),
I(11, "I", "I"),
J(12, "J", "J"),
K(13, "K", "K"),
L(14, "L", "L"),
M(15, "M", "M"),
N(16, "N", "N"),
O(17, "O", "O"),
P(18, "P", "P"),
Q(19, "Q", "Q"),
R(20, "R", "R"),
S(21, "S", "S"),
T(22, "T", "T"),
U(25, "U", "U"),
V(26, "V", "V"),
W(27, "W", "W"),
X(28, "X", "X"),
Y(29, "Y", "Y"),
Z(30, "Z", "Z"),
AA(31, "AA", "AA"),
AB(32, "AB", "AB"),
AC(33, "AC", "AC"),
AD(35, "AD", "AD"),
AE(36, "AE", "AE"),
AF(37, "AF", "AF"),
AG(38, "AG", "AG"),
AH(39, "AH", "AH"),
AI(40, "AI", "AI"),
AJ(41, "AJ", "AJ"),
AK(42, "AK", "AK"),
AL(43, "AL", "AL"),
AM(44, "AM", "AM"),
AN(45, "AN", "AN"),
AO(46, "AO", "AO"),
AP(47, "AP", "AP");
public final static TransactionType[] aArray =
{
O, Z, N, Y, AB
};
public final static TransactionType[] bArray =
{
J, P, AA, L, Q, M, K, AE, AK,
AF, AD, AG, AH
};
public final static TransactionType[] cArray =
{
S, U, V
};
public final static TransactionType[] dArray =
{
A, B, D, G, C, E,
T, R, I, F, H, AC,
AI, AJ, AL, AM, AN,
AO
};
private int id;
private String abbrev;
private String name;
private TransactionType(int id, String abbrev, String name)
{
this.id = id;
this.abbrev = abbrev;
this.name = name;
}
public boolean in(TransactionType... types)
{
if (types == null || types.length == 0)
return false;
for (int i = 0; i < types.length; ++i)
if (types[i] == this)
return true;
return false;
}
public boolean inOld(TransactionType... types)
{
if (types == null || types.length == 0)
return false;
for (int i = 0; i < types.length; ++i)
{
if (types[i] != null && types[i] == this)
return true;
}
return false;
}
}
public static void main(String[] args)
{
for (int i = 0; i < 10; ++i)
bench2();
for (int i = 0; i < 10; ++i)
bench1();
}
private static void bench1()
{
final TransactionType[] values = TransactionType.values();
long runs = 0;
long currTime = System.currentTimeMillis();
while (System.currentTimeMillis() - currTime < 1000)
{
for (TransactionType value : values)
{
value.inOld(TransactionType.dArray);
}
++runs;
}
System.out.println("old " + runs);
}
private static void bench2()
{
final TransactionType[] values = TransactionType.values();
long runs = 0;
long currTime = System.currentTimeMillis();
while (System.currentTimeMillis() - currTime < 1000)
{
for (TransactionType value : values)
{
value.in(TransactionType.dArray);
}
++runs;
}
System.out.println("new " + runs);
}
}
Here are the results of the benchmark running
new 20164901
new 20084651
new 45739657
new 45735251
new 45757756
new 45726575
new 45413016
new 45649661
new 45325360
new 45380665
old 2021652
old 2022286
old 2246888
old 2237484
old 2246172
old 2268073
old 2271554
old 2259544
old 2272642
old 2268579
This is using Oracle JDK 1.7.0.67