gpt4 book ai didi

c++ - System.arraycopy 的 OpenJDK 实现

转载 作者:可可西里 更新时间:2023-11-01 16:40:01 26 4
gpt4 key购买 nike

在一个与 JVM 基于 char[] 实现字符串创建的方式相关的问题之后,我提到当 char[] 被复制到新字符串的内部时不会发生迭代,因为 System.arraycopy 得到最终被调用,它使用诸如 memcpy 之类的函数在 native 的、依赖于实现的级别 ( the original question) 复制所需的内存。

我想亲自检查一下,所以我下载了 Openjdk 7 源代码并开始浏览它。我在 OpenJDK C++ 源代码中找到了 System.arraycopy 的实现,在 openjdx/hotspot/src/share/vm/oops/objArrayKlass.cpp 中:

if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) {
// elements are guaranteed to be subtypes, so no check necessary
bs->write_ref_array_pre(dst, length);
Copy::conjoint_oops_atomic(src, dst, length);
} else {
// slow case: need individual subtype checks

如果元素不需要类型检查(例如原始数据类型数组就是这种情况),则调用 Copy::conjoin_oops_atomic。

Copy::conjoint_oops_atomic 函数位于“copy.hpp”中:

// overloaded for UseCompressedOops
static void conjoint_oops_atomic(narrowOop* from, narrowOop* to, size_t count) {
assert(sizeof(narrowOop) == sizeof(jint), "this cast is wrong");
assert_params_ok(from, to, LogBytesPerInt);
pd_conjoint_jints_atomic((jint*)from, (jint*)to, count);
}

现在我们依赖于平台,因为复制操作有不同的实现,基于操作系统/架构。我将以 Windows 为例。 openjdk\hotspot\src\os_cpu\windows_x86\vm\copy_windows_x86.inline.hpp:

static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) {
// Do better than this: inline memmove body NEEDS CLEANUP
if (from > to) {
while (count-- > 0) {
// Copy forwards
*to++ = *from++;
}
} else {
from += count - 1;
to += count - 1;
while (count-- > 0) {
// Copy backwards
*to-- = *from--;
}
}
}

而且......令我惊讶的是,它遍历元素(oop 值),一个一个地(貌似)复制它们。有人可以通过遍历数组中的元素来解释为什么即使在 native 级别也完成了复制吗?

最佳答案

因为 jint 最接近地映射到 int 而它最接近地映射到旧的硬件架构 WORD,它的大小基本上与数据总线的宽度。

当今的内存架构和 CPU 处理被设计为即使在缓存未命中的情况下也能尝试处理,并且内存位置倾向于预取 block 。您正在查看的代码在性能上并不像您想象的那么“糟糕”。硬件更智能,如果您实际上没有分析,您的“智能”获取例程实际上可能什么也没有添加(甚至减慢处理速度)。

当你被介绍到硬件架构时,你必须被介绍到简单的架构。现代的做的更多,所以你不能假设看起来低效的代码实际上是低效的。例如,当执行内存查找以评估 if 语句的条件时,通常会在查找发生时执行 if 语句的两个分支,并且在数据可用于评估后丢弃处理的“假”分支条件。如果您想提高效率,就必须剖析剖析数据,然后根据剖析数据采取行动。

查看 JVM 操作码部分的分支。您会看到它是(或者可能只是)一个 ifdef 宏的怪异之处,它支持(一次)三种不同的跳转到处理操作码的代码的方式。这是因为这三种不同的方式实际上在不同的 Windows、Linux 和 Solaris 架构上产生了有意义的性能差异。

也许他们可以包含 MMX 例程,但他们没有告诉我 SUN 认为现代硬件的性能提升不足以让我担心它。

关于c++ - System.arraycopy 的 OpenJDK 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11210369/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com