একটি লুপের ভিতরে বা বাইরে ভেরিয়েবলগুলি ঘোষণা করা


236

নিচের কাজটি কেন ঠিক আছে?

String str;
while (condition) {
    str = calculateStr();
    .....
}

তবে এটিকে বিপজ্জনক / ভুল বলে বলা হয়:

while (condition) {
    String str = calculateStr();
    .....
}

লুপের বাইরে ভেরিয়েবল ঘোষণা করা কি প্রয়োজনীয়?

উত্তর:


289

স্থানীয় ভেরিয়েবলের সুযোগ সর্বদা সবচেয়ে ছোট হওয়া উচিত।

আপনার উদাহরণ হিসাবে আমি অনুমান করি লুপের বাইরে ব্যবহার করা strহয় নাwhile , অন্যথায় আপনি প্রশ্ন জিজ্ঞাসা করবেন না, কারণ এটি এর ভিতরে ঘোষণা করেwhile লুপের করা কোনও বিকল্প হবে না, যেহেতু এটি সংকলন করবে না।

সুতরাং, যেহেতু strহয় না লুপ বাইরে ব্যবহার করা হয়, এর জন্য ক্ষুদ্রতম সম্ভব সুযোগ strহয় মধ্যে যখন লুপ।

সুতরাং, উত্তরটি দৃhat়ভাবে বলা যায় যে strএকেবারে লুপের মধ্যেই ঘোষণা করা উচিত। কোনও আইএফএস, কোনও এন্ডএস, কোনও বুট নেই।

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

সম্পাদনা: (উত্তরে নীচে আমার মন্তব্য ইনজেকশন)

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


2
শেষ অনুচ্ছেদে প্রশ্ন: এটি যদি অন্য কোনও হয় তবে স্ট্রিং যা অপরিবর্তনীয় নয় তবে তা কি প্রভাব ফেলবে?
হ্যারি জয়

1
@ হারিজয় হ্যাঁ, অবশ্যই স্ট্রিংবিল্ডারের উদাহরণ নিন, যা পরিবর্তনযোগ্য। আপনি যদি লুপের প্রতিটি পুনরাবৃত্তিতে একটি নতুন স্ট্রিং তৈরি করতে স্ট্রিংবিল্ডার ব্যবহার করেন তবে আপনি লুপের বাইরে স্ট্রিংবিল্ডার বরাদ্দ করে জিনিসগুলি অনুকূল করতে পারেন। তবে এখনও, এটি একটি পরামর্শদায়ক অনুশীলন নয়। আপনি যদি খুব ভাল কারণ ব্যতীত এটি করেন তবে এটি একটি অকাল অপটিমাইজেশন।
মাইক নকিস

7
@ হ্যারিজয় জিনিসগুলি করার সঠিক উপায় হ'ল আপনার সমস্ত কোডটি সঠিকভাবে লেখা , আপনার পণ্যটির জন্য একটি পারফরম্যান্স প্রয়োজনীয়তা প্রতিষ্ঠা করা, এই প্রয়োজনীয়তার বিরুদ্ধে আপনার চূড়ান্ত পণ্যটি পরিমাপ করা এবং যদি এটি সন্তুষ্ট না হয় তবে জিনিসগুলি অনুকূলিত করুন। এবং আপনি জানেন কি? আপনি সাধারণত কয়েকটি স্থানে কয়েকটি দুর্দান্ত এবং আনুষ্ঠানিক অ্যালগরিদমিক অপ্টিমাইজেশান সরবরাহ করতে সক্ষম হবেন যা আপনার পুরো কোড বেজ জুড়ে যাওয়ার পরিবর্তে কৌশলটি সম্পাদন করবে এবং এখানে এবং সেখানে ঘড়ির চক্র নিবিড় করার জন্য জিনিসগুলিকে টুইঙ্ক এবং হ্যাক করবে।
মাইক নকিস

