我目前正在开发一个 java Benchmark 来评估一些使用 Apache Derby 数据库的用例(插入、更新、删除等)。
我的实现如下:
在预热 JVM 之后,我执行一个系列(for 循环:(100k 到 1M 次迭代)),比方说,ÌNSERT
在数据库的(目前单个表)中。因为它是 Apache Derby,所以对于那些知道的人,我测试了每种模式(内存/嵌入式、内存/网络、持久/嵌入式、持久/网络)
进程的执行可以是单线程的,也可以是多线程的(使用Executors.newFixedThreadPool(poolSize)
好吧,这是我的问题:
当我只用 1 个线程执行基准测试时,我得到了非常现实的结果
In memory/embedded[Simple Integer Insert] : 35K inserts/second (1 thread)
然后,我决定依次执行 1 个和 2 个(并发)线程。
现在,我有以下结果:
In memory/embedded[Simple Integer Insert] : 21K inserts/second (1 thread)
In memory/embedded[Simple Integer Insert] : 20K inserts/second (2 thread)
为什么 1 个线程的结果变化如此之大?
基本上,我在循环之前和之后开始和结束计时器:
// Processing
long start = System.nanoTime();
for (int i = 0; i < loopSize; i++) {
process();
}
// end timer
long absTime = System.nanoTime() - start;
double absTimeMilli = absTime * 1e-6;
和 process() 方法:
private void process() throws SQLException {
PreparedStatement ps = clientConn.prepareStatement(query);
ps.setObject(1, val);
ps.execute();
clientConn.commit();
ps.close();
}
由于执行是按顺序处理的,我的代码(数据处理)的其余部分不应该改变基准吗?
随着顺序线程数量的增加(例如 1、2、4、8),结果会变得更糟。
如果这令人困惑,我很抱歉。如果需要,我会提供更多信息或重新解释!
谢谢你的帮助 :)
编辑 :
这是调用上述执行的方法(来自 Usecase 类):
@Override
public ArrayList<ContextBean> bench(int loopSize, int poolSize) throws InterruptedException, ExecutionException {
Future<ContextBean> t = null;
ArrayList<ContextBean> cbl = new ArrayList<ContextBean>();
try {
ExecutorService es = Executors.newFixedThreadPool(poolSize);
for (int i = 0; i < poolSize; i++) {
BenchExecutor be = new BenchExecutor(eds, insertStatement, loopSize, poolSize, "test-varchar");
t = es.submit(be);
cbl.add(t.get());
}
es.shutdown();
es.awaitTermination(Long.MAX_VALUE,TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return cbl;
}