奇怪的分支性能

2024-01-14

The results https://microbenchmarks.appspot.com/runs/864b7017-da27-400b-a8e3-26fdd561a39d of my 基准 https://dl.dropboxusercontent.com/u/4971686/published/maaartin/so/BranchingBenchmark.java显示当分支的概率为 15%(或 85%)而不是 50% 时,性能最差。

有什么解释吗?

代码太长,但相关部分在这里:

private int diff(char c) {
    return TABLE[(145538857 * c) >>> 27] - c;
}

@Benchmark int timeBranching(int reps) {
    int result = 0;
    while (reps-->0) {
        for (final char c : queries) {
            if (diff(c) == 0) {
                ++result;
            }
        }
    }
    return result;
}

它计算的数量BREAKING_WHITESPACE http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/CharMatcher.html#BREAKING_WHITESPACE给定字符串中的字符。结果显示,当分支概率达到 0.20 左右时,时间突然下降(性能提高)。

More details https://microbenchmarks.appspot.com/runs/1a8ef79f-bab5-4e4e-824c-52e403636f04#r:scenario.benchmarkSpec.parameters.seed,scenario.benchmarkSpec.parameters.fractionMatching关于掉落。改变种子 https://microbenchmarks.appspot.com/runs/1a8ef79f-bab5-4e4e-824c-52e403636f04#r:scenario.benchmarkSpec.parameters.fractionMatching,scenario.benchmarkSpec.parameters.seed表明更多奇怪的事情正在发生。请注意,除非靠近悬崖,否则表示最小值和最大值的黑线非常短。


它看起来像是一个小的 JIT bug。对于较小的分支概率,它会生成如下所示的内容,只是由于展开而变得更加复杂(我简化了很多):

movzwl 0x16(%r8,%r10,2),%r9d

获取字符:int r9d = queries[r10]

imul   $0x8acbf29,%r9d,%ebx

乘:ebx = 145538857 * r9d

shr    $0x1b,%ebx

Shift: ebx >>>= 27

cmp    %edx,%ebx
jae    somewhere

