【问题标题】:General methods for optimizing program for speed优化程序速度的一般方法
【发布时间】:2010-11-17 09:15:17
【问题描述】:

在速度方面,有哪些通用方法可以在 Java 中优化程序。我正在使用 DOM Parser 解析 XML 文件,然后将某些单词存储在 ArrayList 中,删除任何重复项,然后通过为每个单词创建 Google 搜索 URL 来拼写检查这些单词,获取 html 文档,找到更正的单词并将其保存到另一个 ArrayList。

任何帮助将不胜感激!谢谢。

【问题讨论】:

    标签: java xml optimization performance google-search


    【解决方案1】:

    为什么需要提高性能?根据您的解释,很明显,这里的最大瓶颈(或性能损失)将是 IO,这是由于 您正在访问 URL 而导致的。

    这肯定会使您在数据结构或 XML 框架中所做的任何微小改进相形见绌

    您的大性能问题将涉及 IO,这是一个很好的一般经验法则。很幽默,我此时正在等待数据库查询以批处理方式返回。它已经运行了将近一个小时。但我欢迎任何对我的 XML 解析库的改进建议!

    这是我的一般方法:

    • 延迟 (IO) 的角度来看,您的程序是否执行任何明显昂贵 的任务?您是否有足够的日志记录来确定这是延迟所在(如果很严重)?

    • 您的程序是否容易发生锁争用(即它可以等待,什么都不做,等待某些资源“空闲”)? 也许您正在锁定整个 Map,同时您对要存储的值进行昂贵的计算,从而阻止其他线程访问映射

    • 是否有一些明显的算法(可能用于数据匹配或排序)可能具有较差的特性?

    • 运行分析器(例如 jvisualvm,JDK 本身附带)并查看您的代码热点。 JVM 把时间花在了哪里?

    【讨论】:

    • 所以这里的通用方法是:分析代码以查看花费最多的时间。您正在(可能正确)预测结果并得出(可能正确)结论:无事可做 :-) 这取决于原始 XML 文件的大小及其来源。
    • 哈哈——我确实是。基于多年的经验。我的数据库查询现已返回!
    • 是的,主要的减速是因为 HTTP 请求。由于有些单词是重复的,所以我认为使用集合首先检查单词是否已经被查询应该会提高速度。没有太多其他事情可做。我会使用 SAX Parser,但单个 XML 文件本身并没有那么大。感谢您输入 oxbow!
    【解决方案2】:

    SAX 比 DOM 快。如果您不想通过 ArrayList 搜索重复项,请将所有内容放在 LinkedHashMap 中——没有重复项,您仍然可以获得 ArrayList 为您提供的插入顺序。

    但真正的瓶颈是向 Google 发送 HTTP 请求,等待响应,然后解析响应。请改用拼写检查库。

    编辑:但请接受我有根据的猜测。使用代码分析器查看真正减慢程序的原因。

    【讨论】:

    • 文件本身并没有那么大,所以我认为使用 SAX 不会有那么大的不同。但是,是的,我需要找到减少对 Google 的 HTTP 请求数量的方法。感谢您的反馈!
    【解决方案3】:

    一般来说,最好的方法是找出瓶颈所在,然后解决它。您通常会发现您将 90% 的时间花在一小部分代码上,而这正是您想要集中精力的地方。

    一旦您弄清楚什么需要花费大量时间,就可以专注于改进您的算法。例如,如果您使用最明显的算法,从 ArrayList 中删除重复项可能是 O(n²) 复杂度,但如果您使用正确的数据结构,则可以减少到 O(n)。

    一旦您弄清楚代码的哪些部分花费的时间最多,并且您不知道如何最好地解决它,我建议您缩小您的问题范围,并在 StackOverflow 上发布另一个问题。

    编辑

    正如@oxbow_lakes 如此讽刺地说,并不是所有的性能瓶颈都可以在代码的 big-O 特征中找到。我当然无意暗示他们是。由于问题是关于优化的“一般方法”,我试图坚持一般的想法,而不是谈论这个特定的程序。但是,您可以将我的建议应用于此特定程序:

    1. 查看瓶颈在哪里。有很多方法可以分析您的代码,从高端、昂贵的分析软件到真正的 hacky。很可能,这些方法中的任何一种都表明您的程序花费了 99% 的时间来等待 Google 的响应。
    2. 专注于算法。现在你的算法是(大致):
      1. 解析 XML
      2. 创建单词列表
      3. 对于每个单词
        1. Ping Google 进行拼写检查。
      4. 返回结果

    由于您的大部分时间都花在“ping Google”阶段,解决此问题的一个明显方法是避免执行该步骤的次数过多。例如:

    1. 解析 XML
    2. 创建单词列表
    3. 将单词列表发送到拼写服务。
    4. 从拼写服务解析结果。
    5. 返回结果

    当然,在这种情况下,最大的速度提升可能是使用在同一台机器上运行的拼写检查器,但这并不总是一种选择。例如,TinyMCE 在浏览器中作为 javascript 程序运行,它不能将整个字典作为网页的一部分下载。因此,它将所有单词打包到一个不同的列表中,并执行一个 AJAX 请求来获取字典中没有的单词的列表。

    【讨论】:

    • 我建议先退后一步,看看你的程序做了什么,先看看明显的东西。并非所有的性能瓶颈都可以在代码的 big-O 特征中找到。例如这个。
    • 您可能会认为这很讽刺,但优化 Java 的一种通用方法是坐下来看看程序做了什么,根据经验法则 IO (或锁争用)可能是罪魁祸首。你的建议是专注于算法而不是 细节 是一个很好的建议
    【解决方案4】:

    这些人可能是对的,但少数random pauses 会将“*可能”变成“肯定,这就是原因”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-07
      • 2013-12-03
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      • 2016-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多