স্যুইচ করলে কেন দ্রুত হয়


116

প্রচুর জাভা বই switchবিবৃতিটি if elseবিবৃতিটির চেয়ে দ্রুত বলে বর্ণনা করে । স্যুইচ করা যদি তার চেয়ে দ্রুত হয় তবে আমি কোথাও খুঁজে পাইনি ।

উদাহরণ

আমার এমন পরিস্থিতি আছে যে দুটিয়ের মধ্যে যে কোনও একটি আইটেম আমাকে বেছে নিতে হবে। আমি হয় ব্যবহার করতে পারেন

switch (item) {
    case BREAD:
        //eat Bread
        break;
    default:
        //leave the restaurant
}

অথবা

if (item == BREAD) {
    //eat Bread
} else {
    //leave the restaurant
}

আইটেম এবং BREAD বিবেচনা করা একটি ধ্রুবক মান হয়।

উপরের উদাহরণে কোনটি দ্রুততর এবং কেন?


জাভা এর জন্য এটিও একটি উত্তর হতে পারে: স্ট্যাকওভারফ্লো.com
টোবিয়াস

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

এই প্রশ্নের শীর্ষের উত্তর এটি বেশ ভাল ব্যাখ্যা করে। এই নিবন্ধটি খুব ভাল সবকিছু ব্যাখ্যা করে।
বেজম্যাক্স

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

2
আপনার কাছে এমন বই থেকে সাবধান হওয়া উচিত যা ব্যাখ্যা / প্রমাণ / যুক্তি ছাড়াই এ জাতীয় বিবৃতি দেয়।
ম্যাট বি

উত্তর:


110

কারণ এমন অনেকগুলি বিশেষ বাইকোড রয়েছে যা যখন প্রচুর ক্ষেত্রে হয় তখন দক্ষ স্যুইচ স্টেটমেন্ট মূল্যায়নের অনুমতি দেয়।

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


6
"চেক, জাম্প" এ অনুবাদ কি পুনরুক্তি হয় না?
ফাইভটভেটিসিক্স

17
@ ফাইভটভেটিসিক্স: না, তথ্যের জন্য এটি উল্লেখ করুন: artima.com/underhehe//PP.html । নিবন্ধ থেকে উদ্ধৃতি: যখন জেভিএম কোনও টেবিলসুইচ নির্দেশের মুখোমুখি হয়, তখন কীটি নিম্ন এবং উচ্চ দ্বারা সংজ্ঞায়িত সীমার মধ্যে রয়েছে কিনা তা খালি পরীক্ষা করতে পারে। যদি তা না হয় তবে এটি অফসেটের ডিফল্ট শাখা নেয়। যদি তা হয় তবে এটি শাখা অফসেটের তালিকায় অফসেট পেতে কী থেকে কম বিয়োগ করে। এই পদ্ধতিতে, এটি প্রতিটি কেস এর মান পরীক্ষা না করেই উপযুক্ত শাখা অফসেট নির্ধারণ করতে পারে।
বেজম্যাক্স

1
(i) ক switchএকটি tableswitchবাইটোকোড নির্দেশে অনুবাদ করা যায় না - এটি এমন নির্দেশ হতে পারে lookupswitchযা যদি / অন্যথায় অনুরূপভাবে সঞ্চালিত হয় (ii) এমনকি tableswitchবাইটকোড নির্দেশাবলী যদি / অন্যটি জেআইটি কর্তৃক একটি সিরিজে সংকলিত হতে পারে, কারণগুলির উপর নির্ভর করে যেমন এর সংখ্যা case
Assylias


34

একটি switchবিবৃতি সবসময় একটি ifবিবৃতি চেয়ে দ্রুত হয় না । এটি if-elseবিবৃতিগুলির দীর্ঘ তালিকার চেয়ে আরও ভাল স্কেল switchকরে যা সমস্ত মানগুলির উপর ভিত্তি করে একটি অনুসন্ধান করতে পারে। তবে, একটি সংক্ষিপ্ত শর্তের জন্য এটি আর দ্রুত হবে না এবং ধীর হতে পারে।


5
"দীর্ঘ" সীমাবদ্ধ করুন। 5 এর চেয়েও বড়? 10 এর চেয়েও বড়? বা আরও 20 - 30 মত?
ভ্যান্ডারওয়াইস্ট

11
আমার সন্দেহ হয় এটি নির্ভর করে। আমার জন্য এটির 3 বা ততোধিক প্রস্তাবগুলি switchদ্রুত না হলে আরও পরিষ্কার হবে।
পিটার লরে

কোন পরিস্থিতিতে এটি ধীর হতে পারে?
এরিক

1
@ এরিক এটি খুব কম সংখ্যক মানগুলির জন্য ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে পড়েছে ring
পিটার ল্যারি

