
我开了 100 个线程用同一个 id 分别去请求这两个方法,把这 100 次方法执行时间的平均值取出来,并且相同的方法重复做了三次得到结果: a: 24907.9ms, b: 24831.1ms ,看结果方法 b 好一点,但这个差距是不是很小啊?
@Controller @RequestMapping("/bench/") public class BenchController { private static Object[] lockObj; rivate static AtomicReference<Integer>[] locks; static { lockObj = new Object[100]; for (int i = 0; i < lockObj.length; i++) { lockObj[i] = new Object(); } locks = new AtomicReference[100]; for (int i = 0; i < locks.length; i++) { locks[i] = new AtomicReference<Integer>(null); } } @RequestMapping("a") @ResponseBody public long a(int id) throws Exception { long start = System.currentTimeMillis(); int index = id % 100; synchronized (lockObj[index]) { Thread.sleep(500); } long result=System.currentTimeMillis() - start; System.out.println(result); return result; } @RequestMapping("b") @ResponseBody public long b(int id) throws Exception { long start = System.currentTimeMillis(); int index = id % 100; while (!locks[index].compareAndSet(null, id)) { } Thread.sleep(500); locks[index].compareAndSet(id, null); long result=System.currentTimeMillis() - start; System.out.println(result); return result; } } 1 sorra 2017-04-22 14:44:43 +08:00 sleep 是有误差的,你的测试可能是无效的。可以在方法内循环大量次数来测试,也许能有效果 |
2 sagaxu 2017-04-22 14:59:09 +08:00 sleep 一下要 500ms , lock 一下是不到 1ms 的, sleep 本身的误差已经远大于 lock 的开销。结论,这测试就是胡乱测的。 JVM 的 jit 预热,这里更加看不到了。 |
4 Ouyangan 2017-04-22 15:22:57 +08:00 二楼的说法靠谱 记得 JDK1.6 的 JIT C2 策略阈值是 10000 , 楼主可以先在静态代码块中先跑个 10000 次 ,触发 JIT 后再做比较 . 推荐补补 JVM 类执行机制的知识 |
5 hyperdak 2017-04-22 15:31:45 +08:00 micro benchmark 会被 gc 、 jit 、不正确的代码影响,你得到结果本身就是错的。 正确的 java benchmark 要用 JMH 这种套件来做,它包含了预热和防止代码被 DCE 。在正确使用 JMH 的时候,你就可以得到一个正确的 benchmark 结果了 |
6 0915240 2017-04-22 17:02:52 +08:00 既然是要获取基准测试并且感知到小差距,建议换到用 jmh 试试看。 |