2
@ মাইকনাকিস আমি যে জিনিসটি আপনি খুব সংকীর্ণ পরিসরে চিন্তা করছেন।
সিটেন

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

293

আমি এই দুটি (অনুরূপ) উদাহরণগুলির বাইট কোডটি তুলনা করেছি:

আসুন 1. তাকান । উদাহরণ :

package inside;

public class Test {
    public static void main(String[] args) {
        while(true){
            String str = String.valueOf(System.currentTimeMillis());
            System.out.println(str);
        }
    }
}

পরে javac Test.java, javap -c Testআপনি পাবেন:

public class inside.Test extends java.lang.Object{
public inside.Test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   invokestatic    #2; //Method java/lang/System.currentTimeMillis:()J
   3:   invokestatic    #3; //Method java/lang/String.valueOf:(J)Ljava/lang/String;
   6:   astore_1
   7:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   10:  aload_1
   11:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   14:  goto    0

}

আসুন 2. তাকান । উদাহরণ :

package outside;

public class Test {
    public static void main(String[] args) {
        String str;
        while(true){
            str =  String.valueOf(System.currentTimeMillis());
            System.out.println(str);
        }
    }
}

পরে javac Test.java, javap -c Testআপনি পাবেন:

public class outside.Test extends java.lang.Object{
public outside.Test();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   invokestatic    #2; //Method java/lang/System.currentTimeMillis:()J
   3:   invokestatic    #3; //Method java/lang/String.valueOf:(J)Ljava/lang/String;
   6:   astore_1
   7:   getstatic       #4; //Field java/lang/System.out:Ljava/io/PrintStream;
   10:  aload_1
   11:  invokevirtual   #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   14:  goto    0

}

পর্যবেক্ষণগুলি দেখায় যে এই দুটি উদাহরণের মধ্যে কোনও পার্থক্য নেই । এটি জেভিএম নির্দিষ্টকরণের ফলাফল ...

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


3
এটি 'সংকলক অপ্টিমাইজেশন' নয়, জেভিএম সোসিফিকেশনের ফলাফল। কোনও পদ্ধতির জন্য প্রয়োজনীয় স্ট্যাক স্লটগুলি সমস্ত পদ্ধতিতে প্রবেশের সময় বরাদ্দ করা হয়। বাইটকোডটি এভাবে নির্দিষ্ট করা হয়।
লার্ন

2
@আরহিমিডে এটিকে লুপের ভিতরে রাখার আরও একটি কারণ রয়েছে (বা কেবল '{}' ব্লক): আপনি যদি অন্য স্কেপটিতে ভেরিয়েবলের বাইরে ঘোষণা করেন তবে সংকলকটি অন্য স্কোপে ভেরিয়েবলের জন্য স্ট্যাক ফ্রেমে বরাদ্দকৃত স্মৃতি পুনরায় ব্যবহার করবে you ।
সার্জ

1
যদি ডেটা অবজেক্টগুলির একটি তালিকা এর মাধ্যমে এটির লুপিং হয়, তবে এটি কি প্রচুর উপাত্তের জন্য কোনও পার্থক্য আনবে? সম্ভবত 40 হাজার।
মিথুন খাত্রি

7
তোমাদের মধ্যে কোন finalপ্রেমীদের: প্রকাশক strহিসাবে finalমধ্যে insideপ্যাকেজ ক্ষেত্রে এছাড়াও কোনো পার্থক্য করে তোলে =)
skia.heliou

27

ক্ষুদ্রতম স্কোপগুলিতে অবজেক্টগুলি ঘোষণা করা পাঠযোগ্যতার উন্নতি করে ।

