我正在寻找一种方法来列出正在运行的并行Java应用程序的所有同步调用,以便检测可伸缩性问题(就线程/核心而言).据我所知,每次进入同步块时,机器都需要同步缓存.这会影响所有正在运行的CPU(以多种方式,如内存带宽),即使进入同步区域未阻止正在运行的任务也是如此.
那个设定:
我有一个在更高级别上并行化的大型应用程序,即它具有并行执行的复杂任务.并行化在该术语中起作用,即所有核心都处于负载状态,并且我没有阻塞线程.性能仍然没有扩展到核心,这可能有几个原因.我感兴趣的特殊可能原因是,如果有很多同步调用(例如,输入同步块,使用锁等).
任务
我想知道我的代码中哪些地方(实际执行的)有这样的同步调用以及实际执行每个同步的频率.有许多引用的库,因此不可能在synchronized关键字或类似的东西上使用常规代码搜索,因为这将搜索许多从未执行过的代码并带来许多误报.完美的解决方案是拥有一个分析器,它列出了所有已执行的同步位置和调用次数.但是,我尝试过的分析器只允许对方法调用进行计数.因此,这里的问题是找到实际相关的所有方法.
或者,如果我能找到某个入口点(主方法)引用的同步位置,它也会有所帮助.即通过递归遍历代码并检查所有引用的方法,类等以进行此类同步.在这种情况下,稍后可以通过使用常规分析器找出频率.
问题
是否有工具或工作流程能够将上述任务归档为更大的项目.
THX提前为您的答案.
解决方法:
进入和离开同步块是相当便宜的操作,除非在该块上存在争用.在非竞争情况下,如果UseBiasedLocking优化成功,则synchronized只是一个原子CAS或几乎是无操作.虽然看起来可以使用Instrumentation API来执行同步分析器,但这没有多大意义.
多线程应用程序的问题是争用同步. JVM有一些内部计数器来监视锁争用(see this question).或者您甚至可以使用JVMTI events编写一个简单的临时工具来跟踪所有竞争锁.
但是,不仅锁定会导致争用.甚至非阻塞算法也可能遭受对共享资源的竞争. Here is a good example这种可扩展性问题.所以,我同意@PeterLawrey的说法,最好从CPU分析器开始,因为它通常更容易找到性能问题.