অন্যরা যেমন বলেছে, আপনার প্রোগ্রামটির কর্মক্ষমতা প্রথমে পরিমাপ করা উচিত এবং সম্ভবত অনুশীলনে কোনও পার্থক্য পাবেন না find
তবুও, একটি ধারণাগত স্তর থেকে আমি ভেবেছিলাম যে আমি আপনার প্রশ্নে জড়িত কয়েকটি জিনিস পরিষ্কার করব। প্রথমত, আপনি জিজ্ঞাসা:
আধুনিক সংকলকগুলিতে এখনও ফাংশন কল ব্যয় গুরুত্বপূর্ণ?
"ফাংশন" এবং "সংকলক" কী শব্দগুলি লক্ষ্য করুন। আপনার উদ্ধৃতিটি সূক্ষ্মভাবে পৃথক:
মনে রাখবেন যে কোনও পদ্ধতির কলটির দাম ভাষার উপর নির্ভর করে উল্লেখযোগ্য হতে পারে।
এটি অবজেক্ট অরিয়েন্টেড অর্থে পদ্ধতি সম্পর্কে কথা বলছে ।
যদিও "ফাংশন" এবং "পদ্ধতি" প্রায়শই আন্তঃসত্তা ব্যবহার করা হয়, যখন তাদের ব্যয়ের বিষয়টি আসে (যা সম্পর্কে আপনি জিজ্ঞাসা করছেন) এবং এটি সংকলনের ক্ষেত্রে আসে (যা আপনি যে প্রসঙ্গে দিয়েছেন))
বিশেষত, স্ট্যাটিক প্রেরণ বনাম গতিশীল প্রেরণ সম্পর্কে আমাদের জানতে হবে । আমি মুহুর্তের জন্য অপ্টিমাইজেশন উপেক্ষা করব।
সি এর মতো ভাষায় আমরা সাধারণত স্ট্যাটিক প্রেরণের সাথে ফাংশনগুলিকে কল করি । উদাহরণ স্বরূপ:
int foo(int x) {
return x + 1;
}
int bar(int y) {
return foo(y);
}
int main() {
return bar(42);
}
সংকলক কলটি দেখলে foo(y)
, foo
নামটি কী ফাংশনটি উল্লেখ করছে তা তা জানে , সুতরাং আউটপুট প্রোগ্রামটি সরাসরি foo
ফাংশনে যেতে পারে, যা বেশ সস্তা। স্ট্যাটিক প্রেরণের অর্থ এটিই ।
বিকল্পটি হ'ল ডায়নামিক প্রেরণ , যেখানে সংকলক জানে না কোন ফাংশনটি ডাকা হচ্ছে। উদাহরণস্বরূপ, এখানে কিছু হাস্কেল কোড রয়েছে (যেহেতু সি সমতুল্য অগোছালো হবে!):
foo x = x + 1
bar f x = f x
main = print (bar foo 42)
এখানে bar
ফাংশনটি তার যুক্তি কল করছে f
, যা কিছু হতে পারে। অতএব সংকলকটি bar
দ্রুত জাম্পের নির্দেশের সাথে কেবল সংকলন করতে পারে না , কারণ কোথায় যেতে হবে তা এটি জানে না। পরিবর্তে, আমরা যে কোডটি তৈরি করি তা কোন ফাংশনটির দিকে ইঙ্গিত করছে তা খুঁজে বের করার জন্য এটি তারপরে ঝাঁপিয়ে bar
পড়বে f
then ডায়নামিক প্রেরণের অর্থ এটিই ।
এই দুটি উদাহরণই ফাংশনের জন্য । আপনি পদ্ধতিগুলি উল্লেখ করেছেন , যা গতিশীল-প্রেরণিত ক্রিয়াকলাপের একটি নির্দিষ্ট স্টাইল হিসাবে ভাবা যেতে পারে। উদাহরণস্বরূপ, এখানে কিছু পাইথন রয়েছে:
class A:
def __init__(self, x):
self.x = x
def foo(self):
return self.x + 1
def bar(y):
return y.foo()
z = A(42)
bar(z)
y.foo()
কল, ডায়নামিক প্রেরণ ব্যবহার যেহেতু এটি মান আপ দেখছে foo
সম্পত্তি y
বস্তু, এবং কলিং যাহা এটা খুঁজে বের করে; এটি জানে না যে y
ক্লাস হবে A
, বা A
ক্লাসে একটি foo
পদ্ধতি রয়েছে , তাই আমরা কেবল এটিতে লাফিয়ে উঠতে পারি না।
ঠিক আছে, এটি প্রাথমিক ধারণা। মনে রাখবেন যে আমরা সংকলন করি বা ব্যাখ্যা করি না কেন স্থির প্রেরণাগুলি গতিশীল প্রেরণের চেয়ে দ্রুত ; অন্য সব সমান হচ্ছে। ডেরেফারেন্সিংয়ে উভয় উপায়ে অতিরিক্ত ব্যয় হয়।
সুতরাং এটি কীভাবে আধুনিককে সংযোজকগুলিকে অনুকূল করে?
প্রথম বিষয় লক্ষণীয় হ'ল স্থিতিশীল প্রেরণকে আরও ভারীভাবে অনুকূল করা যায়: যখন আমরা জানি যে আমরা কোন ফাংশনটিতে যাচ্ছি, ইনলাইনিংয়ের মতো জিনিসগুলি করতে পারে। গতিশীল প্রেরণের সাথে, আমরা জানি না যে আমরা রান সময় পর্যন্ত ঝাঁপিয়ে পড়েছি, তাই আমরা করার মতো অপ্টিমাইজেশন নেই।
দ্বিতীয়ত, এটা কিছু কিছু ভাষায় সম্ভব অনুমান যেখানে কিছু গতিশীল পাঠাবে জাম্পিং শেষ হয়ে যাবে, তাই তাদের স্ট্যাটিক প্রেরণ মধ্যে নিখুত। এটি আমাদের অন্যান্য অপ্টিমাইজেশন যেমন ইনলাইনিং ইত্যাদি সম্পাদন করতে দেয়
উপরের পাইথনের উদাহরণে এই জাতীয় অনুভূতিটি হতাশ হ'ল, যেহেতু পাইথন অন্যান্য কোডগুলি শ্রেণি এবং বৈশিষ্ট্যগুলিকে ওভাররাইড করার অনুমতি দেয়, সুতরাং এটি সমস্ত ক্ষেত্রেই বহুলাংশে অনুধাবন করা কঠিন।
যদি আমাদের ভাষা আমাদের আরও বিধিনিষেধ আরোপ করতে দেয়, উদাহরণস্বরূপ কোনও টিকা ব্যবহার করে y
শ্রেণিতে সীমাবদ্ধ A
করে, তবে আমরা সেই তথ্যটি লক্ষ্য ফাংশনটি অনুমান করতে ব্যবহার করতে পারি। সাবক্লাসিংয়ের ভাষায় (যা ক্লাসগুলির সাথে প্রায় সমস্ত ভাষা!) আসলে যথেষ্ট নয়, যেহেতু y
আসলে আলাদা (উপ) শ্রেণি থাকতে পারে, তাই final
ঠিক কোন ফাংশনটি ডাকা হবে তা জানতে আমাদের জাভা টীকাগুলির মতো অতিরিক্ত তথ্যের প্রয়োজন হবে।
Haskell, একটি OO যেমন পণ্য ভাষা নয়, কিন্তু আমরা এর মান আবিষ্কার করতে পারেন f
ইনলাইনিং দ্বারা bar
(যা হয় স্ট্যাটিক্যালি মধ্যে প্রেষিত) main
, বদলে foo
জন্য y
। যেহেতু লক্ষ্য foo
মধ্যে main
স্ট্যাটিক্যালি পরিচিত হয়, কল স্ট্যাটিক্যালি প্রেষিত হয়ে, এবং সম্ভবত inlined হবে এবং সম্পূর্ণরূপে দূরে অপ্টিমাইজ (যেহেতু এই ফাংশন ছোট কম্পাইলার তাদের ইনলাইন াবনা আেছ; যদিও আমরা সাধারণভাবে নির্ভর করতে পারে না )।
সুতরাং ব্যয়টি নেমে আসে:
- ভাষা কি আপনার কলকে স্থিতিশীলভাবে বা গতিশীল প্রেরণ করে?
- যদি এটি পরে থাকে তবে ভাষাটি কি প্রয়োগকে অন্যান্য তথ্যের (যেমন প্রকার, শ্রেণি, টীকা, ইনলাইনিং ইত্যাদি) ব্যবহার করে লক্ষ্য নির্ধারণের অনুমতি দেয়?
- কীভাবে আক্রমণাত্মকভাবে স্থিতিশীল প্রেরণ (অনুমিত বা অন্যথায়) অনুকূলিত করা যায়?
আপনি যদি প্রচুর গতিশীল প্রেরণ এবং সংকলকের কাছে কয়েকটি গ্যারান্টি সহ "খুব গতিশীল" ভাষা ব্যবহার করেন তবে প্রতিটি কলটির জন্য ব্যয় হবে। আপনি যদি "খুব অচল" ভাষা ব্যবহার করেন তবে একজন পরিপক্ক সংকলক খুব দ্রুত কোড তৈরি করে। যদি আপনি এর মধ্যে থাকেন তবে এটি আপনার কোডিং শৈলীর উপর নির্ভর করে এবং বাস্তবায়নটি কতটা স্মার্ট।