我正在尝试衡量客户端代码的性能。意味着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);
}
}
此代码是否也是线程安全的代码?因为它也会被多个线程访问。
答案 0 :(得分:1)
使用ConcurrentHashMap的replace(key, old value, new value)
方法增加值,而不是使用AtomicLong。
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;
}
}