我正在用Java测试RocksDB的多线程写入性能。
我使用了1、2、4和8个线程来编写测试并修改值的长度(100B,1K,2K,10K),但是在所有测试案例中我都遇到了2个线程写性能下降的问题。 1和4线程写入比2线程快。我想知道为什么。
有我的测试代码:
<dependency>
<groupId>org.rocksdb</groupId>
<artifactId>rocksdbjni</artifactId>
<version>5.15.10</version>
</dependency>
package com.rdbtest;
import org.rocksdb.*;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
//muti test
public class Test6 extends Thread{
public static final String STR="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
public static byte[] getRandomString(Random random, int length){
StringBuffer sb =new StringBuffer(length + 5);
for(int i=0;i<length;i++){
int number= random.nextInt(62);
sb.append(STR.charAt(number));
}
return sb.toString().getBytes();
}
private RocksDB db;
private int maxTreadNum;
private static AtomicInteger writeComplete = new AtomicInteger(0);
private long length,max;
private long writeTimeUsed,readTimeUsed;
byte[][] arrs;
public long getWriteTimeUsed(){
return writeTimeUsed;
}
public long getReadTimeUsed(){
return readTimeUsed;
}
Test6(RocksDB db, int maxTreadNum, int length, long max, byte[][] arrs) {
this.db = db;
this.maxTreadNum = maxTreadNum;
this.length = length;
this.max = max;
this.arrs = arrs;
}
@Override
public void run() {
Random rand = new Random(System.currentTimeMillis());
// int max = 1000*10000;
byte[][] rowkeylist = new byte[(int)this.max][];
for(int i = 0 ; i< this.max;i++) {
rowkeylist[i] = String.format("111aaa%010d",rand.nextInt(100000000)).getBytes();
}
try{
long start = System.currentTimeMillis();
long end = 0;
long timeUsed = 0;
//write qps
for(int i = 0 ; i < max;i++){
db.put(rowkeylist[i], arrs[rand.nextInt(10000)]);
}
end = System.currentTimeMillis();
timeUsed = end - start;
writeTimeUsed = timeUsed;
float qps = max*1.0f/timeUsed*1000;
System.out.println("[write]useTime " + timeUsed + " ms, qps: "+qps);
writeComplete.incrementAndGet();
while(writeComplete.get() != maxTreadNum) {
Thread.sleep(10);
}
//read qps
start = System.currentTimeMillis();
for(int i = 0 ; i < max;i++){
byte[] ret = db.get(rowkeylist[i]);
}
end = System.currentTimeMillis();
timeUsed = end - start;
readTimeUsed = timeUsed;
qps = max*1.0f/timeUsed*1000;
System.out.println("[read]useTime " + timeUsed + " ms, qps: "+qps);
}catch (Exception e) {
System.out.println("error!!!");
e.printStackTrace();
}finally {
}
}
public static void main(String[] args) {
System.out.println("======================================");
RocksDB.loadLibrary();
RocksDB db = null;
String path = args[0];
int threadNum = Integer.parseInt(args[1]);
int length = 1000;
if(args.length >=3 ){
length = Integer.parseInt(args[2]);
}
long max = 1000*10000;
if(args.length >=4 ){
max = Long.parseLong(args[3]);
}
byte[][] arrs = new byte[10000][];
Random random=new Random(System.currentTimeMillis());
for(int i = 0; i< 10000; i++) {
arrs[i] = getRandomString(random,length);
}
System.out.println("Tread Num is :" + threadNum + " length:" + length + " max:" + max);
try{
Options options = new Options()
.setCreateIfMissing(true);
options.setMaxBackgroundFlushes(4);
options.setMaxBackgroundCompactions(4);
db = RocksDB.open(options, path);
Test6[] threads = new Test6[threadNum];
for(int i = 0; i<threadNum;i ++) {
threads[i] = new Test6(db, threadNum, length, max/threadNum, arrs);
Thread.sleep(2);
threads[i].start();
}
long maxWriteTime = 0;
long maxReadTime = 0;
for(int i = 0; i<threadNum;i ++) {
threads[i].join();
maxReadTime = Math.max(maxReadTime, threads[i].getReadTimeUsed());
maxWriteTime = Math.max(maxWriteTime, threads[i].getWriteTimeUsed());
}
System.out.println("final result:");
System.out.println(" write qps:"+(max*1.0/maxWriteTime*1000));
System.out.println(" read qps:"+(max*1.0/maxReadTime*1000));
System.out.println("exe complete");
}catch (Exception e){
System.out.println(e);
}finally {
db.close();
}
}
}