java - switch - সি ভাষার বৈশিষ্ট্য




একটি লুপ জন্য একটি এবং প্রতিটি লুপ জন্য একটি পারফরম্যান্স পার্থক্য আছে? (12)

AcceptList ব্যতিক্রমী ক্ষেত্রে ছাড়া, গৃহীত উত্তর প্রশ্নের উত্তর ...

যেহেতু বেশিরভাগ ডেভেলপারগুলি অ্যারেস্টিস্টের উপর নির্ভর করে (অন্তত আমি তাই বিশ্বাস করি)

তাই আমি এখানে সঠিক উত্তর যোগ করার বাধ্যবাধকতা আছে।

সরাসরি বিকাশকারী ডকুমেন্টেশন থেকে: -

লুপের জন্য বর্ধিত (এছাড়াও মাঝে মাঝে "জন্য-প্রতিটি" লুপ হিসাবে পরিচিত) সংগ্রহস্থলগুলির জন্য ইটারেবল ইন্টারফেস এবং অ্যারেগুলি বাস্তবায়নের জন্য ব্যবহার করা যেতে পারে। সংগ্রহগুলি সহ, একটি ইটারারেটরকে হ্যাক () এবং পরবর্তী () এ ইন্টারফেস কল করার জন্য বরাদ্দ করা হয়। একটি অ্যারেলিস্টের সাথে, হাতের লেখার গণনা করা লুপটি প্রায় 3x দ্রুত (জিটের সাথে বা ছাড়া), তবে অন্য সংগ্রহের জন্য লুপ সিনট্যাক্সের জন্য বর্ধিত সুস্পষ্ট ইটারেটর ব্যবহারের সমতুল্য হবে।

একটি অ্যারে মাধ্যমে পুনরাবৃত্তি করার জন্য বিভিন্ন বিকল্প আছে:

static class Foo {
    int mSplat;
}

Foo[] mArray = ...

public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mSplat;
    }
}

public void one() {
    int sum = 0;
    Foo[] localArray = mArray;
    int len = localArray.length;

    for (int i = 0; i < len; ++i) {
        sum += localArray[i].mSplat;
    }
}

public void two() {
    int sum = 0;
    for (Foo a : mArray) {
        sum += a.mSplat;
    }
}

শূন্য () ধীরতম, কারণ JIT এখনও লুপের মাধ্যমে প্রতিটি পুনরাবৃত্তির জন্য একবার অ্যারের দৈর্ঘ্য পাওয়ার খরচটি অপ্টিমাইজ করতে পারে না।

এক () দ্রুত। এটা লুকানোর জন্য এড়ানো, স্থানীয় ভেরিয়েবল মধ্যে সবকিছু pulls। শুধুমাত্র অ্যারে দৈর্ঘ্য একটি কর্মক্ষমতা সুবিধা উপলব্ধ করা হয়।

দুটি () কোনও JIT ছাড়াই ডিভাইসগুলির জন্য দ্রুত এবং জিটের সাথে ডিভাইসগুলির জন্য এক () থেকে পার্থক্যযোগ্য। এটি জাভা প্রোগ্রামিং ভাষার সংস্করণ 1.5 তে চালু লুপ সিনট্যাক্সের জন্য বর্ধিত ব্যবহার করে।

সুতরাং, আপনি ডিফল্টরূপে লুপের জন্য বর্ধিত ব্যবহার করতে হবে, তবে কর্মক্ষমতা-সমালোচনামূলক অ্যারেস্টিস্ট পুনরাবৃত্তির জন্য হাতের লেখা লিখিত গণনা বিবেচনা করুন।

নিম্নলিখিত দুটি loops মধ্যে পারফরমেন্স পার্থক্য কি, যদি, কোন?

for (Object o: objectArrayList) {
    o.DoSomething();
}

এবং

for (int i=0; i<objectArrayList.size(); i++) {
    objectArrayList.get(i).DoSomething();
}

foreach আপনার কোড পরিষ্কার অভিপ্রায় করে তোলে এবং যে সাধারণত একটি খুব ছোটখাট গতি উন্নতি উপর পছন্দ করা হয় - যদি থাকে।

