【问题标题】:Use string matching or boolean flags for performance optimization [closed]使用字符串匹配或布尔标志进行性能优化 [关闭]
【发布时间】:2014-02-26 17:32:16
【问题描述】:

我有一个函数可以检查几个参数的有效性并返回一个带有错误消息的字符串。在调用函数中,我正在做的是使用errorString.equals("") 方法检查返回的字符串是否为空。如果它不为空,则会显示错误消息。我听说字符串比较在 Java 中代价高昂。我可以使用的另一种方法是错误检查函数返回一个布尔值而不是字符串,并使errorString 成为全局字符串,调用函数检查返回的布尔值并在需要时显示errorString。进行此更改后,我可以期待多少性能改进?假设我的函数每分钟会被调用 1000 次。

编辑:- 例如:-

    public void callingFunction(){
    /*
    some operations....
     */
    String errors=checkErrors(param1,param1,param3,param4,param5);
    if(!"".equals(errors)){
        System.out.println(errors);
    }
}
public String checkErrors(String param1,String pram2,String param3,String pram4,String param5){
    String errors="";
    if(param1 == null)
        errors +="param1 is null";
    if(param1.equals(""))
        errors +="param1 is empty";
    /*
    A lot more validity checks...
     */
    return errors;
}

【问题讨论】:

  • 对于现代 CPU,"1000/minute" 非常慢。无论如何,优化时要查看的第一个位置是performance profile。由于所讨论的所有方法都具有相同的性能界限,因此“性能”只是无关紧要 (TM) - 如果有一些奇怪的机会,它确实很重要,您将能够通过性能概况(见上文)。
  • “程序优化的第一条规则:不要这样做。程序优化的第二条规则(仅供专家使用!):不要这样做。” — 迈克尔 A. 杰克逊
  • 我在每个肩膀上平衡了两条滑溜溜的鱼。
  • 对此我很抱歉,我将使用 Java :-)

标签: java performance optimization string-comparison


【解决方案1】:

根据我的评论,没有性能问题,除非有 benchmark/performance profile 表明存在问题。实际上,在大多数应用程序级代码中,除非性能界限发生变化,否则大多数代码“足够快”——干净利落地编写代码,并遵循 97/31 规则.

在调用函数中,我正在做的是使用 errorString.equals("") 方法检查返回的字符串是否为空。如果它不为空,则会显示错误消息。听说 JAVA 中字符串比较的开销很大。

嗯,不。 String.equals 通常不是不必要的“昂贵”,在这种特殊情况下绝对不是。 String.equals 对于两个相同长度的任意字符串是 O(n),但对于不同长度的字符串是 O(1)。

String.equals 所做的第一件事(嗯,第二件事,在检查 null 之后)是比较两个字符串的长度,并将长度存储在一个简单的整数变量中。如果长度不相等,则可以立即确定字符串不相等:长度为 0 的唯一字符串是空字符串。

也就是说,除了一些额外的指令(JIT 无论如何都可能内联方法调用)之外,它将具有与检查布尔变量相同的性能特征。

另外,不要忘记现代 CPU 非常快。我的“旧”CPU 以 22 十亿 Hz 的频率运行; 1000 次操作/分钟仅为 16 Hz。


1 97/3 规则 (courtesy of D. Knuth):

程序员浪费大量时间思考或担心他们程序中非关键部分的速度。我们应该忘记小的效率,比如说大约 97% 的时间 .. 然而我们不应该放弃我们在关键的 3% 中的机会。一个优秀的程序员会 [..] 明智地仔细查看关键代码;但只有在识别出该代码之后 ..

【讨论】:

  • 你真幸运,我得到的只是一个旧的 286。
  • @user2310289 然后我建议不要使用 Java :(
  • 所以在我的情况下,字符串长度相等的唯一情况是两者都是空字符串,复杂度为 O(0),在所有其他情况下复杂度为 O(1 )。那么是否需要进行任何修改来提高性能?我提到的 1000 次调用是任意的,它可能会增加。
  • @ManuViswam O(1),因为没有 O(0) - 与检查离散/标志布尔变量。我怀疑你会看到切换到单独的字段有什么明显的改进(尽管相反的基准会证明我错了!),所以只需将代码编写为简单/干净,因为它允许。单独的变量/标志可能更清晰,如果适用,请选择它以实现 清晰 和 正确性 - 而不是“性能”。
  • O(0) 只是一个错误。我所理解的是,我所有的检查都将具有 O(1) 的复杂性,因为我正在与一个空字符串进行比较。因此,如果我使用单独的布尔变量,它不会有太大的不同。
【解决方案2】:

我建议你这样做是完全错误的。

  • 如果只有一个条件要检查,则返回boolean。否则:
  • 如果您不需要提供除故障本身以外的任何信息,则返回一个标志字,其各个位指示各种可能的错误(如果已设置)
  • 否则你应该抛出各种异常。

【讨论】:

  • 有几个条件需要检查。每个条件都会添加不同的错误消息,并且这些消息的任意组合都是可能的。抛出不同的异常也是不可能的,因为我必须在单个消息中显示所有错误。
  • @ManuVisam 你的推理似是而非。您当然仍然可以在一条消息中显示所有错误,并且仍然会引发不同的异常。您所要做的就是在调用者处累积它们。或者只是以已经准备好显示的形式构造返回字符串并消除整个问题,但这不是一个非常现实的解决方案。或者问题。
  • 我对异常的了解是(如果我错了,请纠正我)一次只处理一个异常。即使我用 | 在同一个 catch 块中捕获不同的异常操作员,一次只有一个活动,对吗?请提供一些链接,以便我了解同时处理多个异常。
猜你喜欢
  • 1970-01-01
  • 2010-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-02
  • 1970-01-01
相关资源
最近更新 更多