JVMがchar []に基づいてStringの作成を実装する方法に関する質問に続いて、char []が新しい文字列の内部にコピーされるときに反復が行われないことを述べましたSystem.arraycopyは最終的に呼び出されるため、memcpyなどの関数を使用してネイティブ実装固有のレベル(the original question)で目的のメモリをコピーします。System.arraycopyのOpenJDKの実装
自分自身で確認したかったので、Openjdk 7のソースコードをダウンロードして閲覧し始めました。 Iはopenjdx/hotspot/src/share/vm/oops/objArrayKlass.cpp
に、OpenJDKのC++ソースコードにSystem.arraycopyの実装を発見した:
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
要素がないタイプチェックを必要としない場合(すなわち、例えば、プリミティブデータ型アレイの場合だ)、コピー: :conjoin_oops_atomicが呼び出されます。
Copy::conjoint_oops_atomic
機能は「copy.hpp」に格納されています。コピー操作は、OS /アーキテクチャに基づいて、異なる実装を持っているよう
// 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値)を反復処理します。誰かが、配列内の要素を反復することによって、コピーが元のレベルであってもなぜ行われたのか説明できますか?
うわー、ありがとう!はじめてOpenJDKの実装を見るのはちょっと混乱していたので、何か間違っていると思っていました。 :Pだから、この最適化はどう考えますか?私はいくつかのテストとシステムをやった。arraycopyは、通常のJavaの方法よりも10000のintをコピーするのが2倍高速です。 C++では、さまざまなコンパイラの最適化によって影響を受ける可能性がありますが、似たような処理が目立って高速です。 –
C++コピーに別のスレッドで実行されているガベージコレクタがありません。たとえあなたがゴミを発生させないとしても、コレクターは何もする必要がないことを確認するために数サイクルを盗む必要があります。コンパイラーがarraycopyループをアンロールしているかどうか、またはハードウェアがアレイのブロック全体をキャッシュにプリフェッチしているかどうかはわかりません。実際、マイクロコードの最適化では、私の知識の深さを超えています。それがプロファイリングが重要な理由です。最適化が価値があることが証明されたテストです。 –