cglib相关性能测试对比
2011-05-11 10:41
525 查看
背景:
继上一篇文章 cglib源码学习交流
很多同学提出,因中文文档缺乏,导致对文章中的介绍看的不是很明白,更多的只是想了解具体的使用即可。所以趁势写了这篇博文,主要是将cglib中的几个工具类和常用的Reflect ,BeanUtils做一个对比,顺便也介绍一下cglib的相关用法,一举两得,望大家多多支持。
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个属性。
Java代码
interface
TestCallback {
String getName();
CglibPerformanceTest.CopyBean call(CglibPerformanceTest.CopyBean source);
}
定义测试的模板方法
private static final DecimalFormat integerFormat = new DecimalFormat("#,###");
Java代码
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回收
}
说明:
为了测试更加精确,避免因为在一次的循环中进行处理,jvm内存,GC,Class装载对测试的影响,有一个warmup的过程,先执行少量的测试方法,这里是执行10次
避免jvm内存GC对测试id影响,这里有restoreJvm强制进行一次jvm GC
Java代码
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();
}
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;
}
操作系统 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
虚拟8cpu , 5G内存
jdk 1.6.0_18
jvm 参数
Jvm参数代码
-server -Xmx2g -Xms2g -Xmn512m -XX:PermSize=196m -Xss256k -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=
70
第一测试主要是一个对象的全部属性
BeanCopier (cglib)
PropertyUtils (apache-common)
BeanUtils (apache-common)
1. BeanCopier (cglib)
Java代码
// 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)
Java代码
<span style=
"background-color: rgba(0, 0, 0, 0);"
>
// 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);</span>
3. BeanUtils (apache-common)
Java代码
<span style=
"background-color: rgba(0, 0, 0, 0);"
>
// 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);</span>
测试结果:
测试次数: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个数量级。
第二测试主要是一个对象的单个属性
BulkBean (cglib)
BeanMap (cglib)
FastClass/FastMethod (cglib)
未处理的jdk reflect (jdk)
处理的jdk reflect (jdk)
1. BulkBean
Java代码
// 测试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
Java代码
// 测试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
Java代码
// 测试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
Java代码
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
Java代码
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亿次
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=2,882,755,000ns , each cost=28ns
处理过的Reflect total cost=2,792,828,000ns , each cost=27ns
测试结果,性能相差不多,差距不大,这也可以说明jdk对reflect调用的优化已经做的很棒了。
继上一篇文章 cglib源码学习交流
很多同学提出,因中文文档缺乏,导致对文章中的介绍看的不是很明白,更多的只是想了解具体的使用即可。所以趁势写了这篇博文,主要是将cglib中的几个工具类和常用的Reflect ,BeanUtils做一个对比,顺便也介绍一下cglib的相关用法,一举两得,望大家多多支持。
正题:
1. 首先定义一份Pojo Bean ,后续的测试主要围绕这个进行。
Java代码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接口。Java代码
interface
TestCallback {
String getName();
CglibPerformanceTest.CopyBean call(CglibPerformanceTest.CopyBean source);
}
定义测试的模板方法
private static final DecimalFormat integerFormat = new DecimalFormat("#,###");
Java代码
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回收
}
说明:
为了测试更加精确,避免因为在一次的循环中进行处理,jvm内存,GC,Class装载对测试的影响,有一个warmup的过程,先执行少量的测试方法,这里是执行10次
避免jvm内存GC对测试id影响,这里有restoreJvm强制进行一次jvm GC
restoreJvm相关方法:
private static void restoreJvm() {Java代码
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数据
Java代码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. 执行相关测试
测试环境说明:操作系统 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
虚拟8cpu , 5G内存
jdk 1.6.0_18
jvm 参数
Jvm参数代码
-server -Xmx2g -Xms2g -Xmn512m -XX:PermSize=196m -Xss256k -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m -XX:+UseFastAccessorMethods -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=
70
第一测试主要是一个对象的全部属性
进行拷贝
BeanCopier (cglib)PropertyUtils (apache-common)
BeanUtils (apache-common)
1. BeanCopier (cglib)
Java代码
// 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)
Java代码
<span style=
"background-color: rgba(0, 0, 0, 0);"
>
// 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);</span>
3. BeanUtils (apache-common)
Java代码
<span style=
"background-color: rgba(0, 0, 0, 0);"
>
// 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);</span>
测试结果:
测试次数: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个数量级。
第二测试主要是一个对象的单个属性
进行拷贝
BulkBean (cglib)BeanMap (cglib)
FastClass/FastMethod (cglib)
未处理的jdk reflect (jdk)
处理的jdk reflect (jdk)
1. BulkBean
Java代码
// 测试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
Java代码
// 测试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
Java代码
// 测试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
Java代码
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
Java代码
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亿次
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=2,882,755,000ns , each cost=28ns
处理过的Reflect total cost=2,792,828,000ns , each cost=27ns
测试结果,性能相差不多,差距不大,这也可以说明jdk对reflect调用的优化已经做的很棒了。
最后
测试数据仅拱参考,最后测试代码可见附件。测试方法如存在问题,欢迎拍砖相关文章推荐
- SAS vs SSD对比测试MySQL tpch性能
- kvm磁盘io优化以及性能测试以及与物理机对比
- Apworks框架中各种仓储实现的性能基准测试与结果对比
- Win32 FPC/Delphi/BCC/MinGW/VC编译器性能对比测试 (Matrix Multiplication)
- [收藏学习]主流虚拟机技术性能测试与对比
- Mysql数据库Innodb与MyISAM的性能对比测试
- hbase性能测试对比分析
- 干货:性能测试相关问题及解决办法汇总
- Java中字符串操作类String、StringBuffer、StringBuilder区别及性能对比测试
- lua 和 luajit 性能对比测试
- 关于doitphp,thinkphp,yii,ci,doophp等框架的性能对比测试
- 性能测试相关指标计算法则
- nginx折腾记(HTTP性能能测试,与Apache对比)
- 性能测试相关书籍
- JMeter性能测试基础 (3) - 使用参数文件做搜索引擎性能对比
- MongoDB V3 & V2 版本锁性能对比测试及锁的基本概况
- Hive 集算器 Impala性能对比测试报告(上)
- Telechips 6410 GPU JIT 性能测试对比
- unixbench 物理机性能与虚拟机性能测试对比
- YDB与spark SQL在百亿级数据上的性能对比测试