পারফরম্যান্স আজকের সংকলকগুলির পক্ষে গুরুত্বপূর্ণ নয় ((এই দৃশ্যে)
রক্ষণাবেক্ষণের দৃষ্টিকোণ থেকে ২ য় বিকল্পটি আরও ভাল।
সম্ভব সংকীর্ণ সুযোগে একই জায়গায় ভেরিয়েবলগুলি ঘোষণা এবং প্রারম্ভিক করুন।

যেমন ডোনাল্ড এরভিন নুথ বলেছেন:

"আমাদের ছোট কার্যকারিতা সম্পর্কে ভুলে যাওয়া উচিত, সময়ের প্রায় 97% বলুন: অকালীন অপ্টিমাইজেশন হ'ল সমস্ত দুষ্টের মূল"

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


1
"২ য় বিকল্পের কিছুটা দ্রুত পারফরম্যান্স রয়েছে" => আপনি কি এটি মাপা করেছেন? উত্তরের একটি অনুসারে, বাইটকোডটি সমান তাই পারফরম্যান্স কীভাবে আলাদা হতে পারে তা আমি দেখছি না।
Assylias

আমি দুঃখিত তবে জাভা প্রোগ্রামটির পারফরম্যান্স পরীক্ষা করার জন্য এটি সত্যিকারের সঠিক উপায় নয় (এবং আপনি যেভাবেই অসীম লুপের পারফরম্যান্সটি পরীক্ষা করতে পারেন?)
অ্যাসিরিয়াস

আমি আপনার অন্যান্য বিষয়গুলির সাথে একমত - এটি কেবলমাত্র আমি বিশ্বাস করি যে কার্য সম্পাদনের কোনও পার্থক্য নেই।
Assylias

11

আপনি যদি strবাইরে লুপও ব্যবহার করতে চান ; বাইরে ঘোষণা করুন অন্যথায়, 2 য় সংস্করণ ঠিক আছে।


11

দয়া করে আপডেট করা উত্তর এড়িয়ে যান ...

যাঁরা পারফরম্যান্সের বিষয়ে চিন্তা করেন তাদের জন্য System.out এড়িয়ে লুপটি 1 বাইটে সীমাবদ্ধ করুন। ডাবল (পরীক্ষা 1/2) ব্যবহার করে এবং স্ট্রিং (3/4) ব্যবহারের সময়টি উইন্ডোজ 7 প্রফেশনাল bit৪ বিট এবং জেডিকে-১.7.০.১১ এর সাথে মিলিসেকেন্ডে অতিবাহিত সময়গুলি নীচে দেওয়া হয়েছে। বাইটকোডগুলি (টেস্ট 1 এবং টেস্ট 2 এর জন্য নীচেও দেওয়া হয়েছে) এক নয়। আমি পরিবর্তনীয় এবং তুলনামূলকভাবে জটিল বিষয়গুলির সাথে পরীক্ষা করতে খুব অলস ছিলাম।

ডবল

টেস্ট 1 গ্রহণ করেছে: 2710 ম্যাসেকস

টেস্ট 2 নিয়েছে: 2790 ম্যাসেকস

স্ট্রিং (কেবল পরীক্ষার স্ট্রিংয়ের সাথে ডাবল প্রতিস্থাপন করুন)

টেস্ট 3 নিয়েছে: 1200 ম্যাসেকস

টেস্ট 4 নিয়েছে: 3000 ম্যাসেকস

সংকলন এবং বাইকোড পাচ্ছেন

javac.exe LocalTest1.java

javap.exe -c LocalTest1 > LocalTest1.bc


public class LocalTest1 {

    public static void main(String[] args) throws Exception {
        long start = System.currentTimeMillis();
        double test;
        for (double i = 0; i < 1000000000; i++) {
            test = i;
        }
        long finish = System.currentTimeMillis();
        System.out.println("Test1 Took: " + (finish - start) + " msecs");
    }

}

public class LocalTest2 {

    public static void main(String[] args) throws Exception {
        long start = System.currentTimeMillis();
        for (double i = 0; i < 1000000000; i++) {
            double test = i;
        }
        long finish = System.currentTimeMillis();
        System.out.println("Test1 Took: " + (finish - start) + " msecs");
    }
}


Compiled from "LocalTest1.java"
public class LocalTest1 {
  public LocalTest1();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]) throws java.lang.Exception;
    Code:
       0: invokestatic  #2                  // Method java/lang/System.currentTimeMillis:()J
       3: lstore_1
       4: dconst_0
       5: dstore        5
       7: dload         5
       9: ldc2_w        #3                  // double 1.0E9d
      12: dcmpg
      13: ifge          28
      16: dload         5
      18: dstore_3
      19: dload         5
      21: dconst_1
      22: dadd
      23: dstore        5
      25: goto          7
      28: invokestatic  #2                  // Method java/lang/System.currentTimeMillis:()J
      31: lstore        5
      33: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      36: new           #6                  // class java/lang/StringBuilder
      39: dup
      40: invokespecial #7                  // Method java/lang/StringBuilder."<init>":()V
      43: ldc           #8                  // String Test1 Took:
      45: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      48: lload         5
      50: lload_1
      51: lsub
      52: invokevirtual #10                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
      55: ldc           #11                 // String  msecs
      57: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      60: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      63: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      66: return
}


