java中short能优化int吗_关于java:为什么short基本类型比long或int显着慢?

我试图通过将int原语更改为短裤来优化Android游戏的RAM使用率。在进行此操作之前,我对Java中原始类型的性能感兴趣。

因此,我使用卡尺库创建了这个小的测试基准。

public class BenchmarkTypes extends Benchmark {

@Param("10") private long testLong;

@Param("10") private int testInt;

@Param("10") private short testShort;

@Param("5000") private long resultLong = 5000;

@Param("5000") private int resultInt = 5000;

@Param("5000") private short resultShort = 5000;

@Override

protected void setUp() throws Exception {

Random rand = new Random();

testShort = (short) rand.nextInt(1000);

testInt = (int) testShort;

testLong = (long) testShort;

}

public long timeLong(int reps){

for(int i = 0; i < reps; i++){

resultLong += testLong;

resultLong -= testLong;

}

return resultLong;

}

public int timeInt(int reps){

for(int i = 0; i < reps; i++){

resultInt += testInt;

resultInt -= testInt;

}

return resultInt;

}

public short timeShort(int reps){

for(int i = 0; i < reps; i++){

resultShort += testShort;

resultShort -= testShort;

}

return resultShort;

}

}

测试结果令我惊讶。

测试情况

基准在Caliper库下运行。

检测结果

https://microbenchmarks.appspot.com/runs/0c9bd212-feeb-4f8f-896c-e027b85dfe3b

内部2.365 ns

长2.436 ns

短8.156 ns

测试结论?

短基元类型比长基元和int基元类型慢得多(3-4倍)?

为什么short原语比int或long长得多?我希望int原语类型在32位VM上最快,而long和short在时间上相等,或者short甚至更快。

Android手机也是如此吗?知道Android手机通常在32位环境中运行,如今,越来越多的手机开始配备64位处理器。

您尚未预热JIT。您没有完成足够的迭代。这不是您如何微平台化Java。

(最有可能是)由Java将短时间(每次)转换为int(或long)进行算术运算引起的

@GermannArlington-否。时间上相差1000倍的真正原因是基准未正确编写。请参阅链接的问答。

是的,这里没有真正的基准!但是慢1000倍?创建一个良好的基准真的会带来巨大的改变吗?

Rolf-阅读您链接到的答案的第一条评论。写下答案的人可能犯了与您相同的错误。

罗尔夫-当然可以。尝试按照建议重新编写基准,然后看看会得到什么。

为什么将此标记为重复?这肯定是另一个问题!

由于您的基准测试存在缺陷,因此您的"结果"无效,并且试图解释它也没有太多意义……好像它是真实的结果。 (这不仅是无效的。将1000倍的速度减慢根本是不可能的。)虽然此问题并非严格地与另一个问题重复,但其他问题的答案是对此问题的最佳回答。

如果您使用有效的基准和有效的结果更新了问题,则可能值得重新打开...

没有证据表明这个问题及其结果是无效的!你有证据吗?为何有人会在真正的生产应用程序永远不会运行的"特殊微平台"测试环境中进行测试?在这种环境下,速度可能会降低1000倍,而我只想知道为什么在这种环境下会这么慢。

遗传证明(ish)-stackoverflow.com/a/14532605/139985。问题不在于环境。这是因为您的基准测试与实际应用程序不一样……而且典型的JVM设计为有效运行。最有可能发生的是,基准测试的"慢速"部分因JIT编译而失真。您实际上正在测量JIT编译和优化代码所花费的时间!

使用Java caliper库用新的测试结果更新了问题。

请注意,您的操作是无操作,并且足够聪明的JIT可以将其全部销毁。这很容易解决(Id建议单独使用+=或与^=结合使用)。 @StephenC当前关闭的原因不再正确,因此,Id建议重新打开(尽管它可能会因为您链接的问题的重复而关闭)。

@RolfSmit最好证明您已尝试确保基准测试有意义,而不是要求提供证明。解释行为有时可能需要几个小时,我们不希望浪费时间。假设应用程序运行了足够长的时间(这就是Java的本意),那么基准测试工具的作用应该接近实际发生的情况。确实,在Android上可能有所不同。

我同意,我正在尝试优化RAM使用率,使用短裤会改善这种情况。但是我不希望性能下降。我该怎么办?使用短裤的对象被分配!

重新开放-这个问题现在有了一个比较合理的基准,其中包含一组更合理的数字。不过,我很确定,这个问题完全可以通过@StephenC链接的那个问题得到解答。使用short减少内存占用的可能性不大。

对于小于int的基本类型,Java字节码不支持基本操作(+,-,*,/,>>,>>>,<

使用javap签出生成的字节码,以查看short测试和int测试之间的区别。

VM / JIT优化显然偏向于int / long操作,这很有意义,因为它们是最常见的。

小于int的类型有其用途,但主要用于节省数组中的内存。它们不像简单的类成员那样适合(当然,当数据的适当类型时,您仍然会使用它们)。较小的成员甚至不能减小对象的大小。 (再次)主要为当前VM量身定制执行速度,因此VM甚至可以将字段与本机字边界对齐,以提高访问性能,但会浪费内存。

由于java / android处理小于int的基元的整数算术的方式,因此这是可能的。

如果在Java中添加了两个小于数据类型的原语,则它们会被自动提升为整数数据类型。通常需要强制转换以将结果转换回必要的数据类型。

技巧包括速记操作,例如+=,-=等,在隐式发生强制转换的地方,这样操作的最终结果是:

resultShort += testShort;

实际上类似于以下内容:

resultShort = (short)((int) resultShort + (int) testShort);

如果我们看一下方法的反汇编字节码:

public static int test(int a, int b){

a += b;

return a;

}

我们看:

public static int test(int, int);

Code:

0: iload_0

1: iload_1

2: iadd

3: istore_0

4: iload_0

5: ireturn

将其与替换为数据类型的相同方法进行简短比较,我们得到:

public static short test(short, short);

Code:

0: iload_0

1: iload_1

2: iadd

3: i2s

4: istore_0

5: iload_0

6: ireturn

注意附加指令i2s(整数,简称为short)。这可能是造成性能下降的原因。您可能会注意到的另一件事是,所有指令都是基于整数的,由前缀i表示(例如,iadd表示整数加法)。这意味着在iload阶段的某个地方,短裤被提升为整数,这也可能导致性能下降。

如果您能理解我的话,那么长算术的字节码与整数1相同,除了指令是长特定的(例如ladd而不是iadd)。

这个答案是正确的。 但是,重要的是要记住,JVM不会直接执行字节码(一旦它已被JIT编译)。 因此,字节码不能直接解释差异。 例如,如果本机指令集直接支持16算术,并且JIT编译器足够聪明,可以使用它,那么您可能希望short算术比long算术快。

但现实情况是,针对PC,服务器甚至智能电话设备的指令集已针对32位/ 64位操作而非16位操作进行了调整。 因此,执行16位算术通常需要更多的本机指令和更多的时钟周期,这使其比32位和64位要慢,如OP基准测试所示。 但是,这高度依赖于目标平台的硬件……并可能依赖于JIT编译器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值