A
Albretch
I wanted to measurably test how much the stack un/rewinding done by function calls taxes processing speed.
... and the winner is ..., well, as we all knew already, using a C-like structure with all members public is consistently fater. It was actually approx. three times as fast as the Java Bean like class with setters and getters methods
My conclusion is, as long as you -internally- use C Structs-like value objects and they don't get exposed by the API itself, you should go for them.
Would you differ? What is it I am missing here?
// - - - - - START OF CODE
// __ Object's state set at creationg time
class JK00{
private int iI;
private int[] iIAr;
private String aS;
private String[] aSAr;
// __
JK00(int iI, int[] iIAr, String aS, String[] aSAr){
this.iI = iI;
this.iIAr = iIAr;
this.aS = aS;
this.aSAr = aSAr;
}
// __
public int getI(){ return(iI); }
public int[] getIAr(){ return(iIAr); }
public String getS(){ return(aS); }
public String[] getSAr(){ return(aSAr); }
}
// - - - - -
// __ Object state resettable for each single member (Java Bean way)
class JK02{
private int iI;
private int[] iIAr;
private String aS;
private String[] aSAr;
// __
JK02(){}
// __
public void setI(int iI){ this.iI = iI; }
public int getI(){ return(iI); }
// __
public void setIAr(int[] iIAr){ this.iIAr = iIAr; }
public int[] getIAr(){ return(iIAr); }
// __
public void setS(String aS){ this.aS = aS; }
public String getS(){ return(aS); }
// __
public void setSAr(String[] aSAr){ this.aSAr = aSAr; }
public String[] getSAr(){ return(aSAr); }
// __
}
// - - - - -
// __ Object state with a bulk set method and single getters
class JK04{
private int iI;
private int[] iIAr;
private String aS;
private String[] aSAr;
// __
JK04(){}
// __
public void setCtxt(int iI, int[] iIAr, String aS, String[] aSAr){
this.iI = iI;
this.iIAr = iIAr;
this.aS = aS;
this.aSAr = aSAr;
}
// __
public int getI(){ return(iI); }
public int[] getIAr(){ return(iIAr); }
public String getS(){ return(aS); }
public String[] getSAr(){ return(aSAr); }
// __
}
// - - - - -
// __ ANSI C struct-like object
class JK06{
public int iI;
public int[] iIAr;
public String aS;
public String[] aSAr;
// __
JK06(){}
}
// - - - - -
import java.io.*;
import java.util.*;
import java.lang.Math.*;
// __
public class TestStructBean06{
static final boolean IsOutFl = false;
// static final boolean IsOutFl = true;
// __
static void setOutputFile(String azOutFlName){
try{
File Fl = new File(azOutFlName);
FileOutputStream OutFlStrm = new FileOutputStream(Fl);
PrintStream PrntStrm = new PrintStream(OutFlStrm);
System.setOut(PrntStrm);
} catch(IOException IOXcptn){ IOXcptn.printStackTrace(); }
}// setOutputFile(String)
// __
public static void main(String[] azArgs){
String azOFlNm ="PrntOut.txt";
if(IsOutFl)setOutputFile(azOFlNm);
long lTm00, lTtlTm;
int iNewObjs, iTms = 4*4096, iTmsTest=16;
JK00 K00;
JK02 K02;
JK04 K04;
JK06 K06;
// __
int iI;
int[] iIAr;
String aS;
String[] aSAr;
// __
String[][] aA2DAr = new String[][]{
{"The","quick","brown","fox","jumped","over","the","lazy","dog"},
{"quick","brown","fox","jumped","over","the","lazy","dog"},
{"brown","fox","jumped","over","the","lazy","dog"},
{"fox","jumped","over","the","lazy","dog"},
{"jumped","over","the","lazy","dog"},
{"over","the","lazy","dog"},
{"the","lazy","dog"},
{"lazy","dog"},
{"dog"}
};
// __
int[][] i2DAr = new int[aA2DAr.length][];
for(int j = 0; (j < aA2DAr.length); ++j){
i2DAr[j] = new int[(j + 1)];
//System.out.println("|" + j + "|" + i2DAr[j].length + "|");
for(int k = 0; (k < i2DAr[j].length); ++k){
//System.out.println("|" + j + "|" + k + "|" + i2DAr[j].length + "|");
i2DAr[j][k] = k;
}// k
}// j
// __
iNewObjs = iTms*(aA2DAr.length*(aA2DAr.length - 1)/2);
// __
long[][] lTests = new long[4][iTmsTest];
for(int iTest = 0; (iTest < iTmsTest); ++iTest){
System.out.println(" iTest: [" + iTest + "," + iTmsTest + ")");
// __ JK00 Objects
lTm00 = System.currentTimeMillis();
for(int i = 0; (i < iTms); ++i){
for(int j = 0; (j < aA2DAr.length); ++j){
for(int k = 0; (k < aA2DAr[j].length); ++k){
K00 = new JK00(k, i2DAr[k], aA2DAr[j][0], aA2DAr[j]);
// __
iI = K00.getI();
iIAr = K00.getIAr();
aS = K00.getS();
aSAr = K00.getSAr();
// __
}// k
}// j
}// i
lTtlTm = (System.currentTimeMillis() - lTm00);
System.out.println(lTtlTm + " milliseconds needed to create " + iNewObjs + " JK00 Objects.");
lTests[0][iTest] = lTtlTm;
// __ JK02 Objects
lTm00 = System.currentTimeMillis();
K02 = new JK02();
for(int i = 0; (i < iTms); ++i){
for(int j = 0; (j < aA2DAr.length); ++j){
for(int k = 0; (k < aA2DAr[j].length); ++k){
// __
K02.setI(k);
K02.setIAr(i2DAr[k]);
K02.setS(aA2DAr[j][0]);
K02.setSAr(aA2DAr[j]);
// __
iI = K02.getI();
iIAr = K02.getIAr();
aS = K02.getS();
aSAr = K02.getSAr();
// __
}// k
}// j
}// i
lTtlTm = (System.currentTimeMillis() - lTm00);
System.out.println(lTtlTm + " milliseconds needed to create " + iNewObjs + " JK02 Objects.");
lTests[1][iTest] = lTtlTm;
// __ JK04 Objects
lTm00 = System.currentTimeMillis();
K04 = new JK04();
for(int i = 0; (i < iTms); ++i){
for(int j = 0; (j < aA2DAr.length); ++j){
for(int k = 0; (k < aA2DAr[j].length); ++k){
K04.setCtxt(k, i2DAr[k], aA2DAr[j][0], aA2DAr[j]);
// __
iI = K04.getI();
iIAr = K04.getIAr();
aS = K04.getS();
aSAr = K04.getSAr();
// __
}// k
}// j
}// i
lTtlTm = (System.currentTimeMillis() - lTm00);
System.out.println(lTtlTm + " milliseconds needed to create " + iNewObjs + " JK04 Objects.");
lTests[2][iTest] = lTtlTm;
// __ JK04 Objects
lTm00 = System.currentTimeMillis();
K06 = new JK06();
for(int i = 0; (i < iTms); ++i){
for(int j = 0; (j < aA2DAr.length); ++j){
for(int k = 0; (k < aA2DAr[j].length); ++k){
// __
K06.iI = k;
K06.iIAr = i2DAr[k];
K06.aS = aA2DAr[j][0];
K06.aSAr = aA2DAr[j];
// __
iI = K06.iI;
iIAr = K06.iIAr;
aS = K06.aS;
aSAr = K06.aSAr;
// __
}// k
}// j
}// i
lTtlTm = (System.currentTimeMillis() - lTm00);
System.out.println(lTtlTm + " milliseconds needed to create " + iNewObjs + " JK06 Objects.");
lTests[3][iTest] = lTtlTm;
}// [0, iTmsTest)
// __
double[][] d2DAr = getStatsAveDev(lTests);
double dMax = Double.MIN_VALUE;
for(int i = 0; (i < d2DAr.length); ++i){
if(dMax < d2DAr[0]){ dMax = d2DAr[0]; }
}
// __
System.out.println();
System.out.println(" Test run " + iTmsTest + " times.");
String[] aSArKNms = new String[]{"JK00", "JK02", "JK04", "JK08"};
System.out.println("- - - - - - - - - - - - - - - - - - - - - - - - - -");
System.out.println("|__class__|__ave. (ms)|__dev. (ms)__|_times faster_|");
for(int i = 0; (i < d2DAr.length); ++i){
//System.out.println("|\t" + aSArKNms + "\t|\t" + d2DAr[0] + "\t|\t" + d2DAr[1] + "\t|\t" + dMax/d2DAr[0] + "\t|");
System.out.printf("| %s |% 9.4f |%9.4f |%9.4f |\n", aSArKNms, d2DAr[0], d2DAr[1], dMax/d2DAr[0]);
System.out.println("- - - - - - - - - - - - - - - - - - - - - - - - - -");
}
}// main
// __
private static double[][] getStatsAveDev(long[][] lVals){
double[][] d2DAr = new double[lVals.length][2];
double dAve;
double dDev;
double dVal;
// __
int iN = lVals.length;
for(int i = 0; (i < iN); ++i){
dAve = .0;
for(int j = 0; (j < lVals.length); ++j){ dAve += lVals[j]; }
d2DAr[0] = dAve/lVals.length;
// __
dDev = .0;
for(int j = 0; (j < lVals.length); ++j){
dVal = (1.*lVals[j] - d2DAr[0]); dDev += dVal*dVal;
}
// __
dDev /= (iN - 1);
d2DAr[1] = Math.sqrt(dDev);
}// i
// __
return(d2DAr);
}
}// TestStructBean06
// - - - - - END OF CODE
Test run 2 times.
- - - - - - - - - - - - - - - - - - - - - - - - - -
|__class__|__ave. (ms)|__dev. (ms)__|_times faster_|
| JK00 | 85.5000 | 12.6557 | 1.1696 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK02 | 100.0000 | 0.0000 | 1.0000 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK04 | 85.0000 | 4.0825 | 1.1765 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK08 | 35.0000 | 4.0825 | 2.8571 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
Test run 2 times.
- - - - - - - - - - - - - - - - - - - - - - - - - -
|__class__|__ave. (ms)|__dev. (ms)__|_times faster_|
| JK00 | 85.0000 | 12.2474 | 1.1765 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK02 | 100.0000 | 0.0000 | 1.0000 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK04 | 85.5000 | 3.6742 | 1.1696 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK08 | 30.0000 | 0.0000 | 3.3333 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
Test run 16 times.
- - - - - - - - - - - - - - - - - - - - - - - - - -
|__class__|__ave. (ms)|__dev. (ms)__|_times faster_|
| JK00 | 71.3750 | 24.3019 | 1.4212 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK02 | 101.4375 | 7.5263 | 1.0000 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK04 | 80.0625 | 8.1841 | 1.2670 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK08 | 35.0625 | 11.7038 | 2.8930 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
Test run 16 times.
- - - - - - - - - - - - - - - - - - - - - - - - - -
|__class__|__ave. (ms)|__dev. (ms)__|_times faster_|
| JK00 | 71.3750 | 24.3019 | 1.4203 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK02 | 101.3750 | 7.5664 | 1.0000 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK04 | 81.3750 | 7.5664 | 1.2458 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK08 | 34.4375 | 11.6324 | 2.9437 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
... and the winner is ..., well, as we all knew already, using a C-like structure with all members public is consistently fater. It was actually approx. three times as fast as the Java Bean like class with setters and getters methods
My conclusion is, as long as you -internally- use C Structs-like value objects and they don't get exposed by the API itself, you should go for them.
Would you differ? What is it I am missing here?
// - - - - - START OF CODE
// __ Object's state set at creationg time
class JK00{
private int iI;
private int[] iIAr;
private String aS;
private String[] aSAr;
// __
JK00(int iI, int[] iIAr, String aS, String[] aSAr){
this.iI = iI;
this.iIAr = iIAr;
this.aS = aS;
this.aSAr = aSAr;
}
// __
public int getI(){ return(iI); }
public int[] getIAr(){ return(iIAr); }
public String getS(){ return(aS); }
public String[] getSAr(){ return(aSAr); }
}
// - - - - -
// __ Object state resettable for each single member (Java Bean way)
class JK02{
private int iI;
private int[] iIAr;
private String aS;
private String[] aSAr;
// __
JK02(){}
// __
public void setI(int iI){ this.iI = iI; }
public int getI(){ return(iI); }
// __
public void setIAr(int[] iIAr){ this.iIAr = iIAr; }
public int[] getIAr(){ return(iIAr); }
// __
public void setS(String aS){ this.aS = aS; }
public String getS(){ return(aS); }
// __
public void setSAr(String[] aSAr){ this.aSAr = aSAr; }
public String[] getSAr(){ return(aSAr); }
// __
}
// - - - - -
// __ Object state with a bulk set method and single getters
class JK04{
private int iI;
private int[] iIAr;
private String aS;
private String[] aSAr;
// __
JK04(){}
// __
public void setCtxt(int iI, int[] iIAr, String aS, String[] aSAr){
this.iI = iI;
this.iIAr = iIAr;
this.aS = aS;
this.aSAr = aSAr;
}
// __
public int getI(){ return(iI); }
public int[] getIAr(){ return(iIAr); }
public String getS(){ return(aS); }
public String[] getSAr(){ return(aSAr); }
// __
}
// - - - - -
// __ ANSI C struct-like object
class JK06{
public int iI;
public int[] iIAr;
public String aS;
public String[] aSAr;
// __
JK06(){}
}
// - - - - -
import java.io.*;
import java.util.*;
import java.lang.Math.*;
// __
public class TestStructBean06{
static final boolean IsOutFl = false;
// static final boolean IsOutFl = true;
// __
static void setOutputFile(String azOutFlName){
try{
File Fl = new File(azOutFlName);
FileOutputStream OutFlStrm = new FileOutputStream(Fl);
PrintStream PrntStrm = new PrintStream(OutFlStrm);
System.setOut(PrntStrm);
} catch(IOException IOXcptn){ IOXcptn.printStackTrace(); }
}// setOutputFile(String)
// __
public static void main(String[] azArgs){
String azOFlNm ="PrntOut.txt";
if(IsOutFl)setOutputFile(azOFlNm);
long lTm00, lTtlTm;
int iNewObjs, iTms = 4*4096, iTmsTest=16;
JK00 K00;
JK02 K02;
JK04 K04;
JK06 K06;
// __
int iI;
int[] iIAr;
String aS;
String[] aSAr;
// __
String[][] aA2DAr = new String[][]{
{"The","quick","brown","fox","jumped","over","the","lazy","dog"},
{"quick","brown","fox","jumped","over","the","lazy","dog"},
{"brown","fox","jumped","over","the","lazy","dog"},
{"fox","jumped","over","the","lazy","dog"},
{"jumped","over","the","lazy","dog"},
{"over","the","lazy","dog"},
{"the","lazy","dog"},
{"lazy","dog"},
{"dog"}
};
// __
int[][] i2DAr = new int[aA2DAr.length][];
for(int j = 0; (j < aA2DAr.length); ++j){
i2DAr[j] = new int[(j + 1)];
//System.out.println("|" + j + "|" + i2DAr[j].length + "|");
for(int k = 0; (k < i2DAr[j].length); ++k){
//System.out.println("|" + j + "|" + k + "|" + i2DAr[j].length + "|");
i2DAr[j][k] = k;
}// k
}// j
// __
iNewObjs = iTms*(aA2DAr.length*(aA2DAr.length - 1)/2);
// __
long[][] lTests = new long[4][iTmsTest];
for(int iTest = 0; (iTest < iTmsTest); ++iTest){
System.out.println(" iTest: [" + iTest + "," + iTmsTest + ")");
// __ JK00 Objects
lTm00 = System.currentTimeMillis();
for(int i = 0; (i < iTms); ++i){
for(int j = 0; (j < aA2DAr.length); ++j){
for(int k = 0; (k < aA2DAr[j].length); ++k){
K00 = new JK00(k, i2DAr[k], aA2DAr[j][0], aA2DAr[j]);
// __
iI = K00.getI();
iIAr = K00.getIAr();
aS = K00.getS();
aSAr = K00.getSAr();
// __
}// k
}// j
}// i
lTtlTm = (System.currentTimeMillis() - lTm00);
System.out.println(lTtlTm + " milliseconds needed to create " + iNewObjs + " JK00 Objects.");
lTests[0][iTest] = lTtlTm;
// __ JK02 Objects
lTm00 = System.currentTimeMillis();
K02 = new JK02();
for(int i = 0; (i < iTms); ++i){
for(int j = 0; (j < aA2DAr.length); ++j){
for(int k = 0; (k < aA2DAr[j].length); ++k){
// __
K02.setI(k);
K02.setIAr(i2DAr[k]);
K02.setS(aA2DAr[j][0]);
K02.setSAr(aA2DAr[j]);
// __
iI = K02.getI();
iIAr = K02.getIAr();
aS = K02.getS();
aSAr = K02.getSAr();
// __
}// k
}// j
}// i
lTtlTm = (System.currentTimeMillis() - lTm00);
System.out.println(lTtlTm + " milliseconds needed to create " + iNewObjs + " JK02 Objects.");
lTests[1][iTest] = lTtlTm;
// __ JK04 Objects
lTm00 = System.currentTimeMillis();
K04 = new JK04();
for(int i = 0; (i < iTms); ++i){
for(int j = 0; (j < aA2DAr.length); ++j){
for(int k = 0; (k < aA2DAr[j].length); ++k){
K04.setCtxt(k, i2DAr[k], aA2DAr[j][0], aA2DAr[j]);
// __
iI = K04.getI();
iIAr = K04.getIAr();
aS = K04.getS();
aSAr = K04.getSAr();
// __
}// k
}// j
}// i
lTtlTm = (System.currentTimeMillis() - lTm00);
System.out.println(lTtlTm + " milliseconds needed to create " + iNewObjs + " JK04 Objects.");
lTests[2][iTest] = lTtlTm;
// __ JK04 Objects
lTm00 = System.currentTimeMillis();
K06 = new JK06();
for(int i = 0; (i < iTms); ++i){
for(int j = 0; (j < aA2DAr.length); ++j){
for(int k = 0; (k < aA2DAr[j].length); ++k){
// __
K06.iI = k;
K06.iIAr = i2DAr[k];
K06.aS = aA2DAr[j][0];
K06.aSAr = aA2DAr[j];
// __
iI = K06.iI;
iIAr = K06.iIAr;
aS = K06.aS;
aSAr = K06.aSAr;
// __
}// k
}// j
}// i
lTtlTm = (System.currentTimeMillis() - lTm00);
System.out.println(lTtlTm + " milliseconds needed to create " + iNewObjs + " JK06 Objects.");
lTests[3][iTest] = lTtlTm;
}// [0, iTmsTest)
// __
double[][] d2DAr = getStatsAveDev(lTests);
double dMax = Double.MIN_VALUE;
for(int i = 0; (i < d2DAr.length); ++i){
if(dMax < d2DAr[0]){ dMax = d2DAr[0]; }
}
// __
System.out.println();
System.out.println(" Test run " + iTmsTest + " times.");
String[] aSArKNms = new String[]{"JK00", "JK02", "JK04", "JK08"};
System.out.println("- - - - - - - - - - - - - - - - - - - - - - - - - -");
System.out.println("|__class__|__ave. (ms)|__dev. (ms)__|_times faster_|");
for(int i = 0; (i < d2DAr.length); ++i){
//System.out.println("|\t" + aSArKNms + "\t|\t" + d2DAr[0] + "\t|\t" + d2DAr[1] + "\t|\t" + dMax/d2DAr[0] + "\t|");
System.out.printf("| %s |% 9.4f |%9.4f |%9.4f |\n", aSArKNms, d2DAr[0], d2DAr[1], dMax/d2DAr[0]);
System.out.println("- - - - - - - - - - - - - - - - - - - - - - - - - -");
}
}// main
// __
private static double[][] getStatsAveDev(long[][] lVals){
double[][] d2DAr = new double[lVals.length][2];
double dAve;
double dDev;
double dVal;
// __
int iN = lVals.length;
for(int i = 0; (i < iN); ++i){
dAve = .0;
for(int j = 0; (j < lVals.length); ++j){ dAve += lVals[j]; }
d2DAr[0] = dAve/lVals.length;
// __
dDev = .0;
for(int j = 0; (j < lVals.length); ++j){
dVal = (1.*lVals[j] - d2DAr[0]); dDev += dVal*dVal;
}
// __
dDev /= (iN - 1);
d2DAr[1] = Math.sqrt(dDev);
}// i
// __
return(d2DAr);
}
}// TestStructBean06
// - - - - - END OF CODE
Test run 2 times.
- - - - - - - - - - - - - - - - - - - - - - - - - -
|__class__|__ave. (ms)|__dev. (ms)__|_times faster_|
| JK00 | 85.5000 | 12.6557 | 1.1696 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK02 | 100.0000 | 0.0000 | 1.0000 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK04 | 85.0000 | 4.0825 | 1.1765 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK08 | 35.0000 | 4.0825 | 2.8571 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
Test run 2 times.
- - - - - - - - - - - - - - - - - - - - - - - - - -
|__class__|__ave. (ms)|__dev. (ms)__|_times faster_|
| JK00 | 85.0000 | 12.2474 | 1.1765 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK02 | 100.0000 | 0.0000 | 1.0000 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK04 | 85.5000 | 3.6742 | 1.1696 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK08 | 30.0000 | 0.0000 | 3.3333 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
Test run 16 times.
- - - - - - - - - - - - - - - - - - - - - - - - - -
|__class__|__ave. (ms)|__dev. (ms)__|_times faster_|
| JK00 | 71.3750 | 24.3019 | 1.4212 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK02 | 101.4375 | 7.5263 | 1.0000 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK04 | 80.0625 | 8.1841 | 1.2670 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK08 | 35.0625 | 11.7038 | 2.8930 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
Test run 16 times.
- - - - - - - - - - - - - - - - - - - - - - - - - -
|__class__|__ave. (ms)|__dev. (ms)__|_times faster_|
| JK00 | 71.3750 | 24.3019 | 1.4203 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK02 | 101.3750 | 7.5664 | 1.0000 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK04 | 81.3750 | 7.5664 | 1.2458 |
- - - - - - - - - - - - - - - - - - - - - - - - - -
| JK08 | 34.4375 | 11.6324 | 2.9437 |
- - - - - - - - - - - - - - - - - - - - - - - - - -