Java性能分析,性能调优和内存分析练习

Dan*_*Dan 15 java optimization performance profiling memory-leaks

我即将使用JProfilerEclipse Tptp进行java应用程序的研讨会分析,性能调优,内存分析,内存泄漏检测等. 我需要一些练习,我可以提供给参与者,他们可以:使用工具来分析发现问题:瓶颈,内存泄漏,次优代码等.我相信有丰富的经验和现实生活中的例子.

  • 解决问题并实现优化代码
  • 通过执行另一个分析会话来演示解决方案
  • 理想情况下,编写演示性能增益的单元测试

问题和解决方案不应过于复杂; 应该可以在几分钟内解决它们,最坏的情况是几小时.一些有趣的锻炼领域:

  • 解决内存泄漏问题
  • 优化循环
  • 优化对象创建和管理
  • 优化字符串操作
  • 解决因并发性和并发性瓶颈而加剧的问题

理想情况下,练习应包括样本未优化代码和解决方案代码.

San*_*ozi 6

我试图找到我在野外看到的现实生活中的例子(可能略有改变,但基本问题都非常真实).我也试图将它们聚集在同一场景中,这样你就可以轻松地建立一个会话.

场景:您有一个耗时的功能,您希望对不同的值执行多次,但可能会再次弹出相同的值(理想情况下,创建后不会太长).一个好的和简单的例子是您需要下载和处理的url-web页面对(对于练习它应该可能被模拟).

循环:

  • 您想要检查页面中是否弹出任何一组单词.在循环中使用您的函数,但具有相同的值,伪代码:

    for (word : words) {
        checkWord(download(url))
    }
    
    Run Code Online (Sandbox Code Playgroud)

    一个解决方案非常简单,只需在循环之前下载页面即可.其他解决方案如下.

内存泄漏:

  • 简单的一个:你也可以用一种缓存来解决你的问题.在最简单的情况下,您可以将结果放到(静态)映射中.但如果你不阻止它,它的大小将无限增长 - >内存泄漏.
    可能的解决方案:使用LRU映射.最有可能性能不会降低太多,但内存泄漏应该消失.
  • 棘手的一个:假设您使用a实现以前的缓存WeakHashMap,其中键是URL(不是字符串,请参见后面),值是包含URL的类的实例,下载的页面和其他内容.您可能认为它应该没问题,但实际上它不是:因为值(不是弱引用)具有对键(URL)的引用,键永远不会有资格清理 - >内存泄漏.
    解决方案:从值中删除URL.
  • 与之前相同,但是url是实习字符串("如果我们碰巧再次使用相同的字符串,则节省一些内存"),值不会引用它.我没有尝试过,但在我看来它也会导致泄漏,因为实习的字符串无法进行GC编辑.
    解决方案:不要实习,这也会导致你不能跳过的建议:不要过早优化,因为它是所有邪恶的根源.

对象创建和字符串:

  • 说你只想显示页面的文本(〜删除html标签).编写一个逐行执行的函数,并将其追加到不断增长的结果中.首先结果应该是一个字符串,所以追加将花费大量的时间和对象分配.您可以从性能的角度(为什么追加速度太快)和从对象创建的角度(为什么我们创建了如此多的字符串,StringBuffers,数组等)来检测此问题.
    解决方案:使用StringBuilder获取结果.

并发:

  • 您希望通过并行下载/过滤来加速整个过程.创建一些线程并使用它们运行代码,但是在一个大的同步块(基于缓存)中执行所有操作,只是"保护缓存免受并发问题".效果应该是你有效地只使用一个线程,因为所有其他线程都在等待获取缓存上的锁.
    解决方案:仅围绕缓存操作进行同步(例如,使用`java.util.collections.synchronizedMap())

  • 同步所有微小的代码片段.这应该会破坏性能,可能会阻止正常的并行执行.如果你足够幸运/聪明,你也可以拿出死锁.这样做的道德:同步不应该是一个临时的事情,在"它不会伤害"的基础上,而是一个深思熟虑的事情.

奖金锻炼:

在开始时填写你的缓存,之后不要做太多的分配,但在某处仍然有一个小的泄漏.通常这种模式不容易捕捉.您可以使用分析器的"书签"或"水印"功能,该功能应在缓存完成后立即创建.