我正在对客户端代码中的几个方法进行基准测试,以了解这些方法花费了多少时间。所以我编写了一个多线程程序,它将生成多个线程,然后我将测量这些方法在客户端代码和服务器端代码中花费的时间。
我将ConcurrentHashMap
声明为
public static ConcurrentHashMap<Long, Long> map = new ConcurrentHashMap<Long, Long>();
现在我试图找出,在X毫秒内回拨了多少电话,所以我将这些数字存储在上面的地图中。所以上面的地图会存储这样的东西 -
KEY will be Milliseconds
and VALUE will be Number of calls came back in those milliseconds.
下面是代码,我有。
final long start = System.nanoTime();
method.getInformation();
final long end = System.nanoTime() - start;
final long key = end / 1000000L;
boolean done = false;
while(!done) {
Long oldValue = map.putIfAbsent(key, 1L);
if(oldValue != null) {
done = map.replace(key, oldValue, oldValue + 1);
} else {
done = true;
}
}
我正在尝试查看上述代码是否有任何问题?
为什么我要问的是,如果我正在运行Multithreading program
,那么server CPU usage
通常会转到80-90%
左右。但是,如果我从服务器端代码中删除上述基准测试代码,则CPU usage
不会转到80-90%
。所以这就是原因,我试图看看是否有更好的方法来编写上述基准测试代码,可以实现相同的上述场景?
感谢您的帮助。
更新: -
我使用unix中的TOP命令监视服务器端的CPU和MEMORY使用情况 -
top - 17:13:18 up 25 days, 23:24, 4 users, load average: 1.72, 1.43, 1.04
Tasks: 114 total, 1 running, 111 sleeping, 0 stopped, 2 zombie
Cpu0 : 79.2%us, 5.8%sy, 0.0%ni, 23.1%id, 0.0%wa, 0.0%hi, 1.9%si, 0.0%st
Cpu1 : 83.7%us, 3.7%sy, 0.0%ni, 40.7%id, 0.0%wa, 0.0%hi, 1.9%si, 0.0%st
Mem: 6127684k total, 5122736k used, 1004948k free, 240436k buffers
Swap: 1331196k total, 0k used, 1331196k free, 2485984k cached
下面是正在运行的快照,我刚捕获了
答案 0 :(得分:0)
所以我用你的时间检查代码进行了快速测试,并且能够在我的四核2013 Macbook Pro上以8.8秒的速度运行1 百万。这意味着每个通话费用不到8ns(因为我的时间是挂钟并且考虑了线程的东西)。这是相当便宜的IMO。我将0到1000000的随机值保持在100个线程中,最终得到的堆大小为631k,这似乎占用了不到20-30mb的核心。
在我看来,您的通话时间代码不是一个很大的性能问题。我想知道每个线程是否都触及大量内存,而你的代码所做的唯一事情就是遇到内存障碍。可能有趣的是用volatile
字段的单个更新替换代码或强制屏障,看看你是否得到相同的行为。
我没有立即发现您的代码存在任何问题,我也不会认为这会是一个很大的性能问题。
我确实想知道地图有多大。似乎是如果你在地图中使用大量条目长时间运行它,内存需求将会很大。您可以尝试使用-Xmx
参数来增加内存。
如果是内存,那么CPU问题可能与GC有关。我使用Jconsole查看你是否内存不足。
答案 1 :(得分:0)
这里有一些潜在的性能问题。
您的基准测试代码为每个请求添加了两次System.nanoTime()
调用。根据请求中涉及的真实工作量,这些调用可能很重要。
虽然您尝试使用ConcurrentHashMap
来减少并发性瓶颈,但这并不能完全消除它。实际上,如果您有大量请求需要相同的毫秒数,那么该特定计数器就会出现瓶颈。如果特定计数器存在争用,那么当不同的线程竞争更新它时,这将导致“旋转”。
如果(假设)地图变得非常大,您可以开始获取与内存使用相关的问题;例如更大的工作集,更高的缓存和TLB争用,颠簸。
但最重要的是,您添加的任何性能测量代码都可能会改变系统的性能特征。
答案 2 :(得分:0)
性能/资源使用问题:
我的建议
记录列表中的已用时间
static List<long> methodElapsedMillisList = new ArrayList<long>();
final int methodCountBlock = 1000;
static long methodCountStartMillis = System.currentTimeMillis();
static int methodCount = 0;
static Object methodCountMonitorObj = new Object();
// within instrumented method:
synchronised (methodCountMonitorObj) {
methodCount++;
if (methodCount > methodCountBlock ) {
long newMethodCountStartMillis = System.currentTimeMillis();
long elapsedMillis = newMethodCountStartMillis - methodCountStartMillis;
methodCountStartMillis = newMethodCounterStartMillis;
methodElapsedMillisList.add(elapsedMillis);
methodCount = 0;
}
}