যখনই আমি একটি সূচিবদ্ধ লুপ দেখি তখন আমাকে এটি আরও কিছুটা বিশ্লেষণ করতে হবে যাতে এটি মনে হয় যে এটি আমার মনে হয় যেমন এটি শূন্য থেকে শুরু করে, এটি কি শেষ বিন্দু ইত্যাদি অন্তর্ভুক্ত করে বা বাদ দেয়?

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


আচ্ছা, পারফরম্যান্সের প্রভাব বেশিরভাগই উল্লেখযোগ্য, কিন্তু শূন্য নয়। যদি আপনি RandomAccess ইন্টারফেসের RandomAccess :

থাম্ব একটি নিয়ম হিসাবে, একটি তালিকা বাস্তবায়ন এই ইন্টারফেস বাস্তবায়ন করা উচিত, ক্লাসের সাধারণ দৃষ্টান্ত জন্য, এই লুপ:

for (int i=0, n=list.size(); i < n; i++)
    list.get(i);

এই লুপ চেয়ে দ্রুত রান করে:

for (Iterator i=list.iterator(); i.hasNext();)
      i.next();

এবং প্রতিটি লুপ ইটারারটারের সাথে সংস্করণটি ব্যবহার করছে, তাই উদাহরণস্বরূপ, ArrayList জন্য, প্রতিটি লুপ দ্রুততম নয়।


এই সব loops ঠিক একই কাজ, আমি শুধু আমার দুই সেন্ট নিক্ষেপ করার আগে এই প্রদর্শন করতে চান।

প্রথম, তালিকা মাধ্যমে looping ক্লাসিক উপায়:

for(int i=0;i<strings.size();i++) { /* do something using strings.get(i) */ }

দ্বিতীয়ত, এটি কম ত্রুটিযুক্ত প্রবণতা থেকে পছন্দের উপায় (কতবার আপনি "ওহে, আইপি এবং জুপগুলিকে loops মধ্যে জিনিসগুলি মিশ্রিত করেছেন" জিনিসটি করেছেন?)।

for(String s : strings) { /* do something using s */ }

তৃতীয়, লুপ জন্য মাইক্রো অপ্টিমাইজেশান:

int size = strings.size();
for(int i=0;++i<=size;) { /* do something using strings.get(i) */ }

এখন আসল দুটি সেন্ট: অন্তত যখন আমি এই পরীক্ষা করছিলাম, তখন তৃতীয়টি হল মিলিসেকেন্ড গণনা করার সময় সবচেয়ে দ্রুততম, এটি প্রতিটি লুপের জন্য কতক্ষণ সময় নেয় তার মধ্যে একটি সহজ অপারেশন সহ কয়েক মিলিয়ন বার পুনরাবৃত্তি - এটি জাভা 5 ব্যবহার করে উইন্ডোজ এ jre1.6u10 সঙ্গে কেউ আগ্রহী হয় ক্ষেত্রে।

যদিও এটি অন্তততম মনে হচ্ছে যে তৃতীয়টি দ্রুততম, আপনি যদি নিজেকে দেখেছেন যে আপনার লুপিং কোডে সর্বত্র এই পিপফোল অপ্টিমাইজেশানটি বাস্তবায়িত করার ঝুঁকি নিতে চান তবে প্রকৃতপক্ষে লুপিং হয় না। টি সাধারণত কোন বাস্তব প্রোগ্রামের সবচেয়ে সময় গ্রাসকারী অংশ (অথবা আমি শুধু ভুল ক্ষেত্রে কাজ করছি, যারা জানেন)। এবং আমি জাভা ফর-প্রতিটি লুপের জন্য প্রেক্ষাপটে উল্লিখিত করেছি (যেমন কিছু ইটারेटर লুপ এবং অন্যদের জন্য ইন লুপ হিসাবে উল্লেখ করে ) এটি ব্যবহার করার সময় আপনি একটি বিশেষ মূঢ় বাগ আঘাত করার সম্ভাবনা কম। এবং বিতর্কের আগে কিভাবে এটি এমনকি অন্যের তুলনায় আরও দ্রুত হতে পারে, মনে রাখবেন যে জাভ্যাক বাইটকোডটি মোটামুটিভাবে অপ্টিমাইজ করে না (ভাল, প্রায় সব সময়ে), এটি কেবল এটি কম্পাইল করে।

