cglib関連性能テストの比較
背景:
前の記事に続くcglibソース学習交流
多くの学生は、中国語のドキュメントが不足しているため、文章の紹介をよく理解していないが、具体的な使用を理解したいだけだと主張している.そこで勢いに乗ってこのブログを書きましたが、主にcglibのいくつかのツール類とよく使われるReflect、BeanUtilsを比較し、ついでにcglibの関連用法を紹介します.一挙両得、皆さんのご支持をお願いします.
本題:
1.まずPojo Beanを定義し、その後のテストは主にこれをめぐって行われる.
説明:このcopyBeanにはjavaのすべてのプロトタイプオブジェクト、基本オブジェクト、および一般的なBigDecimal、BigIntegerの合計17のプロパティが含まれています.
2.テストテンプレートの定義(テンプレートモード)
TestCallbackインタフェースを定義します.
テストのテンプレートメソッドの定義
private static final DecimalFormat integerFormat = new DecimalFormat("#,###");
説明:
より精確にテストするために、一度のサイクルで処理を行うため、jvmメモリ、GC、Classマウントがテストに与える影響を避けるために、warmupのプロセスがあり、まず少量のテスト方法を実行し、ここでは10回の を実行する. jvmメモリGCがテストidに与える影響を回避し、ここでrestoreJvmがjvm GC を強制的に行う
restoreJvm関連メソッド:
private static void restoreJvm() {
3.元のCopyBeanデータの準備
4.関連テストの実行
テスト環境の説明:
オペレーティングシステムLinux ccbu-156-49 2.6.18-131.el5.customxen #1 SMP Tue Sep 15 15:46:11 CST 2009 x86_64 x86_64 x86_64 GNU/Linux 仮想8 cpu、5 Gメモリ jdk 1.6.0_18 jvmパラメータ
最初のテストは主に1つのオブジェクトのすべてのプロパティをコピーします. BeanCopier (cglib) PropertyUtils (apache-common) BeanUtils (apache-common)
1. BeanCopier (cglib)
2.
PropertyUtils (apache-common)
3. BeanUtils (apache-common)
テスト結果:
テスト回数:testCount=1000*1000=100万回 BeanCopier total cost=36,626,000ns , each cost=36ns PropertyUtils total cost=18,173,767,000ns , each cost=18173ns BeanUtils total cost=31,236,079,000ns , each cost=31236ns
この結果から,BeanCopierはPropertyUtilsの504倍,PropertyUtilsはBeanUtilsの1.71倍,BeanCopierはPropertyUtilsの861.84倍と3桁近い差が見られた.
第2のテストは主に1つのオブジェクトの単一のプロパティをコピーします. BulkBean (cglib) BeanMap (cglib) FastClass/FastMethod (cglib) 未処理jdk reflect(jdk) 処理jdk reflect(jdk) 1. BulkBean
2. BeanMap
3. FastClass/FastMethod
4.未処理jdk reflect
5.処理済みjdk reflect
テスト結果:
テスト回数:testCount=1000*1000*100=1億回 BulkBean total cost=2,125,759,000ns , each cost=21ns BeanMap total cost=2,730,912,000ns , each cost=27ns FastClass total cost=2,576,470,000ns , each cost=25ns 未処理のReflect total cost=288275000 ns、each cost=28 ns で処理したReflect total cost=279280000 ns、each cost=27 ns テストの結果、性能の差は多くなく、差は大きくありません.これはjdkがreflect呼び出しの最適化を素晴らしいことを示しています.
最後に
テストデータはアーチ参照のみで、最後にテストコードに添付ファイルが表示されます.テスト方法に問題があれば、レンガを撮ってください.
前の記事に続くcglibソース学習交流
多くの学生は、中国語のドキュメントが不足しているため、文章の紹介をよく理解していないが、具体的な使用を理解したいだけだと主張している.そこで勢いに乗ってこのブログを書きましたが、主にcglibのいくつかのツール類とよく使われるReflect、BeanUtilsを比較し、ついでにcglibの関連用法を紹介します.一挙両得、皆さんのご支持をお願いします.
本題:
1.まずPojo Beanを定義し、その後のテストは主にこれをめぐって行われる.
public static class CopyBean {
private int intValue;
private boolean boolValue;
private float floatValue;
private double doubleValue;
private long longValue;
private char charValue;
private byte byteValue;
private short shortValue;
private Integer integerValue;
private Boolean boolObjValue;
private Float floatObjValue;
private Double doubleObjValue;
private Long longObjValue;
private Short shortObjValue;
private Byte byteObjValue;
private BigInteger bigIntegerValue;
private BigDecimal bigDecimalValue;
private String stringValue;
......// setter/getter
}
説明:このcopyBeanにはjavaのすべてのプロトタイプオブジェクト、基本オブジェクト、および一般的なBigDecimal、BigIntegerの合計17のプロパティが含まれています.
2.テストテンプレートの定義(テンプレートモード)
TestCallbackインタフェースを定義します.
interface TestCallback {
String getName();
CglibPerformanceTest.CopyBean call(CglibPerformanceTest.CopyBean source);
}
テストのテンプレートメソッドの定義
private static final DecimalFormat integerFormat = new DecimalFormat("#,###");
public static void testTemplate(TestCallback callback, CopyBean source, int count) {
int warmup = 10;
// , ,
for (int i = 0; i < warmup; i++) {
callback.call(source);
}
restoreJvm(); // GC
//
long start = System.nanoTime();
for (int i = 0; i < count; i++) {
callback.call(source);
}
long nscost = (System.nanoTime() - start);
System.out.println(callback.getName() + " total cost=" + integerFormat.format(nscost) + "ns , each cost="
+ nscost / count + "ns");
restoreJvm();// GC
}
説明:
restoreJvm関連メソッド:
private static void restoreJvm() {
int maxRestoreJvmLoops = 10;
long memUsedPrev = memoryUsed();
for (int i = 0; i < maxRestoreJvmLoops; i++) {
System.runFinalization();
System.gc();
long memUsedNow = memoryUsed();
// GC ,
if ((ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount() == 0)
&& (memUsedNow >= memUsedPrev)) {
break;
} else {
memUsedPrev = memUsedNow;
}
}
}
private static long memoryUsed() {
Runtime rt = Runtime.getRuntime();
return rt.totalMemory() - rt.freeMemory();
}
3.元のCopyBeanデータの準備
private static CopyBean getBean() {
CopyBean bean = new CopyBean();
bean.setIntValue(1);
bean.setBoolValue(false);
bean.setFloatValue(1.0f);
bean.setDoubleValue(1.0d);
bean.setLongValue(1l);
bean.setCharValue('a');
bean.setShortValue((short) 1);
bean.setByteValue((byte) 1);
bean.setIntegerValue(new Integer("1"));
bean.setBoolObjValue(new Boolean("false"));
bean.setFloatObjValue(new Float("1.0"));
bean.setDoubleObjValue(new Double("1.0"));
bean.setLongObjValue(new Long("1"));
bean.setShortObjValue(new Short("1"));
bean.setByteObjValue(new Byte("1"));
bean.setBigIntegerValue(new BigInteger("1"));
bean.setBigDecimalValue(new BigDecimal("1"));
bean.setStringValue("1");
return bean;
}
4.関連テストの実行
テスト環境の説明:
-server -Xmx2g -Xms2g -Xmn512m -XX:PermSize=196m -Xss256k -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70
最初のテストは主に1つのオブジェクトのすべてのプロパティをコピーします.
1. BeanCopier (cglib)
// beanCopier
final BeanCopier beanCopier = BeanCopier.create(CopyBean.class, CopyBean.class, false);
final CopyBean beanCopierTarget = new CopyBean();//new , new
testTemplate(new TestCallback() {
public String getName() {
return "BeanCopier";
}
public CopyBean call(CopyBean source) {
beanCopier.copy(source, beanCopierTarget, null);
return beanCopierTarget;
}
}, bean, testCount);
2.
PropertyUtils (apache-common)
// PropertyUtils
final CopyBean propertyUtilsTarget = new CopyBean();
testTemplate(new TestCallback() {
public String getName() {
return "PropertyUtils";
}
public CopyBean call(CopyBean source) {
try {
PropertyUtils.copyProperties(propertyUtilsTarget, source);
} catch (Exception e) {
e.printStackTrace();
}
return propertyUtilsTarget;
}
}, bean, testCount);
3. BeanUtils (apache-common)
// BeanUtils
final CopyBean beanUtilsTarget = new CopyBean();
testTemplate(new TestCallback() {
public String getName() {
return "BeanUtils";
}
public CopyBean call(CopyBean source) {
try {
BeanUtils.copyProperties(beanUtilsTarget, source);
} catch (Exception e) {
e.printStackTrace();
}
return beanUtilsTarget;
}
}, bean, testCount);
テスト結果:
テスト回数:testCount=1000*1000=100万回
この結果から,BeanCopierはPropertyUtilsの504倍,PropertyUtilsはBeanUtilsの1.71倍,BeanCopierはPropertyUtilsの861.84倍と3桁近い差が見られた.
第2のテストは主に1つのオブジェクトの単一のプロパティをコピーします.
// BulkBean
final BulkBean bulkBean = BulkBean.create(bean.getClass(), new String[] { getMethodName },
new String[] { setMethodName }, new Class[] { Integer.class });
final CopyBean bulkBeanTarget = new CopyBean();
testTemplate(new TestCallback() {
@Override
public String getName() {
return "BulkBean";
}
@Override
public CopyBean call(CopyBean source) {
Object[] result = bulkBean.getPropertyValues(source); // getter
bulkBean.setPropertyValues(bulkBeanTarget, result); // setter
return bulkBeanTarget;
}
}, bean, testCount);
2. BeanMap
// BeanMap
final BeanMap sourceMap = BeanMap.create(bean); //
final BeanMap targetMap = BeanMap.create(new CopyBean());
final CopyBean beanMapTarget = new CopyBean();
testTemplate(new TestCallback() {
@Override
public String getName() {
return "BeanMap";
}
@Override
public CopyBean call(CopyBean source) {
targetMap.setBean(beanMapTarget); // beanMap
Object obj = sourceMap.get(fieldName);
targetMap.put(fieldName, obj);
return beanMapTarget;
}
}, bean, testCount);
3. FastClass/FastMethod
// FastClass
final FastClass fastClass = FastClass.create(bean.getClass());
final FastMethod setFastMetod = fastClass.getMethod(setMethodName, new Class[] { Integer.class });
final FastMethod getFastMetod = fastClass.getMethod(getMethodName, new Class[] {});
final CopyBean fastClassTarget = new CopyBean();
testTemplate(new TestCallback() {
@Override
public String getName() {
return "FastClass";
}
@Override
public CopyBean call(CopyBean source) {
try {
Object field = getFastMetod.invoke(source, new Object[] {});// get
setFastMetod.invoke(fastClassTarget, new Object[] { field });// set
} catch (Exception e) {
e.printStackTrace();
}
return fastClassTarget;
}
}, bean, testCount);
4.未処理jdk reflect
try {
// method cache, cache method
final Method getMethod = bean.getClass().getMethod(getMethodName, new Class[] {});
final Method setMethod = bean.getClass().getMethod(setMethodName, new Class[] { Integer.class });
// Reflect
final CopyBean reflect1Target = new CopyBean();
testTemplate(new TestCallback() {
@Override
public String getName() {
return " Reflect";
}
@Override
public CopyBean call(CopyBean source) {
try {
Object field = getMethod.invoke(source, new Object[] {});
setMethod.invoke(reflect1Target, new Object[] { field });
} catch (Exception e) {
e.printStackTrace();
}
return reflect1Target;
}
}, bean, testCount);
} catch (Exception e1) {
e1.printStackTrace();
}
}
5.処理済みjdk reflect
try {
// method cache, cache method
final Method getMethod = bean.getClass().getMethod(getMethodName, new Class[] {});
final Method setMethod = bean.getClass().getMethod(setMethodName, new Class[] { Integer.class });
// Reflect
getMethod.setAccessible(true);// access
setMethod.setAccessible(true);// access
final CopyBean reflect2Target = new CopyBean();
testTemplate(new TestCallback() {
@Override
public String getName() {
return " Reflect";
}
@Override
public CopyBean call(CopyBean source) {
try {
Object field = getMethod.invoke(source, new Object[] {});
setMethod.invoke(reflect2Target, new Object[] { field });
} catch (Exception e) {
e.printStackTrace();
}
return reflect2Target;
}
}, bean, testCount);
} catch (Exception e1) {
e1.printStackTrace();
}
テスト結果:
テスト回数:testCount=1000*1000*100=1億回
最後に
テストデータはアーチ参照のみで、最後にテストコードに添付ファイルが表示されます.テスト方法に問題があれば、レンガを撮ってください.