1

最近有人告诉我,涉及较小整数的比较会更快,例如,

// Case 1
int i = 0;
int j = 1000;
if(i<j) {//do something}

// Case 2
int j = 6000000;
int i = 500000;
if(i<j){//do something else}

因此,案例 1 中的比较(if条件)应该比案例 2 中的更快。在案例 2 中,整数将占用更多空间来存储,但这会影响比较,我不确定。

编辑 1: 我在考虑 i 和 j 的二进制表示,例如,对于 i=0,它将是 0,对于 j=1000,它的 1111101000(在 32 位表示中它应该是:22 个零后跟 1111101000,完全忘记了关于 32 位或 64 位表示,我的错!)

我试图查看一个简单的比较程序的 JVM 规范和字节码,对我来说没有什么意义。现在的问题是java中数字的比较如何工作?我想这也将回答为什么(或为什么不)任何情况都会更快。

编辑2: 我只是在寻找一个详细的解释,我并不担心微优化

4

3 回答 3

3

如果您关心性能,您实际上只需要考虑将代码编译为本机代码时会发生什么。在这种情况下,重要的是 CPU 的行为。对于简单的操作,几乎所有 CPU 的工作方式都相同。

因此,案例 1 中的比较(如果条件)应该比案例 2 中的更快。在案例 2 中,整数将占用更多空间来存储,但这会影响比较,我不确定。

在 Java 中, Anint始终是 32 位的。这意味着它总是占用相同的空间。在任何情况下,数据类型的大小都不是很重要,例如short并且byte通常较慢,因为本机字大小是 32 位和/或 64 位,它必须从更大的类型中提取正确的数据并对其进行符号扩展.

我试图查看一个简单的比较程序的 JVM 规范和字节码,对我来说没有什么意义。

JLS 指定行为,而不是性能特征。

现在的问题是java中数字的比较如何工作?

它的工作方式与几乎所有其他编译语言中的工作方式相同。它使用单个机器代码指令来比较这两个值,并根据需要使用另一个执行条件分支。

我想这也将回答为什么(或为什么不)任何情况都会更快。

大多数现代 CPU 使用分支预测。为了保持 CPU 流水线充满,它会尝试预测将采用哪个分支(在它知道它是正确的分支之前),因此执行的指令不会中断。当这运作良好时,分支几乎没有成本。当它预测错误时,管道可能会被错误猜测的分支指令填充,这可能会导致明显的延迟,因为它会清除管道并采用正确的分支。在最坏的情况下,这可能意味着 100 秒的时钟周期延迟。例如

考虑以下。

int i; // happens to be 0

if (i > 0) {
   int j = 100 / i;

假设分支通常被占用。这意味着管道可以在知道不会采用分支之前加载触发中断(或 Java 中的错误)的指令。这可能会导致复杂的情况,需要一段时间才能正确展开。

这些被称为错误预测的分支简而言之,每次/大部分时间都以相同方式运行的分支更快,突然改变或非常随机的分支(例如在排序和树数据结构中)将更慢。

于 2012-08-28T08:37:26.240 回答
1

Int 在 32 位系统上可能更快,而 long 在 64 位系统上可能更快。我应该为此烦恼吗?不,您不会为系统配置编码,而是根据您的要求进行编码。微优化永远不会起作用,它们可能会引入一些前所未有的问题。

于 2012-08-28T08:33:01.817 回答
0

Small Integer 对象可以更快,因为 java 对待它们是特定的。

-128 && i <= 127 的所有整数值都存储在 IntegerCache 中,这是 Integer 的内部类

于 2012-08-28T08:36:19.657 回答