Compiled from "LocalTest2.java"
public class LocalTest2 {
  public LocalTest2();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]) throws java.lang.Exception;
    Code:
       0: invokestatic  #2                  // Method java/lang/System.currentTimeMillis:()J
       3: lstore_1
       4: dconst_0
       5: dstore_3
       6: dload_3
       7: ldc2_w        #3                  // double 1.0E9d
      10: dcmpg
      11: ifge          24
      14: dload_3
      15: dstore        5
      17: dload_3
      18: dconst_1
      19: dadd
      20: dstore_3
      21: goto          6
      24: invokestatic  #2                  // Method java/lang/System.currentTimeMillis:()J
      27: lstore_3
      28: getstatic     #5                  // Field java/lang/System.out:Ljava/io/PrintStream;
      31: new           #6                  // class java/lang/StringBuilder
      34: dup
      35: invokespecial #7                  // Method java/lang/StringBuilder."<init>":()V
      38: ldc           #8                  // String Test1 Took:
      40: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      43: lload_3
      44: lload_1
      45: lsub
      46: invokevirtual #10                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
      49: ldc           #11                 // String  msecs
      51: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      54: invokevirtual #12                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      57: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      60: return
}

উত্তর উত্তর

সমস্ত জেভিএম অপটিমাইজেশনের সাথে পারফরম্যান্সের তুলনা করা সত্যিই সহজ নয়। তবে এটি কিছুটা সম্ভব। গুগল ক্যালিপারে আরও ভাল পরীক্ষা এবং বিস্তারিত ফলাফল

  1. ব্লগে কিছু বিশদ: আপনার কি লুপের ভিতরে বা লুপের আগে পরিবর্তনশীল ঘোষণা করা উচিত?
  2. গিটহাবের সংগ্রহশালা: https://github.com/gunduru/jvdt
  3. ডাবল কেস এবং 100 এম লুপের পরীক্ষার ফলাফল (এবং হ্যাঁ সমস্ত জেভিএম বিবরণ): https://microbenchmark.appspot.com/runs/b1cef8d1-0e2c-4120-be61-a99faff625b4

ঘোষিত হয়েছে 1,759.209 ঘোষিত ইনসাইড 2,242.308

  • ঘোষিত আগে 1,759.209 এনএস
  • ঘোষিত ইনসাইড 2,242.308 এনএস

দ্বিগুণ ঘোষণার জন্য আংশিক পরীক্ষার কোড

এটি উপরের কোডটির মতো নয়। যদি আপনি কেবল একটি ডামি লুপ কোড করেন ਜੇভিএম এড়িয়ে যায়, তাই কমপক্ষে আপনাকে কিছু বরাদ্দ করতে হবে এবং ফিরে আসতে হবে। ক্যালিপার ডকুমেন্টেশনে এটিও সুপারিশ করা হয়।

