1

我正在尝试衡量客户端代码的性能。意味着需要多少时间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 JVMSUN JVM所以我无法更改 JVM 部分。

所以在 IBM JVMincrementAndGet()方法看起来,首先对我来说很奇怪

/**
 * 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);
    }

}

此代码是否也是线程安全代码?因为它也将被多个线程访问。

4

1 回答 1

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;
    }
}
于 2013-04-14T03:23:26.183 回答