8

বর্তমান জেভিএমের দুটি ধরণের সুইচ বাইট কোড রয়েছে: লুকআপসুইচ এবং টেবিলসুইচ।

একটি স্যুইচ স্টেটমেন্টের প্রতিটি ক্ষেত্রে একটি পূর্ণসংখ্যা অফসেট থাকে, যদি এই অফসেটগুলি সামঞ্জস্যপূর্ণ হয় (বা বেশিরভাগ বড় ফাঁক ছাড়াই বেশিরভাগ স্থানে থাকে) (কেস 0: কেস 1: কেস 2, ইত্যাদি), তবে টেবিলসুইচ ব্যবহার করা হবে।

যদি অফসেটগুলি বড় ফাঁক দিয়ে ছড়িয়ে পড়ে (কেস 0: কেস 400: কেস 93748 :, ইত্যাদি), তবে লুকআপসুইচ ব্যবহৃত হয়।

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

সঠিক কোড শাখার সন্ধান করতে লুকআপ সুইচ একটি বাইনারি অনুসন্ধান ব্যবহার করে। এটি ও (লগ এন) সময়ে চলে যা এখনও ভাল তবে সেরা নয়।

এ সম্পর্কিত আরও তথ্যের জন্য, এখানে দেখুন: জেভিএমের লুকআপসুইচ এবং টেবিল সুইচ এর মধ্যে পার্থক্য?

এখন পর্যন্ত কোনটি দ্রুততম, এই পদ্ধতির ব্যবহার করুন: আপনার যদি 3 বা ততোধিক ঘটনা ঘটে থাকে যার মান ক্রমাগত বা প্রায় একটানা, সর্বদা একটি স্যুইচ ব্যবহার করুন।

আপনার যদি 2 টি মামলা থাকে তবে একটি বিবৃতি ব্যবহার করুন।

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

এছাড়াও, মনে রাখবেন যে জেভিএম জেআইটি অপ্টিমাইজেশানগুলি চালাবে যদি বিবৃতিগুলি কোডের মধ্যে হটেস্ট শাখাটিকে প্রথমে রাখার চেষ্টা করবে। একে বলা হয় "ব্রাঞ্চ প্রেডিকশন"। এটি সম্পর্কে আরও তথ্যের জন্য, এখানে দেখুন: https://dzone.com/articles/branch-prediction-in-java

আপনার অভিজ্ঞতা বিভিন্ন হতে পারে। আমি জানি না যে জেভিএম লুকআপসুইচটিতে অনুরূপ অপটিমাইজেশন চালায় না, তবে আমি জেআইটি অপ্টিমাইজেশানগুলিতে বিশ্বাস রাখতে শিখেছি এবং সংকলককে আউটস্মার্ট করার চেষ্টা করব না।


1
এটি পোস্ট করার পরে, এটি আমার নজরে এসেছে যে "সুইচ এক্সপ্রেশন" এবং "প্যাটার্ন ম্যাচিং" জাভাতে আসবে, সম্ভবত জাভা 12 এর সাথে সাথেই d কিছুই এখনও কংক্রিট নয়, তবে দেখা যাচ্ছে যে এগুলি switchআরও শক্তিশালী ভাষার বৈশিষ্ট্য তৈরি করবে। প্যাটার্ন মিল, উদাহরণস্বরূপ, অনেক মসৃণ এবং পারফরম্যান্ট instanceofলুকআপের জন্য অনুমতি দেয় । যাইহোক, আমি মনে করি এটি বেসিক স্যুইচ / যদি পরিস্থিতিগুলির জন্য, আমি যে নিয়মটি উল্লেখ করেছি এখনও কার্যকর হবে তা ধরে নেওয়া নিরাপদ।
HesNotTheStig

1

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

নীচের ফলাফলটি পেতে আপনার প্রয়োজন বিমূর্ততা .. আমি কীভাবে এটি কাজ করে তা ব্যাখ্যা করতে যাচ্ছি না আশা করি আপনার এটির একটি ধারণা রয়েছে।

প্যাকেটের আকার 255 এ সেট করতে আমি এটি আপডেট করেছি আপনার যদি আরও বেশি প্রয়োজন হয় তবে আপনাকে (আইডি <0) এর জন্য বাউন্ডস চেক করতে হবে || (আইডি> দৈর্ঘ্য)।

Packets[] packets = new Packets[255];

static {
     packets[0] = new Login(6);
     packets[2] = new Logout(8);
     packets[4] = new GetMessage(1);
     packets[8] = new AddFriend(0);
     packets[11] = new JoinGroupChat(7); // etc... not going to finish.
}

