সাধারণভাবে গতিশীল বাইন্ডিং বনাম লেক্সিকাল বাইন্ডিং
নিম্নলিখিত উদাহরণ বিবেচনা করুন:
(let ((lexical-binding nil))
(disassemble
(byte-compile (lambda ()
(let ((foo 10))
(message foo))))))
এটি lambdaস্থানীয় ভেরিয়েবলের সাথে একটি সাধারণকে সংকলন এবং তাত্ক্ষণিকভাবে বিচ্ছিন্ন করে । সঙ্গে lexical-bindingঅক্ষম করা হলে, উপরের হিসাবে, নিম্নরূপ বাইট কোড দেখায়:
0 constant 10
1 varbind foo
2 constant message
3 varref foo
4 call 1
5 unbind 1
6 return
varbindএবং varrefনির্দেশাবলী নোট করুন । এই নির্দেশাবলী হিপ মেমরির একটি বৈশ্বিক বাঁধার পরিবেশে তাদের নামের সাথে যথাক্রমে পরিবর্তনশীলগুলি বাঁধাই এবং অনুসন্ধান করে । এর সবগুলিই পারফরম্যান্সে বিরূপ প্রভাব ফেলে: এতে স্ট্রিং হ্যাশিং এবং তুলনা , গ্লোবাল ডেটা অ্যাক্সেসের জন্য সিঙ্ক্রোনাইজেশন এবং পুনরাবৃত্তি হিপ মেমরি অ্যাক্সেস যা সিপিইউ ক্যাচিংয়ের সাথে খারাপভাবে খেলে। এছাড়াও, গতিশীল ভেরিয়েবল বাইন্ডিংগুলি শেষের দিকে তাদের পূর্বের চলকটিতে পুনরুদ্ধার করা দরকার , যা বাইন্ডিংগুলির সাথে প্রতিটি ব্লকের জন্য অতিরিক্ত লুকআপ যুক্ত করে ।letnletn
আপনি যদি উপরের উদাহরণে আবদ্ধ lexical-bindingহন tতবে বাইট কোডটি কিছুটা পৃথক দেখাচ্ছে:
0 constant 10
1 constant message
2 stack-ref 1
3 call 1
4 return
নোট করুন varbindএবং varrefসম্পূর্ণরূপে চলে গেছে। স্থানীয় পরিবর্তনশীলগুলি কেবল স্ট্যাকের উপরে ধাক্কা দেওয়া হয় এবং stack-refনির্দেশের মাধ্যমে ধ্রুবক অফসেট দ্বারা উল্লেখ করা হয় । মূলত, চলকটি আবদ্ধ এবং ধ্রুবক সময় সহ পড়া হয় , ইন-স্ট্যাক মেমরিটি পড়ে এবং লেখে, যা পুরোপুরি স্থানীয় এবং এইভাবে একত্রে এবং সিপিইউ ক্যাচিংয়ের সাথে ভাল খেলে এবং কোনও স্ট্রিং জড়িত না।
সাধারণত, (যেমন স্থানীয় ভেরিয়েবল আভিধানিক বাঁধাই লুক-সঙ্গে let, setqইত্যাদি) আছে অনেক কম রানটাইম এবং মেমরি জটিলতা ।
এই নির্দিষ্ট উদাহরণ
ডায়নামিকাল বাইন্ডিংয়ের সাথে, প্রতিটি কারণে উপরোক্ত কারণে একটি পারফরম্যান্স জরিমানা জোগায়। আরও বেশি দেয়, তত বেশি গতিশীল পরিবর্তনশীল বাইন্ডিং।
উল্লেখযোগ্যভাবে, দেহের letঅভ্যন্তরে অতিরিক্ত অতিরিক্ত loop, বাউন্ড ভেরিয়েবলটি লুপের প্রতিটি পুনরাবৃত্তিতে পুনরুদ্ধার করা প্রয়োজন এবং প্রতিটি পুনরাবৃত্তিতে অতিরিক্ত ভেরিয়েবল লক যোগ করতে হবে । অতএব, লুপের দেহ থেকে দূরে রাখা আরও দ্রুত, যাতে সম্পূর্ণ লুপটি শেষ হওয়ার পরে পুনরাবৃত্তির পরিবর্তনশীল কেবল একবার পুনরায় সেট করা যায়। যাইহোক, এটি বিশেষভাবে মার্জিত নয়, কারণ পুনরাবৃত্তকরণ পরিবর্তনশীল এটির প্রয়োজনীয়তার আগেই আবদ্ধ।
লেক্সিকাল বাইন্ডিং সহ, এসগুলি letসস্তা। উল্লেখযোগ্যভাবে, একটি letলুপের দেহের অভ্যন্তরে থাকা একটি লুপের দেহের letবাইরের চেয়ে খারাপ (কর্মক্ষমতা অনুযায়ী) হয় না । সুতরাং, স্থানীয় হিসাবে ভেরিয়েবলগুলিকে যথাসম্ভব বেঁধে দেওয়া, এবং পুনরাবৃত্তকরণের পরিবর্তনশীলটিকে লুপের শরীরে সীমাবদ্ধ রাখা পুরোপুরি ঠিক।
এটি সামান্য দ্রুত, কারণ এটি অনেক কম নির্দেশাবলীর সংকলন করে। পাশের পাশের বিচ্ছিন্নতা (ডানদিকে স্থানীয় যাক) বিবেচনা করুন:
0 varref list 0 varref list
1 constant nil 1:1 dup
2 varbind it 2 goto-if-nil-else-pop 2
3 dup 5 dup
4 varbind temp 6 car
5 goto-if-nil-else-pop 2 7 stack-ref 1
8:1 varref temp 8 cdr
9 car 9 discardN-preserve-tos 2
10 varset it 11 goto 1
11 varref temp 14:2 return
12 cdr
13 dup
14 varset temp
15 goto-if-not-nil 1
18 constant nil
19:2 unbind 2
20 return
পার্থক্যটি কী কারণে ঘটছে তা সম্পর্কে আমার কোনও ধারণা নেই।
varbindলেক্সিকাল বাইন্ডিং এর অধীনে সংকলিত কোডের কোনও নেই । এটাই পুরো বিষয়টি এবং উদ্দেশ্য।