2017 আপডেট: প্রথম, আজ পাঠকদের জন্য - এখানে নোড 7 (4+) এর সাথে কাজ করে এমন একটি সংস্করণ এখানে দেওয়া হয়েছে:
function enforceFastProperties(o) {
function Sub() {}
Sub.prototype = o;
var receiver = new Sub(); // create an instance
function ic() { return typeof receiver.foo; } // perform access
ic();
ic();
return o;
eval("o" + o); // ensure no dead code elimination
}
এক বা দুটি ছোট অপ্টিমাইজেশান স্যানস - নীচের সমস্ত কিছুই এখনও বৈধ।
প্রথমে এটি কী করে এবং কেন এটি দ্রুত এবং তারপরে এটি কেন কাজ করে তা নিয়ে আলোচনা করা যাক।
এর মানে কি
ভি 8 ইঞ্জিন দুটি বস্তুর উপস্থাপনা ব্যবহার করে:
- অভিধান মোড - কোন বস্তুকে কী হিসাবে সংরক্ষণ করা হয় - হ্যাশ মানচিত্র হিসাবে মান মানচিত্র ।
- দ্রুত মোড - যার মধ্যে স্ট্রাক্টের মতো অবজেক্টগুলি সংরক্ষণ করা হয় , যেখানে সম্পত্তি অ্যাক্সেসের সাথে জড়িত কোনও গণনা নেই।
এখানে একটি সাধারণ ডেমো যা গতির পার্থক্য দেখায়। এখানে আমরা delete
স্টেটমেন্টটি ধীরে ধীরে অভিধান মোডে জোর করার জন্য ব্যবহার করি ।
যখনই সম্ভব ইঞ্জিন দ্রুত মোড ব্যবহার করার চেষ্টা করে এবং সাধারণত যখনই প্রচুর সম্পত্তি অ্যাক্সেস করা হয় - তবে কখনও কখনও এটি অভিধান মোডে ফেলে দেওয়া হয়। অভিধান মোডে থাকায় একটি বৃহত পারফরম্যান্স পেনাল্টি থাকে তাই সাধারণভাবে বস্তুগুলিকে দ্রুত মোডে রাখাই বাঞ্ছনীয়।
এই হ্যাকটি উদ্দেশ্য মোড থেকে শব্দটিকে দ্রুত মোডে বাধ্য করার উদ্দেশ্যে।
কেন এটি দ্রুত
জাভাস্ক্রিপ্ট প্রোটোটাইপগুলিতে সাধারণত অনেকগুলি ইভেন্টের মধ্যে ভাগ করা ফাংশনগুলি সংরক্ষণ করে এবং খুব কমই গতিশীল পরিবর্তন হয়। এই কারণে প্রতিটি বার যখন কোনও ফাংশন বলা হয় তখন অতিরিক্ত জরিমানা এড়াতে দ্রুত মোডে এগুলি রাখা খুব আকাঙ্ক্ষিত।
এর জন্য - ভি 8 আনন্দের সাথে বস্তুগুলিকে .prototype
দ্রুত মোডে ফাংশনগুলির সম্পত্তি হিসাবে রাখবে যেহেতু তারা নির্মাণকারী হিসাবে ফাংশনটি আহ্বান করে নির্মিত প্রতিটি বস্তু দ্বারা ভাগ করা হবে। এটি সাধারণত একটি চালাক এবং পছন্দসই অপ্টিমাইজেশন।
কিভাবে এটা কাজ করে
আসুন প্রথমে কোডটি দেখুন এবং প্রতিটি লাইন কী করে তা চিত্রিত করুন:
function toFastProperties(obj) {
/*jshint -W027*/ // suppress the "unreachable code" error
function f() {} // declare a new function
f.prototype = obj; // assign obj as its prototype to trigger the optimization
// assert the optimization passes to prevent the code from breaking in the
// future in case this optimization breaks:
ASSERT("%HasFastProperties", true, obj); // requires the "native syntax" flag
return f; // return it
eval(obj); // prevent the function from being optimized through dead code
// elimination or further optimizations. This code is never
// reached but even using eval in unreachable code causes v8
// to not optimize functions.
}
আমরা না আছে যে V8 জাহির করা এই অপ্টিমাইজেশান, আমরা পরিবর্তে পারেন না কোড নিজেদেরকে খুঁজে পেতে V8 ইউনিট পরীক্ষা পড়া :
// Adding this many properties makes it slow.
assertFalse(%HasFastProperties(proto));
DoProtoMagic(proto, set__proto__);
// Making it a prototype makes it fast again.
assertTrue(%HasFastProperties(proto));
এই পরীক্ষাটি পড়া এবং চালানো আমাদের দেখায় যে এই অপ্টিমাইজেশনটি সত্যই v8 এ কাজ করে। তবে - এটি দেখতে ভাল লাগবে।
আমরা যদি পরীক্ষা করে objects.cc
দেখি আমরা নীচের ফাংশনটি (L9925) খুঁজে পেতে পারি:
void JSObject::OptimizeAsPrototype(Handle<JSObject> object) {
if (object->IsGlobalObject()) return;
// Make sure prototypes are fast objects and their maps have the bit set
// so they remain fast.
if (!object->HasFastProperties()) {
MigrateSlowToFast(object, 0);
}
}
এখন, JSObject::MigrateSlowToFast
কেবল স্পষ্টভাবে অভিধান নেওয়া এবং এটিকে দ্রুত ভি 8 অবজেক্টে রূপান্তরিত করে। এটি সার্থকভাবে পড়া এবং ভি 8 অবজেক্ট ইন্টার্নালগুলির মধ্যে একটি আকর্ষণীয় অন্তর্দৃষ্টি - তবে এটি এখানে বিষয় নয়। আমি এখনও আন্তরিকভাবে প্রস্তাব দিচ্ছি যে আপনি এটি এখানে পড়ুন কারণ এটি ভি 8 অবজেক্ট সম্পর্কে জানার ভাল উপায়।
আমরা যদি খুঁজে বার করো SetPrototype
মধ্যে objects.cc
, আমরা দেখতে পাচ্ছেন এটি লাইন 12231 ডেকে হয়:
if (value->IsJSObject()) {
JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
}
যার বদলে বলা হয় কোনটি FuntionSetPrototype
আমরা পাই তা দিয়ে .prototype =
।
করছেন __proto__ =
বা .setPrototypeOf
কাজও করেছেন তবে এগুলি ES6 ফাংশন এবং ব্লুবার্ড নেটস্কেপ 7 এর পরে সমস্ত ব্রাউজারে রান করে তাই কোডটি এখানে সহজ করার জন্য প্রশ্নটির বাইরে। উদাহরণস্বরূপ, আমরা যদি পরীক্ষা .setPrototypeOf
করি তবে আমরা দেখতে পাচ্ছি:
// ES6 section 19.1.2.19.
function ObjectSetPrototypeOf(obj, proto) {
CHECK_OBJECT_COERCIBLE(obj, "Object.setPrototypeOf");
if (proto !== null && !IS_SPEC_OBJECT(proto)) {
throw MakeTypeError("proto_object_or_null", [proto]);
}
if (IS_SPEC_OBJECT(obj)) {
%SetPrototype(obj, proto); // MAKE IT FAST
}
return obj;
}
যা সরাসরি চালু Object
:
InstallFunctions($Object, DONT_ENUM, $Array(
...
"setPrototypeOf", ObjectSetPrototypeOf,
...
));
সুতরাং - আমরা পেটকা কোডটি বেয়ার ধাতব দ্বারা লিখিত কোড থেকে পথ চললাম। এটি দুর্দান্ত ছিল।
দাবি পরিত্যাগী:
মনে রাখবেন এটি সমস্ত বাস্তবায়ন বিশদ। পেটকার মতো লোকেরা অপ্টিমাইজেশন ফ্রিক্স। সর্বদা মনে রাখবেন যে অকাল অপটিমাইজেশন হ'ল 97% সময়ের সমস্ত অশুভের মূল। ব্লুবার্ড খুব ঘন ঘন বেসিক কিছু করে তাই এটি এই পারফরম্যান্স হ্যাকগুলি থেকে প্রচুর লাভ করে - কলব্যাক তত দ্রুত হওয়া সহজ নয়। আপনাকে খুব কমই কোডটিতে এমন কিছু করতে হবে যা কোনও লাইব্রেরিকে শক্তি দেয় না।