@Param int size; // Set automatically by framework, provided in the Main
/**
* Variable is declared inside the loop.
*
* @param reps
* @return
*/
public double timeDeclaredInside(int reps) {
    /* Dummy variable needed to workaround smart JVM */
    double dummy = 0;

    /* Test loop */
    for (double i = 0; i <= size; i++) {

        /* Declaration and assignment */
        double test = i;

        /* Dummy assignment to fake JVM */
        if(i == size) {
            dummy = test;
        }
    }
    return dummy;
}

/**
* Variable is declared before the loop.
*
* @param reps
* @return
*/
public double timeDeclaredBefore(int reps) {

    /* Dummy variable needed to workaround smart JVM */
    double dummy = 0;

    /* Actual test variable */
    double test = 0;

    /* Test loop */
    for (double i = 0; i <= size; i++) {

        /* Assignment */
        test = i;

        /* Not actually needed here, but we need consistent performance results */
        if(i == size) {
            dummy = test;
        }
    }
    return dummy;
}

সংক্ষিপ্তসার: ঘোষিতপূর্বগুলি আরও ভাল পারফরম্যান্সকে নির্দেশিত করে - অত্যন্ত ক্ষুদ্র- এবং এটি ক্ষুদ্রতম সুযোগের নীতির বিরুদ্ধে। জেভিএমের আসলে আপনার জন্য এটি করা উচিত


অবৈধ পরীক্ষার পদ্ধতি, এবং আপনি আপনার ফলাফলগুলির কোনও ব্যাখ্যা সরবরাহ করেন না।
লার্নের মারকুইস

1
@ ইজেপি তাদের পক্ষে বিষয়টি সম্পর্কে খুব স্পষ্ট হওয়া উচিত। আরও দরকারী তথ্য সরবরাহের জন্য প্রাইমস্কের উত্তর থেকে পদ্ধতি নেওয়া হয়েছে। সত্যি কথা বলতে কীভাবে এই উত্তরটির উন্নতি করতে হবে আমার কোনও ধারণা নেই, সম্ভবত আপনি সম্পাদনা ক্লিক করতে পারেন এবং কীভাবে এটি সঠিকভাবে করবেন তা আমাদের দেখাতে পারেন?
ওনুর গেন্ডুরু

2
1) জাভা বাইটকোড রানটাইমের সময় অপ্টিমাইজড (পুনরায় সাজানো, ধসে পড়া, ইত্যাদি) হয়ে যায়, তাই খুব বেশি .class ফাইলগুলিতে কী লেখা আছে সে সম্পর্কে চিন্তা করবেন না। ২) ২.৮ এর পারফরম্যান্স জয় অর্জনের জন্য ১,০০০.০০.০০.০০ রান রয়েছে, সুতরাং নিরাপদে এবং যথাযথ প্রোগ্রামিং স্টাইলের তুলনায় রান প্রতি প্রায় 2.8ns থাকে ts আমার পক্ষে স্পষ্ট বিজয়ী। 3) যেহেতু আপনি ওয়ার্মআপ সম্পর্কে কোনও তথ্য সরবরাহ করেন না, তাই আপনার সময়গুলি বেশ অযথা।
হার্ডকডেড

@ হার্ডকোডযুক্ত ভাল পরীক্ষা / মাইক্রো বেঞ্চমার্কিং কেবল ডাবল এবং 100 এম লুপের জন্য ক্যালিপারের সাথে। অনলাইনে ফলাফলগুলি, যদি আপনি চান অন্য ক্ষেত্রে সম্পাদনা করতে নির্দ্বিধায়।
অনুর গেন্ডুরু

