我正在尝试测量客户端代码的性能。这意味着end to end client side code
占用了多少时间,客户端代码中的其他类很少。所以我做了基准测试。
下面是我目前正在使用的简单程序。但是有一个问题。
public class PerformanceTest {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
try {
for (int i = 0; i < 10 * 5; i++) {
executor.submit(new ThreadTask(i));
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) {
}
}
}
下面是实现Runnable interface
的类
class ThreadTask implements Runnable {
private int id;
public static ConcurrentHashMap<Long, AtomicLong> millisecondsMap = new ConcurrentHashMap<Long, AtomicLong>();
public ThreadTask(int id) {
this.id = id;
}
@Override
public void run() {
long start = System.nanoTime();
attributes = beClient.getAttributes(columnsList);
long end = System.nanoTime() - start;
final AtomicLong before = millisecondsMap.putIfAbsent(end / 1000000L, new AtomicLong(1L));
if (before != null) {
before.incrementAndGet(); //this is a blocking call in IBM JVM
}
}
}
问题陈述:-
我在我的机器上运行IBM JVM
。因为我在一家公司工作,他们使用IBM JVM
而不是SUN JVM
,所以我不能改变JVM部分。
所以在IBM JVM中incrementAndGet()
方法的样子,首先对我来说很奇怪
/**
* Atomically increments by one the current value.
*
* @return the updated value
*/
public final synchronized long incrementAndGet() { //IBM-perf_AtomicLong
++value; //IBM-perf_AtomicLong
return value; //IBM-perf_AtomicLong
}
所以这是一个阻塞调用,因为它是synchronized
,这意味着每个线程将彼此等待。现在我正在寻找Lock free solution
来衡量每种方法的性能。
我知道,这里会有微小的延迟。但是,无论我想在客户端代码中测量什么方法的性能,我通常都将下面一行放在方法
的上方。 long start = System.nanoTime();
方法相同但ConcurrentHashMap
long end = System.nanoTime() - start;
final AtomicLong before = millisecondsMap.putIfAbsent(end / 1000000L, new AtomicLong(1L));
if (before != null) {
before.incrementAndGet();// this is a blocking call in IBM JVM
}
所以如果我在客户端代码的不同类中围绕5-8 different methods
有相同的上面代码。然后端到端性能测量将是错误的,因为每个线程将在那里等待增加值。因此,这就是我正在寻找无锁解决方案的原因。
有什么简单的方法吗?有人能举个例子吗?
提前感谢。
更新代码:
public static ConcurrentHashMap<Long, Long> millisecondsMap = new ConcurrentHashMap<Long, Long>();
@Override
public void run() {
long start = System.nanoTime();
beAttributes = client.getAttributes(columnsList);
long end = System.nanoTime() - start;
long key = end / 1000000L;
boolean done = false;
while(!done) {
long oldValue = millisecondsMap.get(key);
done = millisecondsMap.replace(key, oldValue, oldValue + 1);
}
}
这个代码也是线程安全代码吗?因为它将被多个线程访问。
与其使用AtomicLong,不如使用ConcurrentHashMap的replace(key, old value, new value)
方法来增加该值
ConcurrentHashMap<Long, Long> millisecondsMap = new ConcurrentHashMap<>();
long key = end / 1000000L;
boolean done = false;
while(!done) {
Long oldValue = millisecondsMap.putIfAbsent(key, 1L);
if(oldValue != null) {
done = millisecondsMap.replace(key, oldValue, oldValue + 1);
} else {
done = true;
}
}