আপনি যদি মাইক্রো-অপ্টিমাইজেশানে থাকেন তবে / অথবা আপনার সফটওয়্যারটি অনেকগুলি পুনরাবৃত্তিমূলক লুপ ব্যবহার করে এবং এরপরে আপনি তৃতীয় লুপ টাইপে আগ্রহী হতে পারেন। শুধু loops জন্য পরিবর্তন আগে এবং পরে উভয় আপনার সফটওয়্যার ভালভাবে benchmark মনে রাখবেন আপনি এই অদ্ভুত, মাইক্রো অপ্টিমাইজেশান এক আছে।


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


এমনকি একটি অ্যারেস্টিস্ট বা ভেক্টরের মত, যেখানে "পেতে" একটি সাধারণ অ্যারে সন্ধান হয়, তবে দ্বিতীয় লুপটিতে অতিরিক্ত ওভারহেড থাকে যা প্রথমটি না করে। আমি এটি প্রথম তুলনায় একটি ক্ষুদ্র বিট ধীর হতে আশা করা হবে।


দুর্ভাগ্যবশত একটি পার্থক্য হতে প্রদর্শিত হবে।

আপনি উভয় loops জন্য উত্পন্ন বাইট কোড তাকান, তারা ভিন্ন।

এখানে Log4j সোর্স কোড থেকে একটি উদাহরণ।

/Log4j-api/src/main/java/org/apache/logging/log4j/MarkerManager.java এ আমাদের Log4jMarker নামক স্ট্যাটিক অভ্যন্তরীণ ক্লাস রয়েছে যা সংজ্ঞায়িত করে:

    /*
     * Called from add while synchronized.
     */
    private static boolean contains(final Marker parent, final Marker... localParents) {
        //noinspection ForLoopReplaceableByForEach
        for (final Marker marker : localParents) {
            if (marker == parent) {
                return true;
            }
        }
        return false;
    }

মান লুপ সঙ্গে:

  private static boolean contains(org.apache.logging.log4j.Marker, org.apache.logging.log4j.Marker...);
    Code:
       0: iconst_0
       1: istore_2
       2: aload_1
       3: arraylength
       4: istore_3
       5: iload_2
       6: iload_3
       7: if_icmpge     29
      10: aload_1
      11: iload_2
      12: aaload
      13: astore        4
      15: aload         4
      17: aload_0
      18: if_acmpne     23
      21: iconst_1
      22: ireturn
      23: iinc          2, 1
      26: goto          5
      29: iconst_0
      30: ireturn

প্রতিটি জন্য:

  private static boolean contains(org.apache.logging.log4j.Marker, org.apache.logging.log4j.Marker...);
    Code:
       0: aload_1
       1: astore_2
       2: aload_2
       3: arraylength
       4: istore_3
       5: iconst_0
       6: istore        4
       8: iload         4
      10: iload_3
      11: if_icmpge     34
      14: aload_2
      15: iload         4
      17: aaload
      18: astore        5
      20: aload         5
      22: aload_0
      23: if_acmpne     28
      26: iconst_1
      27: ireturn
      28: iinc          4, 1
      31: goto          8
      34: iconst_0
      35: ireturn

ওটা ওরাকলের সাথে কি?

আমি উইন্ডোজ 7 এ জাভা 7 এবং 8 দিয়ে এটি চেষ্টা করেছি।


নিম্নলিখিত কোডটি:

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

interface Function<T> {
    long perform(T parameter, long x);
}

class MyArray<T> {

    T[] array;
    long x;

    public MyArray(int size, Class<T> type, long x) {
        array = (T[]) Array.newInstance(type, size);
        this.x = x;
    }

    public void forEach(Function<T> function) {
        for (T element : array) {
            x = function.perform(element, x);
        }
    }
}

class Compute {
    int factor;
    final long constant;

    public Compute(int factor, long constant) {
        this.factor = factor;
        this.constant = constant;
    }

    public long compute(long parameter, long x) {
        return x * factor + parameter + constant;
    }
}

public class Main {