ধন্যবাদ, এটি পয়েন্ট 1) এবং 3) সরিয়ে দেয়। তবে সময়টি চক্র প্রতি ~ 5ns পর্যন্ত চলে গেলেও এটি এখনও অবহেলা করার মতো সময়। তত্ত্বের ক্ষেত্রে একটি ছোট্ট অপ্টিমাইজেশনের সম্ভাবনা রয়েছে, বাস্তবে আপনি চক্রের জন্য যে জিনিসগুলি করছেন তা সাধারণত অনেক বেশি ব্যয়বহুল। সুতরাং সম্ভাব্যতা কয়েক মিনিট বা এমনকি কয়েক ঘন্টা চালাতে সর্বাধিক কয়েক সেকেন্ড হবে। উচ্চতর সম্ভাব্য উপলব্ধ (যেমন কাঁটাচাটি / যোগদান, সমান্তরাল স্ট্রিমস) সহ অন্যান্য বিকল্প রয়েছে যা আমি এই ধরণের নিম্ন-স্তরের-অনুকূলিতকরণের জন্য সময় ব্যয় করার আগে যাচাই করতাম।
হার্ডকোড

7

এই সমস্যার একটি সমাধান হ'ল ওয়েল লুপকে এনক্যাপুলেটেড একটি ভেরিয়েবল স্কোপ সরবরাহ করা হতে পারে:

{
  // all tmp loop variables here ....
  // ....
  String str;
  while(condition){
      str = calculateStr();
      .....
  }
}

বাইরের সুযোগটি শেষ হলে এগুলি স্বয়ংক্রিয়ভাবে ডি-রেফারেন্স হবে।



5

যদি আপনার strপরে লুপ (স্কোপ সম্পর্কিত) পরে ব্যবহার করার প্রয়োজন না হয় তবে দ্বিতীয় শর্তটি

  while(condition){
        String str = calculateStr();
        .....
    }

যদি আপনি স্ট্যাকের উপর কোনও বস্তু সংজ্ঞা দেন তবেই যদি conditionতা সত্য হয় better অর্থাৎ আপনার প্রয়োজন হলে এটি ব্যবহার করুন


2
মনে রাখবেন যে প্রথম বৈকল্পিকের মধ্যেও শর্তটি মিথ্যা হলে কোনও অবজেক্ট তৈরি করা হয় না।
ফিলিপ উইন্ডার

@ ফিলিপ: হ্যাঁ আপনি ঠিক বলেছেন। আমার খারাপ। আমি এখনকার মতো ভাবছিলাম ?আপনি কি ভাবেন?
ক্র্যাটিলাস

1
ওয়েল "স্ট্যাকের উপর কোনও বস্তুর সংজ্ঞা দেওয়া" জাভা বিশ্বে কিছুটা অদ্ভুত শব্দ। এছাড়াও, স্ট্যাকের উপর একটি ভেরিয়েবল বরাদ্দ করা সাধারণত রানটাইম এ নূপুর হয়, তবে কেন বিরক্ত করবেন? প্রোগ্রামারকে সহায়তার জন্য স্কোপিং আসল বিষয়টি।
ফিলিপ উইন্ডার 13

3

আমি মনে করি আপনার প্রশ্নের উত্তর দেওয়ার সর্বোত্তম উত্স নিম্নলিখিত পোস্ট হবে:

আগে বা লুপে ভেরিয়েবল ঘোষণার মধ্যে পার্থক্য?

আমার বোঝার মতে এই জিনিসটি ভাষা নির্ভর হবে। আইআইআরসি জাভা এটি অনুকূল করে তোলে, সুতরাং কোনও পার্থক্য নেই, তবে জাভাস্ক্রিপ্ট (উদাহরণস্বরূপ) প্রতিটি বার লুপে পুরো মেমরি বরাদ্দ করবে Java


3

অনেক লোক যেমন উল্লেখ করেছে,

String str;
while(condition){
    str = calculateStr();
    .....
}

এর চেয়ে ভাল নয় :

