首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >java.lang.System与不安全的性能差异

java.lang.System与不安全的性能差异
EN

Stack Overflow用户
提问于 2022-08-24 16:31:14
回答 1查看 116关注 0票数 1

SystemUnsafe都提供了一些重叠的功能(例如System.arraycopy v.s _UNSAFE.copyMemory)。

就实现而言,看起来两者都依赖于jni,这是正确的语句吗?(我可以找到unsafe.cpp,但在JVM源代码中找不到相应的arraycopy实现)。

另外,如果两者都依赖于JNI,我是否可以说两者的调用开销是相似的呢?

我知道Unsafe可以操作offheap内存,但为了比较起见,让我们在onheap内存上限制上下文。

谢谢你的回答。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-08-26 17:14:00

System.arraycopyUnsafe.copyMemory都是HotSpot的本质。这意味着,JVM在从JIT编译的方法调用这些方法时不使用JNI实现。相反,它将调用替换为特定于体系结构的优化程序集代码。

您可以在stubGenerator_.cpp中找到源。

以下是一个简单的JMH基准:

代码语言:javascript
复制
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;

import java.util.concurrent.ThreadLocalRandom;

import static one.nio.util.JavaInternals.byteArrayOffset;
import static one.nio.util.JavaInternals.unsafe;

@State(Scope.Benchmark)
public class CopyMemory {

    @Param({"12", "123", "1234", "12345", "123456"})
    int size;

    byte[] src;
    byte[] dst;

    @Setup
    public void setup() {
        src = new byte[size];
        dst = new byte[size];
        ThreadLocalRandom.current().nextBytes(src);
    }

    @Benchmark
    public void systemArrayCopy() {
        System.arraycopy(src, 0, dst, 0, src.length);
    }

    @Benchmark
    public void unsafeCopyMemory() {
        unsafe.copyMemory(src, byteArrayOffset, dst, byteArrayOffset, src.length);
    }
}

这两种方法的性能是相似的:

代码语言:javascript
复制
Benchmark                    (size)  Mode  Cnt     Score    Error  Units
CopyMemory.systemArrayCopy       12  avgt   16     5.294 ±  0.162  ns/op
CopyMemory.systemArrayCopy      123  avgt   16     7.057 ±  0.406  ns/op
CopyMemory.systemArrayCopy     1234  avgt   16    18.761 ±  0.492  ns/op
CopyMemory.systemArrayCopy    12345  avgt   16   353.386 ±  3.627  ns/op
CopyMemory.systemArrayCopy   123456  avgt   16  5234.125 ± 57.914  ns/op
CopyMemory.unsafeCopyMemory      12  avgt   16     5.028 ±  0.120  ns/op
CopyMemory.unsafeCopyMemory     123  avgt   16     8.055 ±  0.405  ns/op
CopyMemory.unsafeCopyMemory    1234  avgt   16    19.776 ±  0.523  ns/op
CopyMemory.unsafeCopyMemory   12345  avgt   16   353.549 ±  5.878  ns/op
CopyMemory.unsafeCopyMemory  123456  avgt   16  5246.298 ± 65.427  ns/op

如果您使用-prof perfasm分析器运行这个JMH基准测试,您将看到这两个方法归结为完全相同的组装循环:

代码语言:javascript
复制
# systemArrayCopy

  0.64%   ↗   0x00007fa95d4336d0:   vmovdqu -0x38(%rdi,%rdx,8),%ymm0
  2.81%   │   0x00007fa95d4336d6:   vmovdqu %ymm0,-0x38(%rsi,%rdx,8)
  5.67%   │   0x00007fa95d4336dc:   vmovdqu -0x18(%rdi,%rdx,8),%ymm1
 69.64%   │   0x00007fa95d4336e2:   vmovdqu %ymm1,-0x18(%rsi,%rdx,8)
 15.28%   │   0x00007fa95d4336e8:   add    $0x8,%rdx
          ╰   0x00007fa95d4336ec:   jle    Stub::jbyte_disjoint_arraycopy+112 0x00007fa95d4336d0

# unsafeCopyMemory
  
  1.08%   ↗   0x00007f2d39833af0:   vmovdqu -0x38(%rdi,%rdx,8),%ymm0
  3.09%   │   0x00007f2d39833af6:   vmovdqu %ymm0,-0x38(%rcx,%rdx,8)
  5.78%   │   0x00007f2d39833afc:   vmovdqu -0x18(%rdi,%rdx,8),%ymm1
 66.44%   │   0x00007f2d39833b02:   vmovdqu %ymm1,-0x18(%rcx,%rdx,8)
 19.00%   │   0x00007f2d39833b08:   add    $0x8,%rdx
          ╰   0x00007f2d39833b0c:   jle    Stub::jlong_disjoint_arraycopy+48 0x00007f2d39833af0

在Java堆中使用常规数组时,绝对不需要使用不安全的API。标准System.arraycopy进行了很好的优化。JDK类库本身几乎处处使用System.arraycopy,包括StringBuilderArrayListByteArrayOutputStream等。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73476695

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档