ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

java-使用非本地ByteOrder时ByteBuffer.putLong快2倍

2019-10-30 10:02:51  阅读:220  来源: 互联网

标签:microbenchmark disruptor-pattern nio caliper java


尽管广泛阅读了JDK源代码并检查了内在例程,但我还是不能一概而论.

我正在测试清除使用ByteBuffer.putLong(int index,long value)用allocateDirect分配的ByteBuffer.基于JDK代码,如果缓冲区为“本机字节顺序”,则将导致单个8字节的写操作;如果不按字节交换,则将导致相同的写操作.

因此,我希望本机字节顺序(对我来说是小尾数)至少与非本机字节一样快.事实证明,非本地人的速度快约2倍.

这是我在Caliper 0.5x中的基准:

...    

public class ByteBufferBench extends SimpleBenchmark {

    private static final int SIZE = 2048;

    enum Endian {
        DEFAULT,
        SMALL,
        BIG
    }

    @Param Endian endian;

    private ByteBuffer bufferMember; 

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        bufferMember = ByteBuffer.allocateDirect(SIZE);
        bufferMember.order(endian == Endian.DEFAULT ? bufferMember.order() :
            (endian == Endian.SMALL ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN));
    }

    public int timeClearLong(int reps) {
        ByteBuffer buffer = bufferMember;
        while (reps-- > 0) {
            for (int i=0; i < SIZE / LONG_BYTES; i+= LONG_BYTES) {
                buffer.putLong(i, reps);
            }
        }
        return 0;
    }

    public static void main(String[] args) {
        Runner.main(ByteBufferBench.class,args);
    }

}

结果是:

benchmark       type  endian     ns linear runtime
ClearLong     DIRECT DEFAULT   64.8 =
ClearLong     DIRECT   SMALL  118.6 ==
ClearLong     DIRECT     BIG   64.8 =

这是一致的.如果我将putLong替换为putFloat,则本机订单的速度大约要快4倍.如果您看一下putLong的工作原理,那么在非本机情况下,它将做更多的工作:

private ByteBuffer putLong(long a, long x) {
    if (unaligned) {
        long y = (x);
        unsafe.putLong(a, (nativeByteOrder ? y : Bits.swap(y)));
    } else {
        Bits.putLong(a, x, bigEndian);
    }
    return this;
}

请注意,在任何情况下,unaligned都是正确的.本机字节顺序和非本机字节顺序之间的唯一区别是Bits.swap,它偏爱本机大小写(小尾数).

解决方法:

总结机械同情邮件列表中的讨论:

1. OP所描述的异常无法在我的设置(JDK7u40 / Ubuntu13.04 / i7)上重现,从而导致所有情况下堆和直接缓冲区的性能均保持一致,直接缓冲区具有巨大的性能优势:

BYTE_ARRAY DEFAULT 211.1 ==============================
BYTE_ARRAY   SMALL 199.8 ============================
BYTE_ARRAY     BIG 210.5 =============================
DIRECT DEFAULT  33.8 ====
DIRECT   SMALL  33.5 ====
DIRECT     BIG  33.7 ==== 

Bits.swap(y)方法被固有地限制在一条指令中,因此不能/不应该真正考虑很大的差异/开销.

2,以上结果(即与OP经验相矛盾)由幼稚的手推基准和另一位参与者编写的JMH基准独立确认.

这使我相信您正在遇到一些本地问题或某种基准框架问题.如果其他人可以进行实验并查看他们是否可以重现您的结果,那将很有价值.

标签:microbenchmark,disruptor-pattern,nio,caliper,java
来源: https://codeday.me/bug/20191030/1967049.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有