while(condition){
    String str = calculateStr();
    .....
}

সুতরাং আপনি যদি এটিকে পুনরায় ব্যবহার না করে থাকেন তবে তাদের স্কোপের বাইরে ভেরিয়েবলগুলি ঘোষণা করবেন না ...


1
সম্ভবত এইভাবে বাদে: লিঙ্ক
ডেইনিয়াস ক্রেইভিস

2

ওয়াইল লুপের বাইরে স্ট্রিং স্ট্রিং ঘোষণা করে এটিকে লুপের অভ্যন্তরে এবং বাইরে রেফারেন্স দেওয়া যায়। লুপটির অভ্যন্তরে স্ট্রিং স্ট্রের ঘোষণা দিয়ে এটিকে কেবল লুপের অভ্যন্তরে উল্লেখ করা যায়।


1

চলকগুলি যতটা সম্ভব ব্যবহার করা হয় তার কাছাকাছি হিসাবে ঘোষণা করা উচিত।

এটি আরআইআইআই (রিসোর্স অ্যাকুইজিশন ইজ ইনিশিয়ালাইজেশন) সহজ করে তোলে।

এটি ভেরিয়েবলের সুযোগকে শক্ত করে রাখে। এটি অপ্টিমাইজারটিকে আরও ভালভাবে কাজ করতে দেয়।



1

strপরিবর্তনশীল উপলব্ধ হবে এবং পরে এমনকি যখন কোড নিচে মৃত্যুদন্ড কার্যকর মেমরি কিছু জায়গা সংরক্ষিত হবে।

 String str;
    while(condition){
        str = calculateStr();
        .....
    }

strপরিবর্তনশীল উপলব্ধ হবে না এবং মেমরির প্রকাশ করা হবে, যার জন্য বরাদ্দ ছিল strকোড নিচে মধ্যে পরিবর্তনশীল।

while(condition){
    String str = calculateStr();
    .....
}

আমরা যদি দ্বিতীয়টিকে অনুসরণ করি তবে এটি আমাদের সিস্টেমের স্মৃতিশক্তি হ্রাস করবে এবং কার্য সম্পাদন বাড়িয়ে তুলবে।


0

লুপের ভিতরে ঘোষণা করা স্বতন্ত্র ভেরিয়েবলের সুযোগকে সীমাবদ্ধ করে। এটি সমস্ত পরিবর্তনশীলতার সুযোগের উপর প্রকল্পের প্রয়োজনীয়তার উপর নির্ভর করে।


0

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


-1

এই দুটি উদাহরণ একই জিনিস ফলাফল। যাইহোক, প্রথমটি আপনাকে strযখন লুপটির বাইরে ভেরিয়েবল ব্যবহার করে তা সরবরাহ করে ; দ্বিতীয়টি হয় না।


-1

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

public class Test
{
    private final static int STUFF_SIZE = 512;
    private final static long LOOP = 10000000l;

    private static class Foo
    {
        private long[] bigStuff = new long[STUFF_SIZE];

        public Foo(long value)
        {
            setValue(value);
        }

        public void setValue(long value)
        {
            // Putting value in a random place.
            bigStuff[(int) (value % STUFF_SIZE)] = value;
        }

        public long getValue()
        {
            // Retrieving whatever value.
            return bigStuff[STUFF_SIZE / 2];
        }
    }

    public static long test1()
    {
        long total = 0;

        for (long i = 0; i < LOOP; i++)
        {
            Foo foo = new Foo(i);
            total += foo.getValue();
        }

        return total;
    }

    public static long test2()
    {
        long total = 0;

        Foo foo = new Foo(0);
        for (long i = 0; i < LOOP; i++)
        {
            foo.setValue(i);
            total += foo.getValue();
        }

        return total;
    }

