আমি ইতিমধ্যে এই চমত্কার উত্তরের মধ্যে এখানে ঝাঁপিয়ে পড়তে চেয়েছিলাম এবং স্বীকার করতে পেরেছি যে আমি পলিমারফিক কোড পরিবর্তনের বিরোধী প্যাটার্নে switches
বা if/else
পরিমাপযুক্ত লাভের সাথে শাখার পিছনে পিছনে কাজ করার কুৎসিত পদ্ধতি গ্রহণ করেছি taken তবে আমি এই পাইকারিটি করিনি, কেবলমাত্র সবচেয়ে জটিল পথে। এটি এত কালো এবং সাদা হতে হবে না।
অস্বীকৃতি হিসাবে, আমি রেয়েট্রাকিংয়ের মতো অঞ্চলে কাজ করি যেখানে যথার্থতা অর্জন করা এতটা কঠিন নয় (এবং প্রায়শই ঝাপসা এবং প্রায় হয়) তবে গতি প্রায়শই সর্বাধিক প্রতিযোগিতামূলক গুণাবলীর সন্ধান করা হয়। রেন্ডার বার হ্রাস হ'ল প্রায়শই সাধারণ ব্যবহারকারীর অনুরোধগুলির মধ্যে একটি হ'ল আমাদের ক্রমাগত আমাদের মাথা চুলকানো এবং কীভাবে সবচেয়ে গুরুত্বপূর্ণ পরিমাপযোগ্য পথগুলির জন্য এটি অর্জন করা যায় তা নির্ধারণ করা।
শর্তগুলির বহুমুখী রিফ্যাক্টরিং
প্রথমত, শর্তসাপেক্ষ শাখা ( switch
বা if/else
বিবৃতিতে একগুচ্ছ ) এর চেয়ে বহনযোগ্যতার দিক থেকে পলিমারফিজম কেন ভাল can এখানে প্রধান সুবিধা হ'ল এক্সটেনসিবিলিটি ।
পলিমারফিক কোড সহ, আমরা আমাদের কোডবেসে একটি নতুন উপ-প্রকার প্রবর্তন করতে পারি, এটির বহু উদাহরণস্বরূপ ডেটা স্ট্রাকচারে এটির উদাহরণ যোগ করতে পারি এবং বিদ্যমান সমস্ত পলিমারফিক কোড এখনও কোনও পরিবর্তন ছাড়াই স্বয়ংক্রিয়ভাবে কাজ করতে পারে। আপনার যদি এমন একটি বৃহত কোডবেজ জুড়ে কোডের একগুচ্ছ ছড়িয়ে ছিটিয়ে থাকে যা এই রূপটির অনুরূপ, "যদি এই ধরণের 'foo' হয় তবে তা করুন" , আপনি নিজেকে পরিচয় করানোর জন্য কোডের 50 টি পৃথক বিভাগ আপডেট করার একটি ভয়াবহ বোঝা পেয়ে যেতে পারেন might একটি নতুন ধরণের জিনিস, এবং এখনও কিছু হারিয়ে যাওয়া শেষ।
পলিমারফিজমের রক্ষণাবেক্ষণের সুবিধাগুলি স্বাভাবিকভাবেই এখানে হ্রাস পায় যদি আপনার কাছে কেবল আপনার কোডবেসের একটি দম্পতি বা এমন একটি বিভাগ রয়েছে যা এই ধরণের চেক করতে হয়।
অপ্টিমাইজেশন বাধা
আমি এটিকে এত শাখা এবং পাইপলাইনের দৃষ্টিকোণ থেকে না দেখার পরামর্শ দিচ্ছি, এবং এটি অপ্টিমাইজেশন বাধাগুলির সংকলক নকশার মানসিকতা থেকে আরও তাকান। উভয় ক্ষেত্রে প্রযোজ্য শাখার পূর্বাভাস উন্নত করার উপায় রয়েছে যেমন সাব-টাইপের উপর ভিত্তি করে ডেটা বাছাই করা (যদি এটি কোনও ক্রম অনুসারে ফিট করে)।
এই দুটি কৌশলগুলির মধ্যে যেটির চেয়ে বেশি পার্থক্য রয়েছে তা হ'ল অপটিমাইজারের আগাম পরিমাণ পরিমাণ তথ্যের পরিমাণ। পরিচিত একটি ফাংশন কল অনেক বেশি তথ্য সরবরাহ করে, একটি পরোক্ষ ফাংশন কল যা সংকলন সময়ে অজানা ফাংশনটিকে কল করে একটি অপ্টিমাইজেশন বাধা দেয়।
যখন ফাংশনটি ডাকা হচ্ছে তা জানা যায়, সংকলকরা কাঠামোটি বিলুপ্ত করতে পারে এবং স্কেথারেন, ইনলাইনিং কলগুলি, সম্ভাব্য আলিয়াসিং ওভারহেড নির্মূল করে, নির্দেশ / রেজিস্টার বরাদ্দে আরও ভাল কাজ করে, সম্ভবত লুপগুলি এবং অন্যান্য শাখাগুলি পুনর্বিন্যাস করে, শক্ত তৈরি করে যখন উপযুক্ত হবে কোড-ক্ষুদ্রাকরণ LUTs (কিছু কিছু জিসিসি 5.3 সম্প্রতি switch
একটি লাফ টেবিলের পরিবর্তে ফলাফলের জন্য হার্ড-কোডড লুট ব্যবহার করে একটি বিবৃতি দিয়ে আমাকে অবাক করেছে )।
অপ্রত্যক্ষ ফাংশন কলের ক্ষেত্রে যেমন আমরা মিশ্রণে সংকলন-কালীন অজানা পরিচয় করিয়ে দেওয়া শুরু করি তখন সেগুলির কিছুটি হ্রাস পায় এবং শর্তসাপেক্ষ শাখাগুলি সম্ভবত একটি প্রান্ত প্রস্তাব করতে পারে।
মেমরি অপটিমাইজেশন
একটি ভিডিও গেমের উদাহরণ নিন যা বারবার শক্ত লুপে প্রাণীর ক্রম প্রক্রিয়াজাত করে। এই জাতীয় ক্ষেত্রে, আমাদের কিছু পলিমারফিক পাত্রে থাকতে পারে:
vector<Creature*> creatures;
দ্রষ্টব্য: সরলতার জন্য আমি unique_ptr
এখানে এড়ানো হয়েছে।
... Creature
পলিমারফিক বেসের ধরণটি কোথায় । এক্ষেত্রে পলিমারফিক পাত্রে একটি অসুবিধা হ'ল তারা প্রায়শই প্রতিটি উপ-টাইপের জন্য আলাদাভাবে / স্বতন্ত্রভাবে মেমরি বরাদ্দ করতে চান (উদা: operator new
প্রতিটি পৃথক প্রাণীর জন্য ডিফল্ট নিক্ষেপ ব্যবহার করে)।
এটি প্রায়শই শাখাগুলি না করে অপ্টিমাইজেশনের (আমাদের এটির প্রয়োজন হওয়া উচিত) মেমরি-ভিত্তিক প্রথম অগ্রাধিকার তৈরি করবে। এখানে একটি কৌশল হ'ল প্রতিটি উপ-প্রকারের জন্য একটি নির্দিষ্ট বরাদ্দকারীকে ব্যবহার করা, বড় অংশগুলিতে বরাদ্দ করে প্রতিটি উপ-প্রকারের জন্য বরাদ্দকরণের জন্য মেমরি পুলিং করে একটি স্বতন্ত্র প্রতিনিধিত্বকে উত্সাহিত করা। এই জাতীয় কৌশল দ্বারা এটি অবশ্যই এই creatures
ধারকটিকে সাব-টাইপ (পাশাপাশি ঠিকানা) অনুসারে বাছাই করতে সহায়তা করতে পারে , কারণ এটি কেবল শাখার পূর্বাভাসই উন্নত করতে পারে না তবে রেফারেন্সের স্থানীয়তাও উন্নত করে (একই সাব-টাইপের একাধিক প্রাণীকে অ্যাক্সেস করার অনুমতি দেয়) উচ্ছেদের আগে একক ক্যাশে লাইন থেকে)।
ডেটা স্ট্রাকচার এবং লুপগুলির আংশিক ডেভर्चুয়ালাইজেশন
ধরা যাক আপনি এই সমস্ত গতি পেরিয়ে গেছেন এবং আপনি এখনও আরও গতি অর্জন করতে চান। এখানে লক্ষণীয় যে আমরা এখানে প্রতিটি পদক্ষেপটি রক্ষণাবেক্ষণকে হ্রাস করে চলেছে এবং আমরা ইতিমধ্যে হ্রাসমান পারফরম্যান্সের রিটার্ন সহ কিছুটা ধাতব নাকাল পর্যায়ে এসেছি। সুতরাং আমরা যদি এই অঞ্চলটিতে চলে যাই তবে একটি দুর্দান্ত তাৎপর্যপূর্ণ পারফরম্যান্স চাহিদা থাকা দরকার, যেখানে আমরা আরও ছোট এবং ছোট পারফরম্যান্স লাভের জন্য রক্ষণাবেক্ষণের ত্যাগ করতে ইচ্ছুক।
তবুও পরবর্তী পদক্ষেপটি (এবং সর্বদা আমাদের পরিবর্তনগুলি ব্যাক করার ইচ্ছুকতার সাথে এটি যদি কিছু না দেয় তবে) ম্যানুয়াল ডেভ্যাচুয়ালাইজেশন হতে পারে।
সংস্করণ নিয়ন্ত্রণের টিপ: আপনি আমার চেয়ে আরও বেশি অপ্টিমাইজেশন-বুদ্ধি না হলে, আমাদের অপ্টিমাইজেশানের প্রচেষ্টাটি খুব ভালভাবে ঘটতে পারে তবে তা ছুঁড়ে ফেলার ইচ্ছায় এই মুহুর্তে একটি নতুন শাখা তৈরি করা উপযুক্ত। আমার কাছে এটি সমস্ত পরীক্ষার এবং ত্রুটিযুক্ত এই ধরণের পয়েন্টগুলির পরেও একজন প্রোফাইলার হাতে রেখে।
তবুও, আমাদের এই মানসিকতাটি পাইকারিভাবে প্রয়োগ করতে হবে না। আমাদের উদাহরণ অব্যাহত রেখে বলা যাক এই ভিডিও গেমটি বেশিরভাগ ক্ষেত্রেই মানব প্রাণীকে নিয়ে গঠিত। এরকম ক্ষেত্রে, আমরা কেবলমাত্র মানব জীবকে তাদের উত্তোলন করে এবং কেবল তাদের জন্য একটি পৃথক ডেটা কাঠামো তৈরি করে irtশ্বর্যচালিত করতে পারি।
vector<Human> humans; // common case
vector<Creature*> other_creatures; // additional rare-case creatures
এর দ্বারা বোঝা যায় যে আমাদের কোডবেসের সমস্ত অঞ্চল যা জীবকে প্রক্রিয়া করা প্রয়োজন মানবদেহের জন্য পৃথক বিশেষ-ক্ষেত্রে লুপের প্রয়োজন। তবুও এটি মানুষের পক্ষে গতিশীল প্রেরণের ওভারহেড (বা সম্ভবত আরও উপযুক্তভাবে, অনুকূলিতকরণ বাধা) সরিয়ে দেয় যা এখন পর্যন্ত সবচেয়ে সাধারণ প্রাণী ধরণের। যদি এই অঞ্চলগুলি সংখ্যায় বড় হয় এবং আমরা এটির সামর্থ্য রাখি তবে আমরা এটি করতে পারি:
vector<Human> humans; // common case
vector<Creature*> other_creatures; // additional rare-case creatures
vector<Creature*> creatures; // contains humans and other creatures
... যদি আমরা এটি সামর্থ্য করি তবে কম সমালোচনামূলক পথগুলি যেমন রয়েছে তেমন থাকতে পারে এবং সমস্ত প্রাণী প্রকারের বিমূর্তভাবে প্রক্রিয়াজাত করে। সমালোচনামূলক পাথগুলি humans
একটি লুপ এবং other_creatures
দ্বিতীয় লুপে প্রক্রিয়া করতে পারে ।
আমরা প্রয়োজন হিসাবে এই কৌশলটি প্রসারিত করতে পারি এবং সম্ভাব্যভাবে কিছু উপায়ে এইভাবে পিষতে পারি, তবুও এটি প্রক্রিয়াতে আমরা রক্ষণাবেক্ষণযোগ্যতা কতটা হ্রাস করছি তা লক্ষ করার মতো worth এখানে ফাংশন টেমপ্লেটগুলি ব্যবহার করে ম্যানুয়ালি যুক্তিকে নকল না করেই মানুষ এবং প্রাণী উভয়ের জন্য কোড তৈরি করতে সহায়তা করতে পারে।
ক্লাসগুলির আংশিক ডেভर्चুয়ালাইজেশন
কয়েক বছর আগে আমি এমন কিছু করেছি যা সত্যিই স্থূল ছিল, এবং আমি নিশ্চিতও নই যে এটি আর উপকারী (এটি সি ++ 03 যুগে ছিল), এটি ছিল কোনও শ্রেণির আংশিক irtশ্বর্যিককরণ। সেক্ষেত্রে আমরা ইতিমধ্যে প্রতিটি উদ্দেশ্যে একটি ক্লাস আইডি স্টোর করেছিলাম অন্য উদ্দেশ্যে (বেস ক্লাসে অ্যাক্সেসরের মাধ্যমে অ্যাক্সেস করা যা অ-ভার্চুয়াল ছিল)। সেখানে আমরা এর সাথে সাদৃশ্যপূর্ণ কিছু করেছি (আমার স্মৃতিশক্তিটি খানিকটা দুর্বল):
switch (obj->type())
{
case id_common_type:
static_cast<CommonType*>(obj)->non_virtual_do_something();
break;
...
default:
obj->virtual_do_something();
break;
}
... যেখানে virtual_do_something
সাবক্লাসে নন-ভার্চুয়াল সংস্করণগুলি কল করার জন্য প্রয়োগ করা হয়েছিল। এটি স্থূল, আমি জানি, একটি ফাংশন কলকে ভার্চুয়ালাইজ করার জন্য একটি সুস্পষ্ট স্ট্যাটিক ডাউনস্টকাস্ট করছে। আমি বছরের পর বছর ধরে এই ধরণের জিনিস চেষ্টা না করায় এটি এখন কতটা উপকারী তা আমার কোনও ধারণা নেই। ডেটা-ওরিয়েন্টেড ডিজাইনের সংস্পর্শে, আমি গরম / ঠান্ডা ফ্যাশনে ডেটা স্ট্রাকচার এবং লুপগুলি বিভক্ত করার উপরোক্ত কৌশলটি আরও বেশি কার্যকর হতে দেখলাম, অপ্টিমাইজেশনের কৌশলগুলির জন্য আরও বেশি দরজা খুলেছি (এবং এর চেয়ে কম কুৎসিত)।
হোলসেল ডিভ্যাচুয়ালাইজেশন
আমাকে অবশ্যই স্বীকার করতে হবে যে আমি এ পর্যন্ত কোনও অপ্টিমাইজেশান মানসিকতা প্রয়োগ করতে পারি নি, সুতরাং এর সুবিধা সম্পর্কে আমার কোনও ধারণা নেই। আমি দূরদর্শিতার ক্ষেত্রে অপ্রত্যক্ষ কার্যাবলী এড়িয়ে চলেছি যেখানে আমি জানতাম যে কেবলমাত্র একটি কেন্দ্রীয় কন্ডিশনার সেট থাকবে (উদাহরণস্বরূপ: কেবলমাত্র একটি কেন্দ্রীয় স্থান প্রসেসিং ইভেন্টের সাথে ইভেন্ট প্রসেসিং), তবে কখনও পলিমারফিক মানসিকতা নিয়ে শুরু হয়নি এবং সমস্তভাবেই অনুকূলিত হয়নি এখানে অবধি
তাত্ত্বিকভাবে, এখানে তাত্ক্ষণিক সুবিধাগুলি এই অপ্টিমাইজেশন বাধাগুলি সম্পূর্ণরূপে নির্মূল করার পাশাপাশি ভার্চুয়াল পয়েন্টার (প্রাক্তন: 256 অনন্য প্রকার বা তার কম রয়েছে) এই ধারণার প্রতিশ্রুতি দিতে পারলে একক বাইট সম্ভবত কোনও ধরণের সনাক্তকরণের সম্ভাব্য ছোট উপায় হতে পারে The ।
কিছু ক্ষেত্রে সহজে-রক্ষণাবেক্ষণের কোডটি লিখতে সহায়তা করতে পারে (উপরে বর্ণিত অনুকূলিত ম্যানুয়াল ডেভर्चুয়ালাইজেশন উদাহরণগুলি বনাম) যদি আপনি কেবলমাত্র switch
উপ ডাটা টাইপের ভিত্তিতে আপনার ডেটা স্ট্রাকচার এবং লুপগুলি বিভক্ত না করে একটি কেন্দ্রীয় বিবৃতি ব্যবহার করেন , বা যদি কোনও আদেশ থাকে - এই ক্ষেত্রে নির্ভরতা যেখানে জিনিসগুলি একটি সুনির্দিষ্ট ক্রমে প্রক্রিয়া করতে হয় (এমনকি যদি এটি আমাদের পুরো জায়গা জুড়ে শাখা তোলে)। এটি এমন ক্ষেত্রে হবে যেখানে আপনার খুব বেশি জায়গা নেই যা করার দরকার switch
।
আমি সাধারণত এটি খুব দক্ষতা-সমালোচনামূলক মানসিকতার সাথে সুপারিশ করব না যতক্ষণ না এটি বজায় রাখা সহজ হয় না। "বজায় রাখা সহজ" দুটি প্রভাবশালী কারণের উপর জড়িয়ে পড়বে:
- সত্যিকারের এক্সটেনসিবিলিটি প্রয়োজন নেই (উদা: আপনার কাছে প্রক্রিয়া করার জন্য ঠিক 8 ধরণের জিনিস রয়েছে এবং এটি আর কখনও হবে না তা নিশ্চিতভাবে জেনে )।
- আপনার কোডে এমন অনেক জায়গা নেই যা এই ধরণের পরীক্ষা করতে হবে (উদা: একটি কেন্দ্রীয় জায়গা)।
... তবুও আমি বেশিরভাগ ক্ষেত্রে উপরের দৃশ্যের সুপারিশ করছি এবং প্রয়োজন অনুযায়ী আংশিক ডেভ্যাচুয়ালাইজেশন দ্বারা আরও দক্ষ সমাধানের দিকে পুনরাবৃত্তি করব। পারফরম্যান্সের সাথে এক্সটেনসিবিলিটি এবং রক্ষণাবেক্ষণের প্রয়োজনীয়তার ভারসাম্য বজায় রাখতে এটি আপনাকে অনেক বেশি শ্বাসকষ্ট দেয়।
ভার্চুয়াল ফাংশন বনাম ফাংশন পয়েন্টারগুলি
এটিকে শীর্ষে রাখার জন্য, আমি এখানে লক্ষ্য করেছি যে ভার্চুয়াল ফাংশন বনাম ফাংশন পয়েন্টার সম্পর্কে কিছু আলোচনা ছিল। এটি সত্য যে ভার্চুয়াল ফাংশনগুলিতে কল করার জন্য কিছুটা অতিরিক্ত কাজ প্রয়োজন, তবে এর অর্থ এই নয় যে সেগুলি ধীর। পাল্টা স্বজ্ঞাতভাবে, এটি তাদের আরও দ্রুততর করে তুলতে পারে।
এটি এখানে পাল্টা স্বজ্ঞাত যেহেতু আমরা মেমরি শ্রেণিবদ্ধের গতিশীলতার দিকে মনোযোগ না দিয়ে নির্দেশাবলীর ক্ষেত্রে মূল্য পরিমাপ করতে অভ্যস্ত যা যার ফলে আরও অনেক তাত্পর্যপূর্ণ প্রভাব পড়ে।
যদি আমরা class
20 ভার্চুয়াল ফাংশনগুলির সাথে একটি তুলনা করি struct
যা একটি 20 ফাংশন পয়েন্টার সঞ্চয় করে এবং উভয়ই একাধিকবার class
ইনস্ট্যান্ট করা হয় তবে এই ক্ষেত্রে প্রতিটি ক্ষেত্রে মেমরির ওভারহেড 64-বিট মেশিনে ভার্চুয়াল পয়েন্টারটির জন্য 8 বাইট রয়েছে, যখন স্মৃতি এর ওভারহেড struct
160 বাইট
ভার্চুয়াল ফাংশনগুলি ব্যবহার করে ক্লাস ফাংশন পয়েন্টারগুলির টেবিলের সাথে পুরো ব্যবহারিক ব্যয়টি আরও অনেক বাধ্যতামূলক এবং অ-বাধ্যতামূলক ক্যাশে মিস হতে পারে (এবং সম্ভবত যথেষ্ট পরিমাণে ইনপুট স্কেলের পৃষ্ঠা ত্রুটি)। এই ব্যয়টি ভার্চুয়াল টেবিলটিকে সূচিবদ্ধ করার জন্য কিছুটা অতিরিক্ত কাজ বামন করে।
আমি লিগ্যাসি সি কোডবাসগুলি (আমার চেয়ে পুরানো) এর সাথেও কাজ করেছি যেখানে structs
ফাংশন পয়েন্টারগুলিতে ভরাট করা, এবং বহুবার তাত্ক্ষণিকভাবে বাস্তবে ভার্চুয়াল ফাংশনগুলির সাথে ক্লাসে পরিণত করে উল্লেখযোগ্য পারফরম্যান্স লাভ (100% এরও বেশি উন্নতি) দেওয়া হয়েছে এবং কেবল স্মৃতি ব্যবহারের ব্যাপক হ্রাস, ক্যাশে-বন্ধুত্বপূর্ণতা ইত্যাদির কারণে
ফ্লিপ দিকে, যখন আপেলের তুলনায় আপেলগুলি আরও বেশি হয়ে যায়, আমি একইভাবে সি ++ ভার্চুয়াল ফাংশন মানসিকতা থেকে সি-স্টাইল ফাংশন পয়েন্টার মানসিকতার সাথে এই ধরণের পরিস্থিতিতে ব্যবহারের জন্য অনুবাদ করার বিপরীত মানসিকতাটি পেয়েছি:
class Functionoid
{
public:
virtual ~Functionoid() {}
virtual void operator()() = 0;
};
... যেখানে ক্লাসটি একটি একক পরিমাপের ওভারডেয়েবল ফাংশন (যেখানে আমরা ভার্চুয়াল ডেস্ট্রাক্টর গণনা করি তারা দু'জন) সংরক্ষণ করে। এই ক্ষেত্রে, এটি অবশ্যই এটিকে গুরুত্বপূর্ণ রূপান্তরিত করতে গুরুত্বপূর্ণ পথে সহায়তা করতে পারে:
void (*func_ptr)(void* instance_data);
... আদর্শভাবে / থেকে বিপজ্জনক কাস্টগুলি লুকানোর জন্য একটি টাইপ-নিরাপদ ইন্টারফেসের পিছনে void*
।
এই ক্ষেত্রে যেখানে আমরা একটি একক ভার্চুয়াল ফাংশন সহ কোনও শ্রেণি ব্যবহার করার প্রলোভন পেয়েছি, এটি পরিবর্তে ফাংশন পয়েন্টারগুলি ব্যবহার করতে দ্রুত সহায়তা করতে পারে। একটি বড় কারণ এমনকি অগত্যা একটি ফাংশন পয়েন্টার কল করতে ব্যয় হ্রাস করা হয় না। কারণ আমরা যদি অবিচ্ছিন্ন কাঠামোতে তাদের একত্রিত করি তবে আমরা গাদা ছড়িয়ে ছিটিয়ে থাকা অঞ্চলে প্রতিটি পৃথক ফাংশনয়েড বরাদ্দ করার লোভের মুখোমুখি হই না। উদাহরণস্বরূপ ডেটা একজাতীয়, উদাহরণস্বরূপ, এবং কেবল আচরণের পরিবর্তিত হলে এই ধরণের পদ্ধতির সাহায্যে হিপ-সম্পর্কিত এবং মেমরি খণ্ডিত ওভারহেড এড়ানো সহজ করা যায়।
সুতরাং অবশ্যই কিছু ক্ষেত্রে রয়েছে যেখানে ফাংশন পয়েন্টারগুলি ব্যবহার করতে সহায়তা করতে পারে তবে প্রায়শই আমি এটি অন্যভাবে খুঁজে পেয়েছি যদি আমরা ফাংশন পয়েন্টারগুলির একগুচ্ছ টিকিটকে একটি একক ভ্যাটেবলের সাথে তুলনা করি যা প্রতি ক্লাসের উদাহরণ হিসাবে কেবল একটি পয়েন্টার সংরক্ষণ করতে হয় । সেই ভিটিবেল প্রায়শই এক বা একাধিক এল 1 ক্যাশে লাইনে পাশাপাশি টাইট লুপগুলিতে বসে থাকবে।
উপসংহার
যাইহোক, এটি এই বিষয় আমার সামান্য স্পিন। আমি এই জায়গাগুলিতে সতর্কতার সাথে অভিযানের পরামর্শ দিচ্ছি। বিশ্বাসের পরিমাপ, প্রবৃত্তি নয় এবং এই অপটিমাইজেশনগুলি প্রায়শই রক্ষণাবেক্ষণকে হ্রাস করে, কেবল আপনার সাধ্যমতো চালিয়ে যেতে পারে (এবং বুদ্ধিমানের পথটি রক্ষণাবেক্ষণের পক্ষে ভুল করতে হবে)।