java - কেন একটি একক 2D অ্যারে বরাদ্দ করতে একই মোট আকার এবং আকৃতির একাধিক 1D অ্যারে বরাদ্দ করা লুপের চেয়ে বেশি সময় নেয়?




performance (2)

আমি ভেবেছিলাম এটি সরাসরি তৈরি করা দ্রুত হবে তবে বাস্তবে লুপ যুক্ত করতে আধ সময় সময় লাগে takes এতটা ধীর হয়ে গেল এমন কী হয়েছিল?

এখানে পরীক্ষার কোড দেওয়া আছে

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class Test_newArray {
    private static int num = 10000;
    private static int length = 10;

    @Benchmark
    public static int[][] newArray() {
        return new int[num][length];
    }

    @Benchmark
    public static int[][] newArray2() {
        int[][] temps = new int[num][];
        for (int i = 0; i < temps.length; i++) {
            temps[i] = new int[length];
        }
        return temps;
    }

}

পরীক্ষার ফলাফল নিম্নরূপ:

Benchmark                Mode  Cnt    Score   Error  Units
Test_newArray.newArray   avgt   25  289.254 ± 4.982  us/op
Test_newArray.newArray2  avgt   25  114.364 ± 1.446  us/op

পরীক্ষার পরিবেশ নিম্নরূপ

জেএমএইচ সংস্করণ: 1.21

ভিএম সংস্করণ: জেডিকে 1.8.0_212, ওপেনজেডিকে 64-বিট সার্ভার ভিএম, 25.212-বি04


জাভাতে বহুমাত্রিক অ্যারে - multianewarray বরাদ্দ করার জন্য একটি পৃথক বাইটকোড নির্দেশনা multianewarray

  • newArray বেঞ্চমার্ক multianewarray বাইটকোড ব্যবহার করে;
  • newArray2 লুপে সরল newarray আহ্বান জানায়।

সমস্যাটি হ'ল হটস্পট multianewarray জন্য কোনও দ্রুত পথ নেই । এই নির্দেশিকা সর্বদা ভিএম রানটাইমে কার্যকর করা হয়। সুতরাং, সংকলিত কোডে বরাদ্দটি ইনলাইন করা হয় না।

প্রথম বেঞ্চমার্কটি জাভা এবং ভিএম রানটাইম প্রসঙ্গের মধ্যে স্যুইচিংয়ের পারফরম্যান্স জরিমানা দিতে হবে। এছাড়াও, ভিএম রানটাইম (সি ++ তে লিখিত) তে সাধারণ বরাদ্দ কোডটি জেআইটি-সংকলিত কোডে ইনলাইনড বরাদ্দের মতো অনুকূলিত হয় না, কারণ এটি জেনেরিক , অর্থ নির্দিষ্ট বস্তুর ধরণের জন্য বা বিশেষ কল সাইটের জন্য অনুকূল নয়, এটি অতিরিক্ত রানটাইম চেক ইত্যাদি করে

async-profiler সহ উভয় মানদণ্ডকে প্রোফাইল করার ফলাফল এখানে। আমি জেডিকে ১১.০.৪ ব্যবহার করেছি, তবে জেডিকে ৮-এর জন্য চিত্রটি একই রকম দেখাচ্ছে।

প্রথম ক্ষেত্রে, 99% সময় OptoRuntime::multianewarray2_C সি এর মধ্যে - VM রানটাইমের সি ++ কোডে ব্যয় হয়।

দ্বিতীয় ক্ষেত্রে, গ্রাফের বেশিরভাগটি সবুজ, এর অর্থ প্রোগ্রামটি বেশিরভাগ জাভা প্রসঙ্গে চলে, আসলে জেআইটি-সংকলিত কোডটি কার্যকরভাবে প্রদত্ত বেঞ্চমার্কের জন্য অনুকূলিত করে।

সম্পাদনা

* কেবল স্পষ্ট করে multianewarray জন্য: হটস্পট multianewarray ডিজাইনের মাধ্যমে খুব ভালভাবে অনুকূলিত হয় না। উভয় জেআইটি সংকলকগুলিতে এই জাতীয় জটিল অপারেশনটি যথাযথভাবে প্রয়োগ করা ব্যয়বহুল, যদিও এই ধরনের অপ্টিমাইজেশনের সুবিধাগুলি প্রশ্নবিদ্ধ হবে: বহুমাত্রিক অ্যারের বরাদ্দ সাধারণত একটি সাধারণ অ্যাপ্লিকেশনটিতে পারফরম্যান্সের বাধা।


multianewarray নির্দেশের অধীনে ওরাকল ডক্সের একটি নোট বলে:

একক মাত্রার অ্যারে তৈরি করার সময় newarray বা anewarray ( §newarray , §anewarray ) ব্যবহার করা আরও দক্ষ হতে পারে।

আরও:

newArray anewarray বেঞ্চমার্ক anewarray বাইটকোড নির্দেশ ব্যবহার করে।

newArray2 বেঞ্চমার্ক multianewarray বাইটকোড নির্দেশ ব্যবহার করে।

এবং এটিই একটি পার্থক্য তৈরি করে। perf লিনাক্স প্রোফাইলার ব্যবহার করে প্রাপ্ত পরিসংখ্যানগুলি দেখুন।

নতুন newArray বেঞ্চমার্কের জন্য, উত্পন্ন কোডের মধ্যে হটেস্ট অঞ্চলগুলি newArray :