检查边界:if (ebx > edx || ebx < 0) goto somewhere(并在那里扔一个IndexOutOfBoundsException.

cmp    %r9d,%ebx
jne    back

如果不相等则跳回循环开头:if (r9d != ebx) goto back

inc    %eax

增加结果:eax++

jne    back

Simply goto back

我们可以看到一件聪明的事情和一件愚蠢的事情:

  • 绑定检查可以通过单个最佳方式完成无符号比较 http://www.aldeid.com/wiki/X86-assembly/Instructions/jae.
  • 它完全是多余的,因为 x >>> 27 始终为正数并且小于表长度 (32)。

对于高于 20% 的分支概率,这三个指令

cmp    %r9d,%ebx
jne    back
inc    %eax

被类似的东西取代

mov    %eax,%ecx   // ecx = result
inc    %ecx        // ecx++
cmp    %r9d,%ebx   // if (r9b == index)
cmoveq %ecx,%ebx   //    result = ecx

using a 有条件的移动 http://www.jaist.ac.jp/iscenter-new/mpc/altix/altixdata/opt/intel/vtune/doc/users_guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/mergedProjects/instructions/instruct32_hh/vc35.htm操作说明。这又是一条指令,但没有分支,因此没有分支错误预测惩罚。

这解释了 20-80% 范围内非常恒定的时间。低于 20% 的下降显然是由于分支预测错误造成的。

因此,看起来 JIT 未能使用大约 0.04 而不是 0.18 的正确阈值。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

奇怪的分支性能 的相关文章

  • 将 jar 作为 Linux 服务运行 - init.d 脚本在启动应用程序时卡住

    我目前正在致力于在 Linux VM 上实现一个可运行的 jar 作为后台服务 我已经使用了找到的例子here https gist github com shirish4you 5089019作为工作的基础 并将 start 方法修改为
  • 禁用 Eclipse Java 调试器的热代码替换 [重复]

    这个问题在这里已经有答案了 可能的重复 如何在 Eclipse 中禁用热代码替换 https stackoverflow com questions 2594408 how do i disable hot code replace in
  • 使用cameltestsupport进行Camel单元测试,模板始终为空

    我正在用 Camel 做一个简单的单元测试 我想做的就是从文件 在资源下 读取 JSON 内容 将其发送到 Java 类进行验证 这是我试图测试的路线 无论我做什么 模板 我用来发送正文 json 始终为空 这是我的代码 public cl
  • Spring安全“记住我”cookie在第一个请求中不可用

    我无法在登录请求后检索 Spring 记住我 cookie 但它在对受保护页面的下一个请求中工作正常 谁能告诉我怎样才能立即得到它 我在登录请求中设置了记住我的 cookie 但在 Spring 重定向回原始 受保护的 url 后无法检索它
  • TypeScript 编译速度极慢 > 12 秒

    只是把它放在那里看看其他人是否也遇到这个问题 我已经使用 webpack 作为我的构建工具 使用 typescript 构建了一个 Angular 2 应用程序 一切都运行良好 但是我注意到 typescript 编译超级超级慢 我现在只有
  • 在 HTTP 标头中发送 UTF-8 值会导致 Mojibake

    我想使用 servlet 发送阿拉伯语数据HTTPServletResponse给客户 我正在尝试这个 response setCharacterEncoding UTF 8 response setHeader Info arabicWo
  • 如何让spring为JdbcMetadataStore创建相应的schema?

    我想使用此处描述的 jdbc 元数据存储 https docs spring io spring integration docs 5 2 0 BUILD SNAPSHOT reference html jdbc html jdbc met
  • 如何将 android.net.Uri 转换为 java.net.URL? [复制]

    这个问题在这里已经有答案了 有没有办法从Uri to URL 我正在使用的库需要这个 它only接受一个URL但我需要在我的设备上使用图像 如果该方案的Uri is http or https new URL uri toString 应该
  • 在java中实现你自己的阻塞队列

    我知道这个问题之前已经被问过并回答过很多次了 但我只是无法根据互联网上找到的示例找出窍门 例如this http tutorials jenkov com java concurrency blocking queues html or t
  • React Native:加载图像后应用程序性能不佳

    加载图像似乎没有问题 但是加载完毕后就出现问题了 在我的应用程序中 我在整个游戏中一张一张地加载卡片图像 一旦我加载了 40 张卡片图像 整个应用程序就会变得很慢 它总是发生在第 40 个图像处 当我在第 40 个图像之后继续加载更多卡片图
  • Cloudfoundry:如何组合两个运行时

    cloundfoundry 有没有办法结合两个运行时环境 我正在将 NodeJS 应用程序部署到 IBM Bluemix 现在 我还希望能够执行独立的 jar 文件 但应用程序失败 APP 0 bin sh 1 java not found
  • 如何记录来自 Akka (Java) 的所有传入消息

    在 Scala 中 您可以使用 LoggingReceive 包装接收函数 如何通过 Java API 实现相同的目标 def receive LoggingReceive case x do something Scala API 有Lo
  • Android Studio 将音乐文件读取为文本文件,如何恢复它?

    gameAlert mp3是我的声音文件 运行应用程序时 它询问我该文件不与任何文件类型关联 请定义关联 我选择TextFile错误地 现在我的音乐文件被读取为文本文件 我如何将其转换回music file protected void o
  • 为什么java中的for-each循环中需要声明变量

    for 每个循环的通常形式是这样的 for Foo bar bars bar doThings 但如果我想保留 bar 直到循环结束 我可以not使用 foreach 循环 Foo bar null Syntax error on toke
  • 如何在 Quartz 调度程序中每 25 秒运行一次?

    我正在使用 Java 的 Quartz Scheduling API 你能帮我使用 cron 表达式每 25 秒运行一次吗 这只是一个延迟 它不必总是从第 0 秒开始 例如 序列如下 0 00 0 25 0 50 1 15 1 40 2 0
  • 挂钩 Eclipse 构建过程吗?

    我希望在 Eclipse 中按下构建按钮时能够运行一个简单的 Java 程序 目前 当我单击 构建 时 它会运行一些 JRebel 日志记录代码 我有一个程序可以解析 JRebel 日志文件并将统计信息存储在数据库中 是否可以编写一个插件或
  • JSON 到 hashmap (杰克逊)

    我想将 JSON 转换为 HashMapJackson http jackson codehaus org 这是我的 JSON String json Opleidingen name Bijz trajecten zorg en welz
  • Java:多线程内的 XA 事务传播

    我如何使用事务管理器 例如Bitronix http docs codehaus org display BTM Home JBoss TS http www jboss org jbosstm or Atomikos http www a
  • 在android中跟踪FTP上传数据?

    我有一个运行 Android 的 FTP 系统 但我希望能够在上传时跟踪字节 这样我就可以在上传过程中更新进度条 安卓可以实现这个功能吗 现在 我正在使用org apache common net ftp我正在使用的代码如下 另外 我在 A
  • Android 和 Java 中绘制椭圆的区别

    在Java中由于某种原因Ellipse2D Double使用参数 height width x y 当我创建一个RectF在Android中参数是 left top right bottom 所以我对适应差异有点困惑 如果在 Java 中创

随机推荐