代码之家  ›  专栏  ›  技术社区  ›  Paulo Guedes

在Java中提高性能时应该注意什么?

  •  13
  • Paulo Guedes  · 技术社区  · 16 年前

    所以我想知道 在尝试改进系统性能时,我应该寻找哪些简单的方法?

    • 我已经查找了所有出现的代码,如 String a = new String("") 改成 StringBuilder a = new StringBuilder();
    • 我已经更改了对数据库的所有访问权限(如果适用),以使用 PreparedStatement
    • 所有的 Debug 日志记录已删除,并且 Finest 在可能的情况下,将其移除

    如你所见, 这些更改很容易进行,因为它们不需要测量系统性能

    26 回复  |  直到 15 年前
        1
  •  12
  •   Jack Leow    16 年前

    这是一个值得称赞的目标,但你需要专注于实际可证明的绩效问题——而不是你“认为”的绩效问题所在。

    即使你有一张“在不测量系统性能的情况下需要改变的事情”的清单,你真的相信它们适合你的情况吗?

    在您的情况下,我建议您花时间构建测试线束/性能仪表,这样您就可以看到哪里能让您的成本得到最大的回报。

    编辑: 为了解决“我知道使用事先准备好的声明会更快”的反对票和情绪,在面对这个问题时,一个更好的问题是“我应该如何最有效地利用空闲时间让事情变得更好?”OP显然想改善这种情况——这很好……但没有衡量“哪里受伤”,他实际上是在黑暗中开枪。准备好的报表快吗?当然——但如果真正的性能小精灵在其他地方,为什么要花时间“修复”DB代码,因为你可以通过追踪实际的痛点来产生真正的影响?

    还有一件事:在OP所描述的稳定系统中,由于引入的风险,在没有良好的量化理由的情况下进行代码更改通常被认为是不好的做法。在这种稳定的系统中,任何代码更改都必须考虑风险/回报问题。风险是巨大的:许多“简单的,不能破坏任何东西”的更改已经打滑了发布时间表/引入了重大问题。奖励?不确定,因为您实际上不知道您的更改是否导致性能提高。因此,我们进行概要分析,以确保我们正在改进重要的代码。

        2
  •  56
  •   DarkSquid    16 年前

    这两个插件都包括Eclipse插件。

        3
  •  8
  •   Carl Manaster    16 年前

    不要因为事情“看起来”可行就盲目地改变。

     logger.debug("Initializing object state " + object.initialize() );
    

    如果您只是盲目地删除该语句,对象将无法初始化。

    当然,这种说法一开始是错误的,但是,相信我,它们是存在的!!!!如果这样的事情发生在你身上会让你的生活很痛苦。

    更好的方法是使用探查器,找出哪些对象/方法/调用占用更多的时间/内存等,并尝试找出瓶颈。

    如果您有>7k类很可能您只是在修复一堆根本没有使用的代码。

        4
  •  5
  •   Peter    16 年前

    通常,仅仅查看代码库并试图通过查找某些东西来提高性能,并不保证您将获得可测量的性能增益。

        5
  •  4
  •   Carl Manaster    16 年前

    如果存在性能问题,那么@DarkSquid和@AlbertoPL的建议是正确的。但是,如果不是这样的话,也许你最好把时间花在为将来的修改准备代码上。比如分析测试覆盖率,特别是单元测试覆盖率,比如评估圈复杂度,或者只是查看报告错误最多的类(或者最大的类,或者其他一些简单的度量)。这样的主动分析可以使维护更容易。

        6
  •  4
  •   Community CDub    8 年前

    不要只是环顾代码,改变事情。

    I use this simple method.

    对于7000多个类,我敢打赌您的系统设计过度,并且存在太多抽象层的性能问题。

    发生的情况是,简单的函数和方法调用看起来是无辜的,事件处理代码被认为是“前沿”,但如果您运行它并等待它变慢,然后“暂停”几次,您会看到如下情况:

    • 修改数据库
    • 由于初始化数据结构
    • 在创建/销毁窗口的过程中
    • 在树浏览器中更改连接的过程中
    • 由于重新排列列表中的元素
    • 由于剪切/粘贴操作
    • 因为有人设置了一个属性
    • 废话,废话,废话。。。

        7
  •  4
  •   Spooky Muscothym    10 年前

    我觉得你在寻找性能反模式。这很好,但除非你把它们放在你的应用程序的上下文中,否则这一切都只是 .

    如果您真的关心性能和用户的感受,无论他们是直接用户、运营团队还是黄金捐赠者,这就是您在提高性能时应该关注的:

    调用树

    Invocation tree

    内存监视器

    Memory monitor

    调用图

    Call graph

    Google "Java profiler"

        8
  •  3
  •   Mercer Traieste    16 年前

    • 查找复杂代码区域
    • 参见代码覆盖率
    • 请参阅未记录的代码

    http://sonar.codehaus.org/

        9
  •  3
  •   John Doe    16 年前

    您可以使用静态分析工具,如FindBugs。javac编译器已经在尝试优化一些东西。诸如字符串连接之类的事情已经由编译器优化并转换为stringbuilder。

        10
  •  3
  •   Jim Ferrans    15 年前

    在性能方面,首先要确保您遇到了真正的问题,如果您遇到了问题,那么就使用像TPTP或JMeter这样的探查器[edit:HPJMeter曾经是一个通用的Java性能工具,但现在它是HP/UX特有的]。直觉是一个很差的向导。

    确保描述一个真实的测试场景。然后将注意力集中在统计数据顶部显示的方法上。起泡,冲洗,然后重复。还要提前决定何时停止:当性能令人满意时,您不想浪费时间在使代码更加模糊的微优化上。

    一定要阅读 Java Performance Tuning 战略和想法。

    请注意,随着应用程序升温,它将运行得更快(例如,它不再需要进行类加载、一次性初始化和JIT编译)。

    我曾经花了几个月的时间将基于Java的VoiceXML浏览器的性能提高了三倍,以降低使用它的站点的硬件成本。我一次又一次地对热点的位置感到惊讶。因此,正如@DarkSquid所建议的,不要猜测,测量。

        11
  •  2
  •   Hans Malherbe    16 年前

    1. 不要这样做。
    2. 测量两次。
    3. 你不应该到这里来。
    4. 不要微优化。寻找像你使用的容器一样的算法复杂性。
        12
  •  1
  •   AlbertoPL    16 年前

    一般来说:

    1. 递归调用通常在性能上也有很大的影响。确保正确处理递归,并确保任何递归位都是正确的。

        13
  •  1
  •   Eric    16 年前

    有一个自动工具可以帮助您找到 where your code behaves like CRAP

    此外,如果确实存在瓶颈,一个好的java分析器可以帮助您找到瓶颈。

        14
  •  1
  •   Randolpho    16 年前

    首先,仅尝试在您知道的性能大亨所在的位置提供性能增强。这实际上只能使用探查器来确定。有几个不错的 tools 这在这方面可能有所帮助。

    其次,仅仅用StringBuilder替换字符串并不能提高性能。事实上,在许多情况下,这可能导致经济放缓。只有在将大字符串作为循环的一部分构建时,才应该使用StringBuilder,即使这样,也只能作为更大的运行循环的一部分。在所有其他情况下,简单连接通常更快。

        15
  •  1
  •   Mykola Golubyev    16 年前

    我会改变

    字符串a=“”;

    找到重新创建对象的所有位置,并找出是否有任何方法可以返回相同的值。

    阅读有效的Java第二版专用章节。

        16
  •  1
  •   James M.    16 年前

    Java编译器也非常擅长嗅探性能改进,可能比任何一个人都要好。因此,虽然有一些明显的地方可以改进,但也有可能使编译器更难进行优化。分析和识别瓶颈要好得多 之后 汇编并重点关注这些问题。然后,解决方案可能是算法,而不是简单地更改类名。因此,总而言之,寻找一个好的剖析器。:)

        17
  •  1
  •   Bogdan    16 年前

    正如一些人之前所说,您可以使用FindBugs来消除最明显的与性能相关的“bug”。您可以快速识别许多麻烦的代码片段。

    您可以查看FindBugs网站上的列表 http://findbugs.sourceforge.net/bugDescriptions.html .

        18
  •  1
  •   Thorbjørn Ravn Andersen    16 年前

    我同意其他人的观点,即只优化显示速度较慢的代码(通过探查器,使用Java6U10和更高版本的jvisualvm非常容易入门)。

    • 适用于所有类的好javadoc。这有助于未来的维护人员更快地理解代码。在此过程中允许进行简单的重构。
    • javadoc页面的官方位置(因此开发人员可以将代码链接到这些页面,从而可以像Eclipse中的Shift-F2那样轻松导航)
    • 库函数的测试。本质上,这也是文档,因为它清楚地演示了如何使用该库以及可以预期哪些案例。
    • 找出一种自动运行/测试/强调应用程序的方法。(鼠标点击GUI,调用web服务器上的大量请求等)。

    这些项目中的任何一项都将改进代码库,而不会实际不必要地更改代码。

        19
  •  1
  •   user128807    16 年前

    所有最好的性能改进都是算法改进。

        20
  •  1
  •   mP.    16 年前

        21
  •  1
  •   omerkudat    16 年前

    也许一个好的起点是尝试查看应用程序在哪里可能破坏或违反任何SLA。如果没有任何关于性能的具体抱怨,请尝试提高性能要求,并查看代码的哪些部分会导致问题。

    如果您有时间敏感的功能,请尝试在更大的系统负载或更严格的限制下进行测试。如果需要较大的空间,请增大数据大小或限制堆空间。如果在这些场景中遇到问题,请修复这些热点。

    虽然这可能不会对您的日常性能产生影响,但它将确保您的系统在系统负载或输入达到峰值时保持可用。

        22
  •  0
  •   Paul Sonier    16 年前

    我要说的是寻找系统性能缓慢的领域。我天生就有点怀疑单纯为了提高性能而提高性能的尝试。我想说,您最好在代码中寻找合适的位置来 重构 (听起来你们中的一些人已经这样做了;不过,我并不想故作迂腐;重构是一件非常好的事情,但它不是,也不应该与性能改进混淆;重构可以 提供介绍的机会 性能改进,但它们是不同的)。

    “过早优化是问题的根源 -唐纳德·克努斯

        23
  •  0
  •   Tom Hawtin - tackline    16 年前

    虽然通常只花时间优化实际存在问题的代码是一个好主意,但有一些事情是可以做的。

    典型的例子是在C.中考虑循环。

    for (int ct=0; ct<strlen(str); ++ct) { ... }

    在这里 strlen 实际上是扫描 char 数组查找 NUL 斯特伦 外面 const int len = strlen(str); . 您可以在Java中做同样的事情(我也这么做),但它对性能的影响微不足道。根据口味编码。

    • 编写好代码。说真的,乱七八糟的代码往往会隐藏性能问题。如果您首先进行优化,那么您将无法很容易地看到有用的优化。
    • 注意选择数据结构(这实际上不是有用的建议,但需要说明)。
    • 使用 ArrayList 而不是 LinkedList . 你可以在这里和其他地方找到细节,但是 即使你认为它会很快,它也会很慢。
    • 考虑应用程序性能的哪一部分是关键的。例如,响应鼠标移动可能总是很好的,但打开对话框可能会有明显的延迟(在共享服务器上不太重要)。
    • 请记住,CPU比缓存快,比主存快,比本地网络/磁盘快,比internet快,比web服务快。
    • 考虑悲伤的情况和快乐的情况。
        24
  •  0
  •   Uri    16 年前

    如果您的代码使用了几个关键的数据结构,尤其是映射/集/涉及大量查找的任何内容,那么您可能需要确保以最佳方式使用它们。

    例如,如果您使用的是基于散列的集合,那么您的散列函数在生成统一分布方面有多好?这通常不是一个问题,但在少数情况下,由于哈希表实际上可能是一个链表,因此它可以很好地保存。

    同样的问题也扩展到了基于比较的集合(例如TreeSet),看看是否可以优化比较函数可能是有意义的。例如,你能先做比较便宜的吗?(假设只对函数使用比较)。

        25
  •  0
  •   brianegge    15 年前

    我会先看看更新/更快的硬件是否能解决您的问题。尽管人们可能希望优化代码,但将软件移动到更快的服务器通常更经济。我喜欢使用DaCapo bennchmarking工具来比较Java在硬件上的性能。我还保存了一份关于 hardware which I've tested .

        26
  •  0
  •   Peter Lawrey    15 年前

    你可以看看FindBugs之类的工具,但它们不会修复你的代码。我建议你试试IntelliJ社区版,它是免费的。这将发现可能的性能问题,并为您提供快速修复。

    但是,最好的方法是使用性能分析器。描述一个真实的程序示例,这通常会指向可以提高性能的简单操作。i、 e.只有在分析器中找到的最重要的东西值得优化,其余的运行不够,不值得更改。