1

我目前正在开发一个 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;
}
4

1 回答 1

1

在简单的操作中,每个数据库的行为都与您描述的一样。

原因是您生成的所有线程都试图在同一张表(或一组表)上进行操作,因此数据库必须对访问进行序列化。

在这种情况下,每个线程的工作速度都会慢一些,但总体结果是(小)增益。(21K+20K=41K 对 35K 的单线程版本)。

增益随着线程数的增加而减少(通常呈指数级),最终您可能会因为锁升级而遭受损失(请参阅https://dba.stackexchange.com/questions/12864/what-is-lock-escalation)。

通常,多线程解决方案在其性能不受单一资源约束,而是受多种因素(即计算、多表选择、不同表插入)的约束时,收益最大。

于 2013-02-20T09:49:02.843 回答