java数组中第i个元素为空_将Java数组中任意范围的元素设置为空的最快方法是什么?...

如果我的意思是正确的,你需要取消一个数组,或者一个包含对象引用的数组的子范围,使它们符合GC.并且您有一个常规的

Java数组,它将数据存储在堆上.

回答您的问题,System.arrayCopy是清空数组子范围的最快方法.它比Arrays.ref的内存更糟糕,因为你必须分配两倍的内存来保存最坏情况下的引用,可以从中复制一个null数组.虽然如果你需要完全清空一个数组,更快的只是创建一个新的空数组(例如新的Object [desiredLength]),并用一个你想要的null替换它.

不安全,DirectByteBuffer,DirectLongBuffer实现在初始化的直接实现(即,如果您只是使用DirectByteBuffer或Unsafe替换Array)不提供任何性能增益.它们比较慢,然后批量System.arrayCopy以及.由于这些实现与Java Array无关,所以它们超出了您的问题的范围.

这是我的JMH基准(完整基准代码可用via gist)的代码片段,包括根据@apangin注释的unsafe.setMemory案例;并且包括ByteBuffer.put(long [] src,int srcOffset,int longCount))// @ jan-chaefer;并且等同于Arrays.fill循环,根据@ scott-carey来检查Arrays.fill是否可以是JDK 8中的内在函数.

@Benchmark

@BenchmarkMode(Mode.SampleTime)

@OutputTimeUnit(TimeUnit.NANOSECONDS)

public void arrayFill() {

Arrays.fill(objectHolderForFill, null);

}

@Benchmark

@BenchmarkMode(Mode.SampleTime)

@OutputTimeUnit(TimeUnit.NANOSECONDS)

public void arrayFillManualLoop() {

for (int i = 0, len = objectHolderForFill.length; i < len; i++) {

objectHolderForLoop[i] = null;

}

}

@Benchmark

@BenchmarkMode(Mode.SampleTime)

@OutputTimeUnit(TimeUnit.NANOSECONDS)

public void arrayCopy() {

System.arraycopy(nullsArray, 0, objectHolderForArrayCopy, 0,

objectHolderForArrayCopy.length);

}

@Benchmark

@BenchmarkMode(Mode.SampleTime)

@OutputTimeUnit(TimeUnit.NANOSECONDS)

public void directByteBufferManualLoop() {

while (referenceHolderByteBuffer.hasRemaining()) {

referenceHolderByteBuffer.putLong(0);

}

}

@Benchmark

@BenchmarkMode(Mode.SampleTime)

@OutputTimeUnit(TimeUnit.NANOSECONDS)

public void directByteBufferBatch() {

referenceHolderByteBuffer.put(nullBytes, 0, nullBytes.length);

}

@Benchmark

@BenchmarkMode(Mode.SampleTime)

@OutputTimeUnit(TimeUnit.NANOSECONDS)

public void directLongBufferManualLoop() {

while (referenceHolderLongBuffer.hasRemaining()) {

referenceHolderLongBuffer.put(0L);

}

}

@Benchmark

@BenchmarkMode(Mode.SampleTime)

@OutputTimeUnit(TimeUnit.NANOSECONDS)

public void directLongBufferBatch() {

referenceHolderLongBuffer.put(nullLongs, 0, nullLongs.length);

}

@Benchmark

@BenchmarkMode(Mode.SampleTime)

@OutputTimeUnit(TimeUnit.NANOSECONDS)

public void unsafeArrayManualLoop() {

long addr = referenceHolderUnsafe;

long pos = 0;

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

unsafe.putLong(addr + pos, 0L);

pos += 1 << 3;

}

}

@Benchmark

@BenchmarkMode(Mode.SampleTime)

@OutputTimeUnit(TimeUnit.NANOSECONDS)

public void unsafeArraySetMemory() {

unsafe.setMemory(referenceHolderUnsafe, size*8, (byte) 0);

}

这是我得到的(Java 1.8,JMH 1.13,Core i3-6100U 2.30 GHz,Win10):

100 elements

Benchmark Mode Cnt Score Error Units

ArrayNullFillBench.arrayCopy sample 5234029 39,518 ± 0,991 ns/op

ArrayNullFillBench.directByteBufferBatch sample 6271334 43,646 ± 1,523 ns/op

ArrayNullFillBench.directLongBufferBatch sample 4615974 45,252 ± 2,352 ns/op

ArrayNullFillBench.arrayFill sample 4745406 76,997 ± 3,547 ns/op

ArrayNullFillBench.arrayFillManualLoop sample 5549216 78,677 ± 13,013 ns/op

ArrayNullFillBench.unsafeArrayManualLoop sample 5980381 78,811 ± 2,870 ns/op

ArrayNullFillBench.unsafeArraySetMemory sample 5985884 85,062 ± 2,096 ns/op

ArrayNullFillBench.directLongBufferManualLoop sample 4697023 116,242 ± 2,579 ns/op

ArrayNullFillBench.directByteBufferManualLoop sample 7504629 208,440 ± 10,651 ns/op

I skipped all** the loop implementations from further tests

** - except arrayFill and arrayFillManualLoop for scale

1000 elements

Benchmark Mode Cnt Score Error Units

ArrayNullFillBench.arrayCopy sample 6780681 184,516 ± 14,036 ns/op

ArrayNullFillBench.directLongBufferBatch sample 4018778 293,325 ± 4,074 ns/op

ArrayNullFillBench.directByteBufferBatch sample 4063969 313,171 ± 4,861 ns/op

ArrayNullFillBench.arrayFillManualLoop sample 6270397 543,801 ± 20,325 ns/op

ArrayNullFillBench.arrayFill sample 6590416 548,250 ± 13,475 ns/op

10000 elements

Benchmark Mode Cnt Score Error Units

ArrayNullFillBench.arrayCopy sample 2551851 2024,543 ± 12,533 ns/op

ArrayNullFillBench.directLongBufferBatch sample 2958517 4469,210 ± 10,376 ns/op

ArrayNullFillBench.directByteBufferBatch sample 2892258 4526,945 ± 33,443 ns/op

ArrayNullFillBench.arrayFill sample 2578580 5532,063 ± 20,705 ns/op

ArrayNullFillBench.arrayFillManualLoop sample 2562569 5550,195 ± 40,666 ns/op

附:说到ByteBuffer和Unsafe – 它们在你的情况下的主要优点是它们将数据存储在堆外,并且可以实现自己的内存分配算法,这将比常规GC更好地挖掘出数据结构.所以你不需要取消它们,并且可以按你的要求压缩内存.最有可能的努力将不值得,因为现在您可以轻松获得性能较差且容易出错的代码.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值