কোন "যদি" নির্মাণটি দ্রুত - বিবৃতি বা টেরিনারি অপারেটর?


83

সেখানে দুই ধরনের হয় if: সর্বোত্তম - জাভা বিবৃতি if {} else {}এবং সাধারণভাবে সংক্ষেপে: exp ? value1 : value2। একজনের চেয়ে অন্যের চেয়ে দ্রুত বা সেগুলি কি একই রকম?

বিবৃতি:

int x;
if (expression) {
  x = 1;
} else {
  x = 2;
}

টেরিনারি অপারেটর:

int x = (expression) ? 1 : 2;

34
আমি অনুমান করছি একেবারে কোনও পার্থক্য নেই। এটা ঠিক বাক্য গঠন। যদি না কম্পাইলার কিছুটা মন্দ (বা অন্য কিছু) এবং আমি ভুল
sinelaw

4
আপনি (মাইক্রো) এটি মানদণ্ড করেছেন? ফলাফল ভাগ করুন।
BalusC

4
উভয়ই jit'ed পাবেন। কিছুতেই কোনও তফাত থাকবে না। এবং জিনিসগুলি পচে যাওয়ার বিরক্ত করবেন না। হটস্পট যা প্রথম কাজ করে তা হ'ল জাভ্যাক দ্বারা প্রয়োগ করা সমস্ত অপটিমাইজেশন গ্রহণ করা ।
আইভো ওয়েটজেল

11
বিভিন্ন গতির জন্য এগুলি বিদ্যমান নেই। তারা বিভিন্ন উদ্দেশ্যে বিদ্যমান। আমি নিশ্চিত আপনি বিবৃতি এবং প্রকাশের মধ্যে পার্থক্য বুঝতে পেরেছি। বিবৃতি ক্রিয়া সম্পাদন করে। এক্সপ্রেশন মান তৈরি করে। ifবিবৃতিতে ব্যবহারের জন্য। ?এক্সপ্রেশন ব্যবহারের জন্য।
মাইক ডুনলাভে

4
এই প্রশ্নের প্রতিক্রিয়া হিসাবে +1 পড়ার মতো হলেও মূল প্রশ্নের অভিপ্রায়টি ভুল-নির্দেশিত।
জবল

উত্তর:


106

সেখানে কেবল "এক প্রকার" বিবৃতি আছে। অন্যটি শর্তাধীন অভিব্যক্তি। কোনটি আরও ভাল পারফরম্যান্স করবে: তারা একই বাইটোকোডে সংকলন করতে পারে এবং আমি তাদের অনুরূপ আচরণ করার প্রত্যাশা করব - বা এতটা কাছাকাছি যে আপনি অবশ্যই পারফরম্যান্সের দিক থেকে অন্যটির চেয়ে একটি বেছে নিতে চান না।

কখনও কখনও একটি ifবিবৃতি আরও পঠনযোগ্য হবে, কখনও কখনও শর্তসাপেক্ষ অপারেটর আরও পঠনযোগ্য হবে। বিশেষত, আমি যখন দুটি অপারেশনগুলি সহজ এবং পার্শ্ব-প্রতিক্রিয়ামুক্ত শর্তসাপেক্ষ অপারেটরটি ব্যবহার করার পরামর্শ দেব, যখন দুটি শাখার মূল উদ্দেশ্য যদি তাদের পার্শ্ব প্রতিক্রিয়া হয় তবে আমি সম্ভবত একটি ifবিবৃতি ব্যবহার করব ।

এখানে একটি নমুনা প্রোগ্রাম এবং বাইটকোড:

public class Test {
    public static void main(String[] args) {
        int x;
        if (args.length > 0) {
            x = 1;
        } else {
            x = 2;
        }
    }

    public static void main2(String[] args) {
        int x = (args.length > 0) ? 1 : 2;
    }
}

বাইটকোড এর সাথে পচে গেছে javap -c Test:

public class Test extends java.lang.Object {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1
       4: return