    public static void main(String[] args) {
        List<Long> numbers = new ArrayList<Long>(50000000);
        for (int i = 0; i < 50000000; i++) {
            numbers.add(i * i + 5L);
        }

        long x = 234553523525L;

        long time = System.currentTimeMillis();
        for (int i = 0; i < numbers.size(); i++) {
            x += x * 7 + numbers.get(i) + 3;
        }
        System.out.println(System.currentTimeMillis() - time);
        System.out.println(x);
        x = 0;
        time = System.currentTimeMillis();
        for (long i : numbers) {
            x += x * 7 + i + 3;
        }
        System.out.println(System.currentTimeMillis() - time);
        System.out.println(x);
        x = 0;
        numbers = null;
        MyArray<Long> myArray = new MyArray<Long>(50000000, Long.class, 234553523525L);
        for (int i = 0; i < 50000000; i++) {
            myArray.array[i] = i * i + 3L;
        }
        time = System.currentTimeMillis();
        myArray.forEach(new Function<Long>() {

            public long perform(Long parameter, long x) {
                return x * 8 + parameter + 5L;
            }
        });
        System.out.println(System.currentTimeMillis() - time);
        System.out.println(myArray.x);
        myArray = null;
        myArray = new MyArray<Long>(50000000, Long.class, 234553523525L);
        for (int i = 0; i < 50000000; i++) {
            myArray.array[i] = i * i + 3L;
        }
        time = System.currentTimeMillis();
        myArray.forEach(new Function<Long>() {

            public long perform(Long parameter, long x) {
                return new Compute(8, 5).compute(parameter, x);
            }
        });
        System.out.println(System.currentTimeMillis() - time);
        System.out.println(myArray.x);
    }
}

আমার সিস্টেমে আউটপুট নিম্নলিখিত দেয়:

224
-699150247503735895
221
-699150247503735895
220
-699150247503735895
219
-699150247503735895

আমি উবুন্টু 12.10 আলফা ব্যবহার করছি OracleJDK 1.7 আপডেট 6।

সাধারণভাবে হট স্পট অনেকগুলি অদলবদল এবং সাধারণ ক্ষতিকারক ক্রিয়াকলাপকে অপ্টিমাইজ করে, তাই সাধারণভাবে আপনাকে তাদের সম্পর্কে উদ্বিগ্ন হওয়া উচিত না যতক্ষণ না তাদের অনেকেই সিকেন্সে থাকে বা তারা খুব ঘন ঘন হয়।

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


ভেরিয়েবল নাম objectArrayList , আমি অনুমান করি যে এটি java.util.ArrayList একটি উদাহরণ। যে ক্ষেত্রে, পারফরম্যান্স পার্থক্য অজানা হবে।

অন্যদিকে, যদি এটি java.util.LinkedList এর উদাহরণ হয় তবে দ্বিতীয় পদ্ধতিটি যত ধীর হবে ততই List#get(int) একটি O (n) অপারেশন হবে।

লুপের যুক্তি অনুসারে সূচীটি প্রয়োজন না হওয়া পর্যন্ত প্রথম পদ্ধতিটি সর্বদা পছন্দসই।


সূচনার পরিবর্তে ইটারারটার ব্যবহার করা সবসময় ভাল। Indexer (কলিং পেতে) হতে পারে না যখন এটির তালিকা তালিকা বাস্তবায়ন জন্য সম্ভবত optimizied কারণ এটি কারণ। উদাহরণস্বরূপ লিঙ্কডলিস্ট একটি তালিকা তবে তার উপাদানগুলির মাধ্যমে সূচীটি ইটারারটার ব্যবহার করে পুনরাবৃত্তির চেয়ে ধীর হবে।


public class FirstJavaProgram {

    public static void main(String[] args) 
    {
        int a[]={1,2,3,45,6,6};

// Method 1: this is simple way to print array 

        for(int i=0;i<a.length;i++) 
        { 
            System.out.print(a[i]+" ");
        }

// Method 2: Enhanced For loop

        for(int i:a)
        {
            System.out.print(i+" ");
        }
    }
}

1. for(Object o: objectArrayList){
    o.DoSomthing();
}
and

2. for(int i=0; i<objectArrayList.size(); i++){
    objectArrayList.get(i).DoSomthing();
}

উভয়ই একই রকম কাজ করে কিন্তু সহজ এবং নিরাপদ প্রোগ্রামিংয়ের জন্য প্রতিটি ব্যবহারের জন্য, ব্যবহার করার দ্বিতীয় পদ্ধতিতে ভুল প্রবণতার সম্ভাবনা রয়েছে।





for-loop