public void handlePacket(IncomingData data)
{
    int id = data.readByte() & 0xFF; //Secure value to 0-255.

    if (packet[id] == null)
        return; //Leave if packet is unhandled.

    packets[id].execute(data);
}

আমি সি ++ তে প্রচুর জাম্প টেবিল ব্যবহার করার পরে সম্পাদনা করুন এখন আমি কোনও ফাংশন পয়েন্টার জাম্প টেবিলের উদাহরণ দেখাব। এটি খুব সাধারণ উদাহরণ, তবে আমি এটি চালিয়েছি এবং এটি সঠিকভাবে কাজ করে। মনে রাখবেন আপনাকে অবশ্যই NULL তে পয়েন্টার সেট করতে হবে, সি ++ জাভাতে স্বয়ংক্রিয়ভাবে এটি করবে না।

#include <iostream>

struct Packet
{
    void(*execute)() = NULL;
};

Packet incoming_packet[255];
uint8_t test_value = 0;

void A() 
{ 
    std::cout << "I'm the 1st test.\n";
}

void B() 
{ 
    std::cout << "I'm the 2nd test.\n";
}

void Empty() 
{ 

}

void Update()
{
    if (incoming_packet[test_value].execute == NULL)
        return;

    incoming_packet[test_value].execute();
}

void InitializePackets()
{
    incoming_packet[0].execute = A;
    incoming_packet[2].execute = B;
    incoming_packet[6].execute = A;
    incoming_packet[9].execute = Empty;
}

int main()
{
    InitializePackets();

    for (int i = 0; i < 512; ++i)
    {
        Update();
        ++test_value;
    }
    system("pause");
    return 0;
}

এছাড়াও আরেকটি বিষয় যা আমি তুলে ধরতে চাই তা হ'ল বিখ্যাত বিভাজন এবং বিজয়। সুতরাং আমার উপরের 255 অ্যারের ধারণাটি 8 এর পরে আর কমানো যাবে 8 যদি বিবৃতি সবচেয়ে খারাপ পরিস্থিতি হিসাবে হয়।

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

If (Value >= 128)
{
   if (Value >= 192)
   {
        if (Value >= 224)
        {
             if (Value >= 240)
             {
                  if (Value >= 248)
                  {
                      if (Value >= 252)
                      {
                          if (Value >= 254)
                          {
                              if (value == 255)
                              {

                              } else {

                              }
                          }
                      }
                  }
             }      
        }
   }
}

2
ডাবল ইন্ডিয়ারেশন কেন? যেহেতু আইডি অবশ্যই যাই হোক না কেন, কেবল আসন্ন আইডিটিকে বাউন্ড-চেক না করে 0 <= id < packets.lengthনিশ্চিত করুন packets[id]!=nullএবং তারপরে কী করবেন packets[id].execute(data)?
লরেন্স ডল

হ্যাঁ দেরি করে দেওয়া প্রতিক্রিয়ার জন্য আবার এটির দিকে নজর রেখেছিল .. এবং আমি কী ভাবছিলাম তা আমি বুঝতে পারছি না আমি কী পোস্টটি আপডেট করে আপডেট করেছি এবং প্যাকেটগুলিকে স্বাক্ষরবিহীন বাইট আকারে ক্যাপড করেছিলাম যাতে দৈর্ঘ্যের চেক প্রয়োজন হয় না।
জেরেমি ত্রিফিলো

0

বাইটকোড স্তরে, সাবজেক্ট ভেরিয়েবল রানটাইম দ্বারা লোড হওয়া কাঠামোগত। ক্লাস ফাইলটিতে মেমরি ঠিকানা থেকে কেবল একবার প্রসেসরের রেজিস্ট্রারে লোড করা হয় এবং এটি একটি স্যুইচ বিবৃতিতে রয়েছে; যদিও একটি if-বিবৃতিতে, আপনার কোড-সংকলন ডিই দ্বারা একটি পৃথক jvm নির্দেশ তৈরি করা হয়, এবং এর জন্য প্রতিটি ভেরিয়েবলটি রেজিস্টারগুলিতে লোড করা আবশ্যক যদিও পরবর্তী চলন চলতি if-বিবৃতি হিসাবে ব্যবহৃত হয়। যদি আপনি সমাবেশের ভাষায় কোডিংয়ের কথা জানেন তবে এটি সাধারণ বিষয় হবে; যদিও জাভা সংকলিত কক্সেস বাইটোকড বা সরাসরি মেশিন কোড নয়, তবে শর্তাধীন ধারণাটি এখনও সুসংগত। ঠিক আছে, আমি ব্যাখ্যা করার পরে গভীর প্রযুক্তিগততা এড়াতে চেষ্টা করেছি। আমি আশা করি আমি ধারণাটি পরিষ্কার এবং অচল করে দিয়েছি। ধন্যবাদ.

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.