  public static void main(java.lang.String[]
    Code:
       0: aload_0
       1: arraylength
       2: ifle          10
       5: iconst_1
       6: istore_1
       7: goto          12
      10: iconst_2
      11: istore_1
      12: return

  public static void main2(java.lang.String[
    Code:
       0: aload_0
       1: arraylength
       2: ifle          9
       5: iconst_1
       6: goto          10
       9: iconst_2
      10: istore_1
      11: return
}

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


এস / শর্তসাপেক্ষ বিবৃতি / শর্তসাপেক্ষ অভিব্যক্তি /
লরেন্স গনসাল্ভেস

4
আমি অনুমান করছি আপনি উভয়ের জন্যই বোঝেন নি mainএবং main2ঠিক একইরকম হতে চান?
কলিনড

চিত্তাকর্ষক আমি জানতাম না আপনি এখন পর্যন্ত বাইট কোডটি সংকলন করতে পারেন।
কাইল

4
@ কাইল: আমি জাভাটি সংকলন করেছি, তারপরে জাভাপের সাথে সংশ্লেষ করেছি।
জন স্কিটে

4
@ কাইল: হুবহু আমি বেশিরভাগই বাইকোডটি অভিন্ন হওয়ার আশা করতাম । যেমনটি হ'ল, এটি প্রায় অভিন্ন ) :)
জন স্কিটি

10

আপনার উভয় উদাহরণই সম্ভবত অভিন্ন বা প্রায় অভিন্ন বাইকোডের সাথে সংকলন করবে, সুতরাং পারফরম্যান্সে কোনও পার্থক্য থাকতে হবে না।

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


8

এগুলি একই রকম। উভয়ই মোটামুটি দ্রুত, প্রায় 10-30 ন্যানো-সেকেন্ডের কাছাকাছি। (ব্যবহারের ধরণের উপর নির্ভর করে) এই সময় ফ্রেমটি কি আপনার পক্ষে গুরুত্বপূর্ণ?

আপনি যা বিশ্বাস করেন তা পরিষ্কার করা উচিত।


4

কেবলমাত্র অন্য সমস্ত উত্তর যুক্ত করতে:

দ্বিতীয় প্রকাশটি প্রায়শই তৃতীয় / টেরিনারি অপারেটর / বিবৃতি বলে। এটি খুব কার্যকর হতে পারে কারণ এটি একটি অভিব্যক্তি ফেরায়। কখনও কখনও এটি আদর্শ সংক্ষিপ্ত বিবৃতিগুলির জন্য কোডটিকে আরও স্পষ্ট করে তোলে।


4
বাস্তবে এর দুর্দান্ত উদাহরণ: জাভাতে, যদি আমাকে কোনও এক্সপ্রেশনের ফলাফলের উপর ভিত্তি করে স্ট্রিং ফাইনাল করতে হয়, তবে আমি টেরিনারি সিনট্যাক্স ফাইনাল স্ট্রিংটি ব্যবহার করতে পারি যা টেবিল = (পূর্ণসংখ্যা.পারসেন্ট (ক্লায়েন্টআইডি)> 500)? "সার্ভারক্লিয়েন্টস": "অফলাইনক্লায়েন্টস"; তারপরে আমি সেই জায়গাগুলিতে অভিব্যক্তির মানটি ব্যবহার করতে পারি যেখানে টেবিলটি চূড়ান্ত হওয়া দরকার। নিম্নলিখিতটি অবৈধ হবে: চূড়ান্ত স্ট্রিং যা টেবিল = ""; if (Integer.parseInt (clientId)> 500)) whichTable = "serverClients"; } অন্য {যা টেবিল = "অফলাইনক্লায়েন্টস"; }
জেমস পেরিহ

@ জামেসপিরিহ কোনও finalক্ষেত্রের ক্ষেত্রে, আপনি মান নির্ধারণ করতে কনস্ট্রাক্টর ব্লক ব্যবহার করতে পারেন (যদিও শর্তসাপেক্ষ অপারেটরটি বিলিয়ন গুন বেশি ভাল আইএমও দেখায়) এবং স্থানীয় ভেরিয়েবলের সাহায্যে আপনি কোডটিকে প্রথমে ব্যবহারের আগে একটি মান নির্ধারণ করতে পারেন আমি ভিতরে এসেছি I কল করার সময় আমার মনে হয় কেবলমাত্র একটি ক্ষেত্রে যখন কোনও তিন্নি কোনও সুবিধা দিতে পারে if-elseissuper(...)this(...) ভিতরে কোনও নির্মাণকারীর বা তার অভ্যন্তরে
ক্রু


0

টার্নারি অপারেটর যদি অন্য অবস্থার চেয়ে দ্রুত হয়।

public class TerinaryTest {
    public static void main(String[] args)
    {
        int j = 2,i = 0;
        Date d1 = new Date();
        for(long l=1;l<100000000;l++)
            if(i==1) j=1;
                else j=0;
        Date d2 = new Date();
        for(long l=1;l<100000000;l++)
            j=i==1?1:0;
        Date d3 = new Date();
        System.out.println("Time for if-else: " + (d2.getTime()-d1.getTime()));
        System.out.println("Time for ternary: " + (d3.getTime()-d2.getTime()));
    }
}

পরীক্ষার ফলাফল:

ট্রেইল -১:

অন্যথায়: 63

ত্রিনিয়ার সময়: 31

ট্রেইল -২:

অন্যথায়: 78

ত্রিনিয়ার সময়: 47

ট্রেইল -৩:

অন্যথায় সময়: 94

ত্রিনিয়ার সময়: 31

ট্রেইল -4:

অন্যথায়: 78

ত্রিনিয়ার সময়: 47


আপনার উদাহরণটি চালানোর সময় আমার ঠিক বিপরীত ফলাফল ছিল, যা দেখায় যে ফলাফলগুলি অবিশ্বস্ত। দুর্ভাগ্যক্রমে আপনি মাইক্রোবেঞ্চমার্কিংয়ের ফাঁদে পড়ে যাচ্ছেন - সঠিকভাবে মাইক্রোবেঞ্চমার্কগুলি করা কুখ্যাতভাবে কঠিন। : একটি দম্পতি উদাহরণের জন্য আপনি এখানে দেখতে পারেন stackoverflow.com/questions/2842695/what-is-microbenchmarking
Rogach

আপনার বিশেষ উদাহরণটি কমপক্ষে এই সমস্যাগুলির সাথে ভুগছে: 4 টি ট্রায়াল পর্যাপ্ত নয়, আপনি সর্বদা একই ক্রমে পরীক্ষা চালান (প্রথম যদি-অন্যথায়, দ্বিতীয় তৃতীয়), আপনি পরীক্ষা চালানোর আগে জেভিএমকে ওয়ার্ম আপ করেন না, ইত্যাদি etc.
রোগাচ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.