....[Hottest Methods (after inlining)]..............................................................
 22.58%           libjvm.so  MemAllocator::allocate
 14.80%           libjvm.so  ObjArrayAllocator::initialize
 12.92%           libjvm.so  TypeArrayKlass::multi_allocate
 10.98%           libjvm.so  AccessInternal::PostRuntimeDispatch<G1BarrierSet::AccessBarrier<2670710ul, G1BarrierSet>, (AccessInternal::BarrierType)1, 2670710ul>::oop_access_barrier
  7.38%           libjvm.so  ObjArrayKlass::multi_allocate
  6.02%           libjvm.so  MemAllocator::Allocation::notify_allocation_jvmti_sampler
  5.84%          ld-2.27.so  __tls_get_addr
  5.66%           libjvm.so  CollectedHeap::array_allocate
  5.39%           libjvm.so  Klass::check_array_allocation_length
  4.76%        libc-2.27.so  __memset_avx2_unaligned_erms
  0.75%        libc-2.27.so  __memset_avx2_erms
  0.38%           libjvm.so  [email protected]
  0.17%           libjvm.so  [email protected]
  0.10%           libjvm.so  G1ParScanThreadState::copy_to_survivor_space
  0.10%   [kernel.kallsyms]  update_blocked_averages
  0.06%   [kernel.kallsyms]  native_write_msr
  0.05%           libjvm.so  G1ParScanThreadState::trim_queue
  0.05%           libjvm.so  Monitor::lock_without_safepoint_check
  0.05%           libjvm.so  G1FreeCollectionSetTask::G1SerialFreeCollectionSetClosure::do_heap_region
  0.05%           libjvm.so  OtherRegionsTable::occupied
  1.92%  <...other 288 warm methods...>

এবং নতুন newArray2 :

....[Hottest Methods (after inlining)]..............................................................
 93.45%      perf-28023.map  [unknown]
  0.26%           libjvm.so  G1ParScanThreadState::copy_to_survivor_space
  0.22%   [kernel.kallsyms]  update_blocked_averages
  0.19%           libjvm.so  OtherRegionsTable::is_empty
  0.17%        libc-2.27.so  __memset_avx2_erms
  0.16%        libc-2.27.so  __memset_avx2_unaligned_erms
  0.14%           libjvm.so  OptoRuntime::new_array_C
  0.12%           libjvm.so  G1ParScanThreadState::trim_queue
  0.11%           libjvm.so  G1FreeCollectionSetTask::G1SerialFreeCollectionSetClosure::do_heap_region
  0.11%           libjvm.so  MemAllocator::allocate_inside_tlab_slow
  0.11%           libjvm.so  ObjArrayAllocator::initialize
  0.10%           libjvm.so  OtherRegionsTable::occupied
  0.10%           libjvm.so  MemAllocator::allocate
  0.10%           libjvm.so  Monitor::lock_without_safepoint_check
  0.10%   [kernel.kallsyms]  rt2800pci_rxdone_tasklet
  0.09%           libjvm.so  G1Allocator::unsafe_max_tlab_alloc
  0.08%           libjvm.so  ThreadLocalAllocBuffer::fill
  0.08%          ld-2.27.so  __tls_get_addr
  0.07%           libjvm.so  G1CollectedHeap::allocate_new_tlab
  0.07%           libjvm.so  TypeArrayKlass::allocate_common
  4.15%  <...other 411 warm methods...>

যেমন আমরা দেখতে পাচ্ছি, ধীরে ধীরে নতুন newArray বেঞ্চমার্কের জন্য বেশিরভাগ সময় ব্যয় করা হয়:

22.58%  MemAllocator::allocate
14.80%  ObjArrayAllocator::initialize
12.92%  TypeArrayKlass::multi_allocate
 7.38%  ObjArrayKlass::multi_allocate

OptoRuntime::new_array_C ব্যবহার করার OptoRuntime::new_array_C ব্যবহার করে, অ্যারেগুলির জন্য মেমরি বরাদ্দকরণে অনেক কম সময় ব্যয় করে।

perfnorm প্রোফাইলার ব্যবহার করে বোনাসের পরিসংখ্যান:

Benchmark                        Mode  Cnt        Score    Error  Units
newArray                         avgt    4      448.018 ± 80.029  us/op
newArray:CPI                     avgt             0.359            #/op
newArray:L1-dcache-load-misses   avgt         10399.712            #/op
newArray:L1-dcache-loads         avgt       1032985.924            #/op
newArray:L1-dcache-stores        avgt        590756.905            #/op
newArray:cycles                  avgt       1132753.204            #/op
newArray:instructions            avgt       3159465.006            #/op
newArray2                        avgt    4      125.531 ± 50.749  us/op
newArray2:CPI                    avgt             0.532            #/op
newArray2:L1-dcache-load-misses  avgt         10345.720            #/op
newArray2:L1-dcache-loads        avgt         85185.726            #/op
newArray2:L1-dcache-stores       avgt        103096.223            #/op
newArray2:cycles                 avgt        346651.432            #/op
newArray2:instructions           avgt        652155.439            #/op

চক্র এবং নির্দেশাবলীর সংখ্যার পার্থক্যটি নোট করুন।

1 - কোড অঞ্চলগুলি যা সবচেয়ে কার্যকর সময় নেয় execution





performance