    public static void main(String[] args)
    {
        long start;

        start = System.currentTimeMillis();
        test1();
        System.out.println(System.currentTimeMillis() - start);

        start = System.currentTimeMillis();
        test2();
        System.out.println(System.currentTimeMillis() - start);
    }
}

উপসংহার: স্থানীয় ভেরিয়েবলের আকারের উপর নির্ভর করে এত বড় ভেরিয়েবল না থাকলেও পার্থক্য বিশাল হতে পারে।

কেবল এটি বলা যায় যে কখনও কখনও লুপের বাইরে বা অভ্যন্তরের পক্ষে বিষয়টি গুরুত্বপূর্ণ।


1
অবশ্যই, দ্বিতীয়টি দ্রুত, তবে আপনি বিভিন্ন স্টাফ করছেন: টেস্ট 1 বড় অ্যারে দিয়ে প্রচুর পরিমাণে ফু-অবজেক্ট তৈরি করছে, টেস্ট 2 নেই। টেস্ট 2 একই ফু অবজেক্টটিকে বারবার পুনঃব্যবহার করছে যা মাল্টিথ্রেডেড পরিবেশে বিপজ্জনক হতে পারে।
হার্ডকডেড

বহুতল পরিবেশে বিপজ্জনক ??? কেন দয়া করে ব্যাখ্যা করুন। আমরা একটি স্থানীয় পরিবর্তনশীল সম্পর্কে কথা বলছি। এটি পদ্ধতির প্রতিটি কলে তৈরি করা হয়।
rt15

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

পিএস: আপনার সেটভ্যালু পদ্ধতিটি হওয়া উচিত bigStuff[(int) (value % STUFF_SIZE)] = value;( 2147483649L এর একটি মান চেষ্টা করুন)
হার্ডকোড

পার্শ্ব প্রতিক্রিয়া সম্পর্কে কথা বলা: আপনি কি আপনার পদ্ধতির ফলাফলের তুলনা করেছেন?
হার্ডকোড

-1

আমি মনে করি অবজেক্টের আকারটিও গুরুত্বপূর্ণ। আমার একটি প্রকল্পে, আমরা একটি বৃহত দ্বিমাত্রিক অ্যারে ঘোষণা এবং প্রারম্ভিক করেছিলাম যা অ্যাপ্লিকেশনটিকে মেমোরির একটি ব্যতিক্রম ছুঁড়ে ফেলছে। পরিবর্তে আমরা ঘোষণাকে লুপের বাইরে সরিয়ে নিয়েছি এবং প্রতিটি পুনরাবৃত্তির শুরুতে অ্যারে সাফ করেছি।


-2

NullPointerExceptionআপনার calculateStr()পদ্ধতিটি বাতিল হয়ে যায় এবং তারপরে আপনি স্ট্রেডে কোনও পদ্ধতিতে কল করার চেষ্টা করার ঝুঁকি রয়েছে ।

আরও সাধারণভাবে, নাল মান সহ ভেরিয়েবল থাকা এড়ানো । এটি শ্রেণীর বৈশিষ্ট্যগুলির জন্য আরও শক্তিশালী।


2
এটি কোনওভাবেই প্রশ্নের সাথে সম্পর্কিত নয়। নালপয়েন্টারএক্সসেপশন (ভবিষ্যতের ফাংশন কলগুলিতে) এর সম্ভাবনা কীভাবে কোনও ভেরিয়েবল ঘোষণা করা হয় তার উপর নির্ভর করে না।
মরুভূমির বরফ

1
আমি এটি মনে করি না, কারণ প্রশ্নটি "এটি করার সর্বোত্তম উপায় কী?" Is IMHO আমি একটি নিরাপদ কোড পছন্দ করব।
রুমি ডোলাইগে

1
শূন্যতার ঝুঁকি আছে NullPointerException.যদি এই কোডটি চেষ্টা করে তবে return str;এটি একটি সংকলনের ত্রুটির মুখোমুখি হবে।
লার্নের মারকুইস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.