首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java分析、性能调优和内存分析练习

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

Stack Overflow用户
提问于 2010-08-04 14:01:31
回答 3查看 4K关注 0票数 15

我将使用JProfiler日食Tptp对java应用程序进行工作坊分析、性能调优、内存分析、内存泄漏检测等我需要一套可以提供给参与者的练习:使用工具来分析发现的问题:瓶颈、内存泄漏、不优化的代码等等。我确信我们有丰富的经验和现实生活中的例子。

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

问题和解决办法不应过于复杂;最多只能在几分钟内解决这些问题,最坏的情况则是几个小时的问题。一些令人感兴趣的活动领域:

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

理想情况下,练习应该包括示例未优化代码和解决方案代码。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-08-12 07:58:47

我试图找到我在野外所见过的真实生活中的例子(也许略有改变,但基本问题都是非常真实的)。我还尝试将它们聚集在相同的场景中,这样您就可以轻松地构建一个会话。

场景:您有一个耗时的函数,您想要对不同的值执行多次,但是相同的值可能会再次弹出(理想情况下,在创建它之后不会太久)。一个很好的简单的例子是您需要下载和处理的url页面对(对于这个练习,它可能应该是模拟的)。

循环:

  • 您需要检查页面中是否有一组单词弹出。在循环中使用函数,但使用相同的值,伪代码: (word :word){checkWord(下载(Url))} 一个解决方案非常容易,只需在循环之前下载页面即可。其他解决方案如下。

内存泄漏:

  • 简单一点:你也可以用一种缓存来解决你的问题。在最简单的情况下,您只需将结果放到(静态)映射中即可。但是,如果你不阻止它,它的大小将无限增长->内存泄漏。 可能的解决方案:使用LRU映射。大多数情况下,性能不会下降太多,但是内存泄漏应该消失。
  • 更棘手的一个:假设您使用一个WeakHashMap实现上一个缓存,其中键是URL (而不是字符串,请稍后参阅),值是包含URL、下载页面和其他内容的类的实例。您可能会假设它应该很好,但实际上并非如此:因为值(不是弱引用的)有对键( URL)的引用,所以该键永远不会有资格清除->漂亮的内存泄漏。 解决方案:从值中删除URL。
  • 和以前一样,但是urls是内部字符串(“如果我们碰巧又有相同的字符串,可以节省一些内存”),所以value不引用这个字符串。我没有尝试,但在我看来,这也会导致泄漏,因为被拘留的字符串不能被GC-编辑。 解决方案:不要实习,这也会导致你不能跳过的建议:不要做过早的优化,因为它是万恶之源。

对象创建和字符串:

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

并发性:

  • 您希望通过并行下载/过滤来加快整个过程。创建一些线程并使用它们运行代码,但是在一个大的同步块(基于缓存)中做所有事情,只是“保护缓存不受并发问题的影响”。效果应该是您只使用一个线程,因为所有其他线程都在等待获取缓存上的锁。 解决方案:仅围绕缓存操作同步(例如使用`java.util.collections.synchronizedMap())
  • 同步所有微小的代码片段。这会降低性能,可能会阻止正常的并行执行。如果你够幸运/够聪明的话,你也可以想出一把死锁。这一点的寓意是:同步不应该是一件临时的事情,在“它不会伤害”的基础上,而是一件深思熟虑的事情。

奖金练习:

在开始时填充缓存,之后不要做太多的分配,但是在某个地方仍然有一个小漏洞。通常这种模式不太容易捕捉。您可以使用分析器的“书签”或“水印”特性,它应该在缓存完成后立即创建。

票数 6
EN

Stack Overflow用户

发布于 2010-08-04 14:38:19

不要忽视这种方法,因为它适用于任何语言和操作系统,适用于这些原因这里就是一个例子。此外,尝试使用具有I/O和重要调用深度的示例。不要只使用像Mandelbrot这样的小型cpu绑定程序。如果您以这个不太大的C示例为例,并使用Java对其进行重新编码,那么这将说明您的大部分观点。

让我们看看:

  • 解决内存泄漏。 垃圾收集器的全部目的是堵塞内存泄漏。但是,您仍然可以分配太多的内存,这在某些对象的“新”中显示为很大一部分时间。
  • 优化循环。 通常情况下,循环不需要被优化,除非在它们里面做的事情很少(而且它们需要很好的时间)。
  • 优化对象创建和管理。 这里的基本方法是:使数据结构尽可能简单。特别是不要使用通知式的尝试来保持数据的一致性,因为这些东西会使调用树变得非常混乱。这是造成大型软件性能问题的一个主要原因。
  • 优化字符串操作。 使用string构建器,但不要使用不使用可靠执行时间百分比的代码。
  • 并发性。 并发有两个目的。 1)性能,但这只在允许多个硬件同时运行的范围内起作用。如果硬件不在那里,那就没有用了。很疼。 2)表达式的清晰性,例如UI代码不必担心同时进行繁重的计算或网络I/O。

在任何情况下,它都不能得到足够的强调,在证明某件事情需要大量时间之前,不要做任何优化。

票数 1
EN

Stack Overflow用户

发布于 2010-08-10 07:04:50

我使用JProfiler来分析我们的application.But --没有多少help.Then,我使用了JHat.Using JHat --您无法看到真正的time.You中的堆必须进行堆转储,然后进行分析。使用对象查询语言是查找堆泄漏的好方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3406286

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档