TL; DR ধীর লুপটি অ্যারে 'আউট অফ সীমানা' অ্যাক্সেসের কারণে হয় যা ইঞ্জিনকে কম বা কোনও অপ্টিমাইজেশন সহ ফাংশনটি পুনরায় সংযোগ করতে বাধ্য করে বা এই অপ্টিমাইজেশানগুলির সাথে আরম্ভ করে ফাংশনটি সংকলন না করে ( যদি (JIT-) সংকলক প্রথম সংকলনের 'সংস্করণ' এর আগে এই শর্তটি সনাক্ত / সন্দেহ করে) তবে নীচে কেন পড়ুন;
কাউকে কেবল
এটি বলতে হবে (পুরোপুরি হতবাক কেউ আগেই করেনি):
এমন এক সময় ব্যবহৃত হত যখন ওপির স্নিপেট একটি প্রারম্ভিক প্রোগ্রামিং বইয়ের একটি নকশার উদাহরণ হতে পারে যা জাভাস্ক্রিপ্টে 'অ্যারেগুলি' সূচনা করে সূচিত হয়। 0-এ, 1 নয়, এবং সাধারণ 'শিক্ষাগুলি ভুলের' উদাহরণ হিসাবে ব্যবহার করা হয় (কীভাবে 'প্রোগ্রামিং ত্রুটি' শব্দটি আমি এড়িয়ে গেছি তা আপনি পছন্দ করেন না
;)
):
সীমার বাইরে অ্যারে অ্যাক্সেস ।
উদাহরণ 1:
একটি Dense Array
(সংলগ্ন হওয়া (সূচকগুলির মধ্যে কোনও ব্যবধানের মধ্যে নেই) এবং প্রকৃতপক্ষে প্রতিটি সূচকে একটি উপাদান) 0-ভিত্তিক সূচক (সর্বদা ES262 তে) ব্যবহার করে 5 টি উপাদান।
var arr_five_char=['a', 'b', 'c', 'd', 'e']; // arr_five_char.length === 5
// indexes are: 0 , 1 , 2 , 3 , 4 // there is NO index number 5
সুতরাং আমরা সত্যিই <
বনাম <=
(বা 'একটি অতিরিক্ত পুনরাবৃত্তি') এর মধ্যে পারফরম্যান্স পার্থক্যের বিষয়ে কথা বলছি না , তবে আমরা কথা বলছি:
'সঠিক স্নিপেট (খ) ভুল স্নিপেট (ক) এর চেয়ে দ্রুত চালায় কেন?'
উত্তরটি হ'ল দ্বিগুণ (যদিও ES262 ভাষার প্রয়োগকারীের দৃষ্টিকোণ থেকে উভয়ই অনুকূলিতকরণের ফর্ম):
- ডেটা-প্রতিনিধিত্ব: মেমরিতে অ্যারেটি অভ্যন্তরীণভাবে কীভাবে উপস্থাপন / সংরক্ষণ করা যায় (অবজেক্ট, হ্যাশম্যাপ, 'আসল' সংখ্যাসূচক অ্যারে ইত্যাদি)
- কার্যকরী মেশিন-কোড: এই 'অ্যারে'গুলিকে অ্যাক্সেস / হ্যান্ডলগুলি (পড়ুন / সংশোধন করুন) কোডটি কীভাবে সংকলন করবেন
আইটেম 1 গ্রহণযোগ্য উত্তর দ্বারা যথেষ্ট (এবং সঠিকভাবে আইএমএইচও) ব্যাখ্যা করা হয়েছে , তবে এটি আইটেম 2: সংকলনে কেবল 2 শব্দ ('কোড') ব্যয় করে ।
আরও সুনির্দিষ্টভাবে: জেআইটি-সংকলন এবং আরও গুরুত্বপূর্ণভাবে জেআইটি- রে -সংকলন !
ভাষার স্পেসিফিকেশন মূলত কেবলমাত্র অ্যালগরিদমগুলির একটি সেট ('সংজ্ঞায়িত শেষ ফলাফল অর্জনের জন্য পদক্ষেপ') কেবলমাত্র বর্ণনা। এটি, যেমনটি দেখা যাচ্ছে যে কোনও ভাষা বর্ণনার খুব সুন্দর উপায়। এবং এটি প্রকৃত পদ্ধতিটি প্রয়োগ করে যা কোনও ইঞ্জিন প্রয়োগকারীদের জন্য নির্দিষ্ট ফলাফলগুলি অর্জন করতে ব্যবহার করে, সংজ্ঞায়িত ফলাফলগুলি উত্পাদন করার জন্য আরও কার্যকর উপায় নিয়ে আসার যথেষ্ট সুযোগ দেয়। একটি নির্দিষ্ট মাপসই ইঞ্জিনটি কোনও সংজ্ঞায়িত ইনপুটটির জন্য নির্দিষ্ট অনুসারে ফলাফল দেয়।
এখন, জাভাস্ক্রিপ্ট কোড / লাইব্রেরি / ব্যবহার বাড়ছে এবং একটি 'আসল' সংকলক কতগুলি সংস্থান (সময় / স্মৃতি / ইত্যাদি) ব্যবহার করে তা মনে রেখে, এটি স্পষ্ট যে আমরা কোনও ওয়েব-পৃষ্ঠাগুলি পরিদর্শনকারী ব্যবহারকারীদের এত দীর্ঘ অপেক্ষা করতে পারি না (এবং সেগুলি প্রয়োজনীয়) যে অনেক সংস্থান উপলব্ধ আছে)।
নিম্নলিখিত সাধারণ ফাংশনটি কল্পনা করুন:
function sum(arr){
var r=0, i=0;
for(;i<arr.length;) r+=arr[i++];
return r;
}
পুরোপুরি পরিষ্কার, তাই না? কোনও অতিরিক্ত স্পষ্টকরণের দরকার নেই, তাই না? রিটার্ন টাইপ Number
ঠিক আছে?
ঠিক আছে .. না, না এবং না ... এটি নামক ফাংশন প্যারামিটারে আপনি কী যুক্তি দিয়ে যাচ্ছেন তার উপর নির্ভর করে arr
...
sum('abcde'); // String('0abcde')
sum([1,2,3]); // Number(6)
sum([1,,3]); // Number(NaN)
sum(['1',,3]); // String('01undefined3')
sum([1,,'3']); // String('NaN3')
sum([1,2,{valueOf:function(){return this.val}, val:6}]); // Number(9)
var val=5; sum([1,2,{valueOf:function(){return val}}]); // Number(8)
সমস্যা দেখুন? তারপরে বিবেচনা করুন এটি সবেমাত্র বিপুল সম্ভাব্য ক্রমানুসারে স্ক্র্যাপ করছে ... আমাদের এমনকি শেষ পর্যন্ত কী ধরণের TYPE ফাংশনটি রিটার্ন হয় তা আমরা জানি না ...
এখন এই একই ফাংশনটির কোডটি কল্পনা করুন - কোডটি আসলে বিভিন্ন ধরণের বা ইনপুট এমনকি বিভিন্ন প্রকারে ব্যবহৃত হচ্ছে, পুরোপুরি অক্ষরে অক্ষরে (উত্স কোডে) বর্ণিত এবং গতিশীলভাবে প্রোগ্রামে তৈরি 'অ্যারে' তৈরি করা হয়েছে ..
সুতরাং, আপনি যদি sum
কেবলমাত্র কার্য সম্পাদনা করতে চান তবে একমাত্র উপায় যা সর্বদা যে কোনও এবং সমস্ত ধরণের ইনপুটটির জন্য নির্দিষ্ট-নির্দিষ্ট ফলাফলটি প্রদর্শন করে, স্পষ্টতই, কেবলমাত্র সমস্ত নির্দিষ্ট-নির্ধারিত প্রধান এবং উপ-পদক্ষেপগুলি সম্পাদন করে স্পষ্ট অনুসারে ফলাফলের গ্যারান্টি দিতে পারে (নামবিহীন প্রাক-y2k ব্রাউজারের মতো)। কোনও অপ্টিমাইজেশন নেই (কারণ কোনও অনুমান নয়) এবং মৃত ধীর ব্যাখ্যা করা স্ক্রিপ্টিং ভাষা অবশেষ।
জেআইটি-সংকলন (জাস্ট ইন টাইম হিসাবে জেআইটি) বর্তমান জনপ্রিয় সমাধান।
সুতরাং, আপনি ফাংশনটি এটি কী করে, রিটার্ন দেয় এবং গ্রহণ করে সে সম্পর্কে অনুমানগুলি ব্যবহার করে সংকলন শুরু করে।
আপনি যদি ফাংশনটি অন-স্পষ্ট সম্মতিসূচক ফলাফলগুলি (যেমন এটি অপ্রত্যাশিত ইনপুট গ্রহণ করে) প্রত্যাবর্তন শুরু করতে পারে তা সনাক্ত করতে যতটা সম্ভব চেক নিয়ে এসেছেন up তারপরে, পূর্ববর্তী সংকলিত ফলাফলটি টস করে আরও কিছু বিশদভাবে পুনরায় সংকলন করুন, ইতিমধ্যে আপনার যে আংশিক ফলাফল রয়েছে তা নিয়ে কী করবেন তা সিদ্ধান্ত নিন (নিশ্চিত হওয়ার জন্য এটি আবার বিশ্বাসযোগ্য বা গণনা করা বৈধ), প্রোগ্রামটিতে ফাংশনটি টাই করুন এবং আবার চেষ্টা কর. চূড়ান্তভাবে ধাপের দিকের স্ক্রিপ্ট-ব্যাখ্যায় ফিরে আসা spec
এই সব সময় লাগে!
সমস্ত ব্রাউজারগুলি তাদের ইঞ্জিনগুলিতে কাজ করে, প্রতিটি উপ-সংস্করণের জন্য আপনি জিনিসগুলি উন্নতি করতে এবং পুনরায় সংশোধন করতে দেখবেন। স্ট্রিংগুলি ইতিহাসের এক পর্যায়ে ছিল সত্যিকারের অপরিবর্তনীয় স্ট্রিং (অতএব অ্যারে.জোঁইন স্ট্রিং কনটেনটেশনের চেয়ে দ্রুত ছিল), এখন আমরা দড়ি (বা অনুরূপ) ব্যবহার করি যা সমস্যাটি প্রশমিত করে। উভয়ই নির্দিষ্ট ধারণা অনুসারে ফলাফল দেয় এবং এটিই গুরুত্বপূর্ণ!
দীর্ঘ গল্প সংক্ষিপ্ত: জাভাস্ক্রিপ্টের ভাষার শব্দার্থতত্ত্বগুলি প্রায়শই আমাদের পিছনে ফিরে আসে (যেমন ওপির উদাহরণে এই নীরব বাগের মতো) এর অর্থ এই নয় যে 'বোকা' ভুলগুলি দ্রুতগতিতে মেশিন-কোড ছিটিয়ে আমাদের সংকলকের সম্ভাবনা বাড়িয়ে তোলে। এটি ধরে নেওয়া হয় যে আমরা 'সাধারণত' সঠিক নির্দেশাবলী লিখেছিলাম: বর্তমান মন্ত্রটি আমরা 'ব্যবহারকারীদের' (প্রোগ্রামিং ভাষার) অবশ্যই থাকতে হবে: সংকলকটিকে সহায়তা করুন, আমরা কী চাই তা বর্ণনা করতে পারি, সাধারণ আইডিয়াগুলিকে সমর্থন করি (বেসিক বোঝার জন্য asm.js থেকে ইঙ্গিত নিন কি ব্রাউজারগুলি অপ্টিমাইজ করার চেষ্টা করতে পারে এবং কেন)।
এর কারণে, পারফরম্যান্সের বিষয়ে কথা বলা উভয়ই গুরুত্বপূর্ণ একটি খনি ক্ষেত্রের জন্য (এবং খনির ক্ষেত্রটি বলার কারণে আমি সত্যিই কিছু প্রাসঙ্গিক উপাদানকে নির্দেশ করে (এবং উদ্ধৃতি দিয়ে) শেষ করতে চাই:
অস্তিত্বের অবজেক্ট বৈশিষ্ট্যে অ্যাক্সেস এবং সীমা ছাড়িয়ে অ্যারে উপাদানগুলি undefined
ব্যতিক্রম বাড়ানোর পরিবর্তে মান প্রদান করে returns এই গতিশীল বৈশিষ্ট্যগুলি জাভাস্ক্রিপ্টে প্রোগ্রামিংকে সুবিধাজনক করে তোলে তবে এগুলি জাভাস্ক্রিপ্টকে দক্ষ মেশিন কোডে সংকলন করতে অসুবিধাজনক করে তোলে।
...
কার্যকর জেআইটি অপ্টিমাইজেশনের একটি গুরুত্বপূর্ণ ভিত্তি হ'ল প্রোগ্রামাররা জাভাস্ক্রিপ্টের গতিশীল বৈশিষ্ট্যগুলি একটি নিয়মতান্ত্রিক উপায়ে ব্যবহার করে। উদাহরণস্বরূপ, জেআইটি সংকলকরা এই সত্যটি কাজে লাগায় যে অবজেক্ট বৈশিষ্ট্যগুলি একটি নির্দিষ্ট ক্রমে নির্দিষ্ট ধরণের কোনও বস্তুর সাথে প্রায়শই যুক্ত হয় বা সীমা ছাড়িয়ে অ্যারে অ্যাক্সেস খুব কমই ঘটে। জেআইটি সংকলকগণ রানটাইমে দক্ষ মেশিন কোড তৈরি করতে এই নিয়মিততা অনুমানগুলি কাজে লাগান। যদি কোনও কোড ব্লক অনুমানগুলি পূরণ করে তবে জাভাস্ক্রিপ্ট ইঞ্জিন দক্ষ, উত্পন্ন মেশিন কোডটি কার্যকর করে। অন্যথায়, ইঞ্জিনটি অবশ্যই ধীর কোডে বা প্রোগ্রামটির ব্যাখ্যায় ফিরে যেতে হবে।
উত্স:
"JITProf: pinpointing জে আই টি JIT-অনাত্মীয় জাভাস্ক্রিপ্ট কোড"
বার্কলে প্রকাশন, 2014, লিয়াং গং, মাইকেল Pradel, কৌশিক সেন
http://software-lab.org/publications/jitprof_tr_aug3_2014.pdf
ASM.JS (বাউন্ড অ্যারে অ্যাক্সেস বন্ধ পছন্দ করে না):
সামনের সময়ের সংকলন
যেহেতু asm.js জাভাস্ক্রিপ্টের একটি কঠোর উপসেট, এই স্পেসিফিকেশনটি কেবল বৈধতা যুক্তির সংজ্ঞা দেয় — কেবল কার্যকর জাভাস্ক্রিপ্টের শব্দার্থক শব্দটি se তবে, যাচাইযোগ্য asm.js সামনের সময়ের (এওটি) সংকলনের জন্য উপযুক্ত। তদুপরি, একটি এওটি সংকলক দ্বারা উত্পন্ন কোডটি যথেষ্ট দক্ষ হতে পারে, বৈশিষ্ট্যযুক্ত:
- পূর্ণসংখ্যা এবং ভাসমান-পয়েন্ট সংখ্যাগুলির আনবক্সযুক্ত উপস্থাপনা;
- রানটাইম টাইপ চেকের অনুপস্থিতি;
- আবর্জনা সংগ্রহের অনুপস্থিতি; এবং
- দক্ষ হিপ লোড এবং স্টোর (প্ল্যাটফর্মের দ্বারা পরিবর্তিতকরণের কৌশল সহ)
বৈধতা প্রমাণ করতে ব্যর্থ কোডটি অবশ্যই traditionalতিহ্যবাহী উপায়গুলি দ্বারা কার্যকর করাতে হবে, উদাহরণস্বরূপ, ব্যাখ্যা এবং / অথবা সুনির্দিষ্ট (জেআইটি) সংকলন।
http://asmjs.org/spec/latest/
এবং পরিশেষে https://blogs.windows.com/msedgedev/2015/05/07/bringing-asm-js-to-chakra-microsoft-edge/
এ সীমাগুলি অপসারণ করার সময় ইঞ্জিনের অভ্যন্তরীণ পারফরম্যান্সের উন্নতি সম্পর্কে একটি ছোট্ট সাবসেকশন রয়েছে চেক (কেবলমাত্র লুপের বাইরে সীমা-চেক তুলতে ইতিমধ্যে 40% এর উন্নতি হয়েছে)।
সম্পাদনা:
নোট করুন যে একাধিক উত্স বিভিন্ন স্তরের জেআইটি-সংশোধন নিয়ে ব্যাখ্যা পর্যন্ত আলোচনা করে।
ওপির স্নিপেট সম্পর্কিত উপরের তথ্যের ভিত্তিতে তাত্ত্বিক উদাহরণ :
- #PrimeDivisible- এ কল করুন
- সাধারণ অনুমান (যেমন সীমা অ্যাক্সেসের বাইরে না) ব্যবহার করে প্রাইমডিজিভিয়েলকে সঙ্কলন করুন
- কাজ কর
- বিএএম, হঠাৎ অ্যারে সীমা ছাড়িয়ে অ্যাক্সেস করে (শেষে ডানদিকে)।
- ক্র্যাপ, ইঞ্জিন বলেছেন, আসুন এটি পুনরায় কম্পাইল করুন যা পৃথক (কম) অনুমানগুলি ব্যবহার করে প্রাইমডিজিবিলযোগ্য হয় এবং এই উদাহরণ ইঞ্জিনটি বর্তমান আংশিক ফলাফলটিকে পুনরায় ব্যবহার করতে পারে কিনা তা নির্ধারণের চেষ্টা করে না, তাই
- ধীর ফাংশন ব্যবহার করে সমস্ত কাজ পুনরায় সাজান (আশা করি এটি শেষ হয়, অন্যথায় পুনরাবৃত্তি করুন এবং এবার কেবল কোডটি ব্যাখ্যা করুন)।
- রিটার্ন ফলাফল
অতএব সময়টি ছিল:
প্রথম চালানো (শেষ পর্যন্ত ব্যর্থ হয়েছে) + প্রতিটি পুনরাবৃত্তির জন্য ধীর মেশিন কোড ব্যবহার করে পুনরায় সমস্ত কাজ করা + পুনরুদ্ধার ইত্যাদি .. স্পষ্টতই> এই তাত্ত্বিক উদাহরণে 2 গুণ বেশি সময় লাগে !
সম্পাদনা 2: (অস্বীকৃতি: নীচের তথ্যের উপর ভিত্তি করে অনুমান)
আমি যত বেশি মনে করি, ততই আমি মনে করি যে উত্তরটি ভ্রান্ত স্নিপেট এ (বা স্নিপেট বিতে পারফরম্যান্স-বোনাস) এর এই 'পেনাল্টি'র জন্য আরও প্রভাবশালী কারণটি ব্যাখ্যা করতে পারে , আপনি এটি কীভাবে ভাবেন তার উপর নির্ভর করে, অবিকল কেন আমি একে (স্নিপেট এ) প্রোগ্রামিং ত্রুটি বলার ক্ষেত্রে দৃ ad়ভাবে আছি:
এটি অনুমান করা বেশ লোভনীয় যে this.primes
এটি একটি 'ঘন অ্যারে' খাঁটি সংখ্যাসূচক যেটি ছিল
- সোর্স কোডে হার্ড-কোডেড আক্ষরিক ( কম্পাইল- টাইমের আগে কম্পাইলারের কাছে সমস্ত কিছু ইতিমধ্যে পরিচিত বলে 'সত্যিকারের' অ্যারে হয়ে উঠার জন্য পরিচিত অতিপ্রার্থ প্রার্থী ) বা
- সম্ভবত
new Array(/*size value*/)
আরোহী ক্রমানুসারে একটি প্রাক-আকারের ( ) পূরনকারী একটি সংখ্যাসূচক ফাংশন ব্যবহার করে উত্পন্ন হয়েছে ('আসল' অ্যারে হওয়ার জন্য আরও দীর্ঘকালীন পরিচিত প্রার্থী)।
আমরা আরও জানি যে primes
অ্যারের দৈর্ঘ্যটি ক্যাশে করা হয়েছে prime_count
! (এটি এর উদ্দেশ্য এবং নির্দিষ্ট আকার নির্দেশ করে)।
আমরা আরও জানি যে বেশিরভাগ ইঞ্জিন প্রাথমিকভাবে অ্যারেগুলিকে অনুলিপি-অন-সংশোধন (যখন প্রয়োজন হয়) হিসাবে পাস করে যা তাদের হ্যান্ডেলিংকে আরও দ্রুত করে তোলে (যদি আপনি এগুলি পরিবর্তন না করেন)।
সুতরাং এটি ধরে নেওয়া যুক্তিযুক্ত যে primes
অ্যারেটি ইতিমধ্যে অভ্যন্তরীণভাবে একটি অনুকূলিত অ্যারে যা সৃষ্টির পরে পরিবর্তিত হয় না (তৈরির পরে অ্যারে সংশোধন করার কোনও কোড না থাকলে সংকলকটির জন্য জানা সহজ) এবং তাই ইতিমধ্যে (যদি প্রয়োগ হয় তবে ইঞ্জিন) একটি অপ্টিমাইজড উপায়ে সঞ্চিত, বেশ কিছুটা যেমন এটি Typed Array
।
যেহেতু আমি আমার sum
ফাংশন উদাহরণ দিয়ে পরিষ্কার করার চেষ্টা করেছি , আর্গুমেন্ট (গুলি) যা উত্তীর্ণ হয়ে যায় আসলে কী ঘটবে তা প্রভাবিত করে এবং যেমন সেই নির্দিষ্ট কোডটি মেশিন-কোডে কীভাবে সংকলিত হচ্ছে। ফাংশনে একটি পাস String
করার ফলে sum
স্ট্রিং পরিবর্তন করা উচিত নয় তবে কীভাবে ফাংশনটি জেআইটি-সংকলিত হয় তা পরিবর্তন করা উচিত! অ্যারে পাস করার sum
জন্য মেশিন-কোডের সংস্করণটি আলাদা (সম্ভবত এই ধরণের এমনকি অতিরিক্ত, বা তারা যেমন ডাকবে তত 'আকৃতি') সংকলন করবে।
যেহেতু এটি সামান্য বোনকাস বলে মনে হচ্ছে টাইপড_আর্রে-এর মতো অ্যারেটিকে অন-দ্য ফ্লাইতে কিছু_এলসতে রূপান্তরিত করতে হবে যখন সংকলকটি primes
জানে যে এই ফাংশনটি এটি পরিবর্তন করতেও যাচ্ছে না!
এই অনুমানের অধীনে 2 টি বিকল্প রয়েছে:
- কোনও সীমানা ছাড়িয়ে ধরে না নম্বর-ক্র্যাঙ্কার হিসাবে সংকলন করুন, শেষে প্রান্তের বাইরে চলে যাওয়া সমস্যার মধ্যে চলে যান, পুনরায় রচনা করুন এবং পুনরায় কাজ করুন (উপরের 1 সম্পাদনায় তাত্ত্বিক উদাহরণে বর্ণিত হিসাবে)
- সংকলক ইতিমধ্যে আবদ্ধ প্রবেশের বাইরে (বা সন্দেহভাজন?) সনাক্ত করেছে এবং ফাংশনটি জেআইটি-সংকলিত হয়েছে যেন আর্গুমেন্টটি পাস করা একটি বিচ্ছুরিত বস্তু যার ফলে ধীর ফাংশনাল মেশিন কোড হয় (কারণ এতে আরও চেক / রূপান্তর / সংঘাত হবে) ইত্যাদি)। অন্য কথায়: ফাংশনটি নির্দিষ্ট অপটিমাইজেশনের জন্য কখনই যোগ্য ছিল না, এটি সংমিত করা হয়েছিল যেন এটি একটি 'স্পার্স অ্যারে' (- মত) যুক্তি পেয়েছিল।
আমি এখন সত্যিই ভাবছি যে এটি 2 এর মধ্যে কোনটি!
<=
এবং<
অভিন্ন।