সিল করা ক্লাসগুলি কি কার্যত কর্মক্ষমতা বেনিফিট দেয়?


140

আমি প্রচুর অপ্টিমাইজেশান টিপস নিয়ে এসেছি যা বলছে যে অতিরিক্ত কর্মক্ষমতা সুবিধা পেতে আপনার ক্লাসগুলি সিল হিসাবে চিহ্নিত করা উচিত।

পারফরম্যান্সের পার্থক্য পরীক্ষা করে দেখার জন্য আমি কিছু পরীক্ষা চালিয়েছি এবং কোনও কিছুই পাইনি। আমি কি ভুল কিছু করছি? আমি কি এমন মামলাটি মিস করছি যেখানে সিল করা ক্লাসগুলি আরও ভাল ফলাফল দেবে?

কেউ পরীক্ষা চালিয়েছে এবং কোন পার্থক্য দেখেছেন?

আমাকে শিখতে সহায়তা করুন :)


9
আমি মনে করি না সিল করা ক্লাসগুলি একটি নিখুঁত বৃদ্ধি দেওয়ার উদ্দেশ্যে করা হয়েছিল। তারা যে ঘটনাটি ঘটায় তা ঘটনাক্রমে হতে পারে। এটি ছাড়াও, সিল করা ক্লাসগুলি ব্যবহার করার জন্য আপনার অ্যাপটিকে রিফ্যাক্ট করার পরে প্রোফাইল দিন এবং এটি চেষ্টা করার উপযুক্ত কিনা তা নির্ধারণ করুন। অপ্রয়োজনীয় মাইক্রো-অপ্টিমাইজেশান তৈরি করতে আপনার এক্সটেনসিবিলিটিটি লক করা আপনার দীর্ঘমেয়াদে ব্যয় করবে। অবশ্যই, যদি আপনি প্রোফাইল করেন এবং এটি আপনাকে আপনার পারফ বেঞ্চমার্কগুলিতে আঘাত করতে দেয় (পারফের জন্য পারফের চেয়ে)), তবে ব্যয় করা অর্থের উপযুক্ত হলে আপনি একটি দল হিসাবে সিদ্ধান্ত নিতে পারেন। যদি আপনি অ-পারফেক্ট কারণে ক্লাসগুলি সিল করেন তবে তাদের রাখুন :)
মার্লিন মরগান-গ্রাহাম

1
আপনি প্রতিবিম্ব দিয়ে চেষ্টা করেছেন? কোথাও পড়ি যে প্রতিফলন দ্বারা শুরু করতে গিয়ে সিল শ্রেণীর সঙ্গে দ্রুততর
onof

আমার জ্ঞানের কোন কিছুই নেই। সিলযুক্ত আলাদা কারণের জন্য রয়েছে - এক্সটেনসিবিলিটি ব্লক করা, যা প্রচুর ক্ষেত্রে দরকারী / প্রয়োজনীয় হতে পারে। পারফরম্যান্স অপটিমাইজেশন এখানে একটি লক্ষ্য ছিল না।
টমটম

... তবে আপনি যদি সংকলকটি সম্পর্কে ভাবেন: আপনার ক্লাসটি সিল করা থাকলে, সংকলনের সময় আপনি আপনার ক্লাসে কল করেছেন এমন কোনও পদ্ধতির ঠিকানা জানেন। যদি আপনার ক্লাসটি সিল না করা হয় তবে রান-টাইমে আপনাকে পদ্ধতিটি সমাধান করতে হবে কারণ আপনাকে ওভাররাইডের কল করতে হতে পারে। এটি অবশ্যই নগণ্য হতে চলেছে, তবে আমি দেখতে পাচ্ছিলাম যে কিছু পার্থক্য থাকবে।
ড্যান পুজে

হ্যাঁ, তবে ওপি নির্দেশ করেছেন বলে এই ধরণের সত্যিকারের সুবিধাগুলিতে অনুবাদ হয় না। আর্কিটেকচারাল পার্থক্যগুলি অনেক বেশি প্রাসঙ্গিক হতে পারে।
টমটম

উত্তর:


60

জিটর মাঝেমধ্যে সিলড ক্লাসে নন-ভার্চুয়াল কলগুলি ব্যবহার করবে কারণ তাদের আরও বাড়ানোর কোনও উপায় নেই।

কলিং টাইপ, ভার্চুয়াল / নন ভার্চুয়াল সম্পর্কে জটিল বিধি রয়েছে এবং আমি এগুলি সব জানি না তাই আমি আপনার পক্ষে সত্যই তাদের রূপরেখা দিতে পারি না, তবে আপনি সিল করা ক্লাস এবং ভার্চুয়াল পদ্ধতিগুলির জন্য গুগল করলে আপনি এই বিষয়ের উপর কিছু নিবন্ধ খুঁজে পেতে পারেন।

নোট করুন যে আপনি এই স্তরের অপ্টিমাইজেশান থেকে যে কোনও ধরণের পারফরম্যান্স সুবিধা পাবেন তা সর্বশেষ-অবলম্বন হিসাবে বিবেচনা করা উচিত, আপনি কোড-স্তরে অনুকূলিত হওয়ার আগে সর্বদা অ্যালগরিদমিক স্তরে অনুকূলিত হন।

এখানে এটির একটি লিঙ্ক উল্লেখ করা হয়েছে: সিল করা কীওয়ার্ডে র‌্যামব্লিং


2
'র‌্যাম্বলিং' লিঙ্কটি আকর্ষণীয় যে এটিকে প্রযুক্তিগত মঙ্গল বলে মনে হয় তবে এটি আসলে বাজে non আরও তথ্যের জন্য নিবন্ধে মন্তব্য পড়ুন। সংক্ষিপ্তসার: প্রদত্ত ৩ টি কারণ হ'ল সংস্করণ, পারফরম্যান্স এবং সুরক্ষা / ভবিষ্যদ্বাণী - [পরবর্তী মন্তব্য দেখুন]
স্টিভেন এ। লো

1
[অব্যাহত] সংস্করণ কেবল তখনই প্রযোজ্য যখন কোনও সাবক্ল্যাস নেই, দুহ, কিন্তু এই যুক্তিটি প্রতিটি শ্রেণীর কাছে প্রসারিত করুন এবং হঠাৎ আপনার কোনও উত্তরাধিকার নেই এবং কী অনুমান করুন, ভাষা আর বস্তু-কেন্দ্রিক নয় (কেবল নিছক অবজেক্ট ভিত্তিক)! [পরবর্তী দেখুন]
স্টিভেন এ। লো 21

3
[অব্যাহত] পারফরম্যান্সের উদাহরণটি একটি রসিকতা: একটি ভার্চুয়াল পদ্ধতি কলটি অনুকূলকরণ; সিল করা শ্রেণীর কেন প্রথম স্থানটিতে ভার্চুয়াল পদ্ধতি থাকবে কারণ এটি সাবক্ল্যাসিং করা যায় না? পরিশেষে, সুরক্ষা / ভবিষ্যদ্বাণী যুক্তি পরিষ্কারভাবে মজাদার: 'আপনি এটি ব্যবহার করতে পারবেন না এটি নিরাপদ / অনুমানযোগ্য'। হাঃ হাঃ হাঃ!
স্টিভেন এ লো

16
@ স্টিভেন এ। লো - আমার মনে হয় জেফ্রি রিখরর কিছুটা চারিদিক দিয়ে যা বলতে চাইছিল তা হ'ল আপনি যদি আপনার ক্লাসটি খোলামেলা ছাড়েন তবে আপনাকে উদ্ভূত শ্রেণিগুলি কীভাবে ব্যবহার করতে পারে / কীভাবে ব্যবহার করতে পারে তা চিন্তা করা দরকার এবং যদি আপনার কাছে না থাকে সময় বা ঝুঁকির সাথে এটি সঠিকভাবে করার জন্য, তারপরে এটি সীলমোহর করুন কারণ এটি ভবিষ্যতে অন্যের কোডে পরিবর্তন আনার সম্ভাবনা কম। এটি মোটেই বাজে কথা নয়, এটি খুব সাধারণ জ্ঞান।
গ্রেগ বিচ

6
সিল করা শ্রেণীর একটি ভার্চুয়াল পদ্ধতি থাকতে পারে কারণ এটি এটি ঘোষণা করে এমন কোনও ক্লাস থেকে আসে। আপনি যখন পরে, সিল করা বংশধর শ্রেণীর একটি পরিবর্তনশীল ঘোষণা করুন এবং সেই পদ্ধতিটি কল করবেন তখন সংকলকটি জানা বাস্তবায়নের জন্য সরাসরি কলটি নির্গমন করতে পারে, কারণ এটি জানে যে এটি জানা- এর চেয়ে আলাদা হতে পারে এমন কোনও উপায় নেই- ক্লাসের জন্য at-compile-vtable। সিল করা / সিসিল না করা সম্পর্কে, এটি আলাদা আলোচনা এবং আমি ডিফল্টরূপে ক্লাসগুলি সিল করার কারণগুলির সাথে একমত।
ল্যাসে ভি। কার্লসেন

143

উত্তরটি হ'ল না, সিল করা ক্লাসগুলি সিলবিহীন থেকে ভাল সম্পাদন করে না।

callবনাম callvirtআইএল অপ কোডগুলিতে সমস্যাটি নেমে আসে । Callএর চেয়ে দ্রুত callvirtএবং callvirtএটি প্রধানত ব্যবহৃত হয় যখন আপনি জানেন না যে অবজেক্টটি সাবক্ল্যাস করা হয়েছে কিনা। তাই মানুষ অনুমান যদি আপনি কোন ক্লাসে সীল সব অপ কোড থেকে পরিবর্তন করতে হবে calvirtsকরতে callsএবং দ্রুত হতে হবে।

দুর্ভাগ্যক্রমে callvirtঅন্যান্য জিনিসগুলিও এটি কার্যকর করে তোলে যেমন নাল রেফারেন্সগুলির জন্য পরীক্ষা করা। এর অর্থ হ'ল এমনকি যদি কোনও শ্রেণি সিল করা থাকে তবে রেফারেন্সটি এখনও শূন্য হতে পারে এবং এইভাবে একটি callvirtপ্রয়োজনীয় প্রয়োজন। আপনি এটি কাছাকাছি পেতে পারেন (ক্লাসটি সিল করার প্রয়োজন ছাড়াই) তবে এটি কিছুটা অর্থহীন হয়ে যায়।

স্ট্রাইকগুলি ব্যবহার করা হয় callকারণ সেগুলি সাবক্ল্যাস করা যায় না এবং কখনই নਾਲ হয় না।

আরও তথ্যের জন্য এই প্রশ্নটি দেখুন:

কল এবং কলvirt


5
আফাইক, যে পরিস্থিতিতে callব্যবহৃত হয় তা হ'ল: পরিস্থিতিতে new T().Method(), structপদ্ধতির জন্য, পদ্ধতিগুলিতে অ-ভার্চুয়াল কলগুলির জন্য virtual(যেমন base.Virtual()), বা staticপদ্ধতিগুলির জন্য । অন্য কোথাও ব্যবহার করে callvirt
porges

1
আহ ... আমি বুঝতে পেরেছি এটি পুরানো, তবে এটি পুরোপুরি ঠিক নয় ... সিলড ক্লাসগুলির সাথে বড় জয়টি তখন হয় যখন জেআইটি অপ্টিমাইজার কলটি ইনলাইন করতে পারে ... সেক্ষেত্রে সিল করা শ্রেণিটি বিশাল জয় হতে পারে ।
ব্রায়ান কেনেডি

5
কেন এই উত্তর ভুল। মনো থেকে চেঞ্জলগ থেকে: "সিলড ক্লাস এবং পদ্ধতিগুলির জন্য ডিভ্রিচুয়ালাইজেশন অপ্টিমাইজেশন, আয়রন পাইথন ২.০ পাইথস্টোন পারফরম্যান্সকে ৪% উন্নত করেছে। অন্যান্য প্রোগ্রামগুলিও একইরকম উন্নতি আশা করতে পারে [রডরিগো]।" সিল করা ক্লাসগুলি পারফরম্যান্সের উন্নতি করতে পারে, তবে বরাবরের মতো এটি পরিস্থিতির উপর নির্ভর করে।
স্মাইলিভার

1
@ স্মাইলিভার এটি পারফরম্যান্সের উন্নতি করতে পারে, তবে কেবলমাত্র আপনার কাছে খারাপ জেআইটি থাকলে (নেট জাইটিগুলি আজকাল কতটা ভাল তা জানেনা - যদিও এই বিষয়ে বেশ খারাপ ব্যবহার করা হত)। উদাহরণস্বরূপ হটস্পট ভার্চুয়াল কলগুলিকে ইনলাইন করবে এবং প্রয়োজনে পরে ডিউটিমাইজ করবে - সুতরাং আপনি অতিরিক্ত ওভারহেড কেবল তখনই প্রদান করেন যদি আপনি ক্লাসটি সাবক্লাস করেন (এবং তারপরেও প্রয়োজনীয়ভাবে নয়)।
ভু

1
-1 জেআইটি একই আইএল অপকডগুলির জন্য একই মেশিন কোডটি জেনারেট করে না। নাল চেকিং এবং ভার্চুয়াল কল হ'ল অর্থোগোনাল এবং কল ভার্টের পৃথক পদক্ষেপ। সিলযুক্ত ধরণের ক্ষেত্রে জেআইটি সংকলক এখনও কলভার্টের অংশটিকে অনুকূল করতে পারে। যখন জেআইটি সংকলক গ্যারান্টি দিতে পারে যে কোনও রেফারেন্স নালার নয় The
ডানফোল্ড

29

আপডেট:। নেট কোর ২.০ এবং। নেট ডেস্কটপ ৪.7.১ অনুসারে, সিএলআর এখন ডিভ্যাচুয়ালাইজেশন সমর্থন করে। এটি সিল করা ক্লাসে পদ্ধতি গ্রহণ করতে পারে এবং সরাসরি কলগুলির সাথে ভার্চুয়াল কলগুলি প্রতিস্থাপন করতে পারে - এবং এটি সিল-ক্লাস না করা ক্লাসগুলির পক্ষে এটি করা সম্ভব যদি এটি করা নিরাপদ হয়।

এই জাতীয় ক্ষেত্রে (একটি সিলড ক্লাস যা সিএলআর অন্যথায় ডেভ্যাচুয়ালাইজ করার পক্ষে সুরক্ষিত হিসাবে সনাক্ত করতে পারে না), একটি সিল করা শ্রেণিটি অবশ্যই একরকম পারফরম্যান্স বেনিফিট সরবরাহ করে।

তাই বলা হয়, আমার মনে হয় না এটা সম্পর্কে উদ্বেজক মূল্য হতে চাই যদি না আপনি ইতিমধ্যে কোড প্রোফাইল করেছিলেন এবং নিশ্চিত যে আপনি একটি বিশেষ গরম পাথ মত কিছু ছিল সময়ের লক্ষ বলা হচ্ছে, অথবা:

https://blogs.msdn.microsoft.com/dotnet/2017/06/29/performance-improvements-in-ryujit-in-net-core-and-net-framework/


আসল উত্তর:

আমি নিম্নলিখিত পরীক্ষার প্রোগ্রামটি তৈরি করেছিলাম এবং তারপরে এমএসআইএল কোডটি কীভাবে নির্গত হয়েছিল তা দেখার জন্য এটি রিফ্লেক্টর ব্যবহার করে এটি ডিসপম্প্ল করে দিয়েছিলাম।

public class NormalClass {
    public void WriteIt(string x) {
        Console.WriteLine("NormalClass");
        Console.WriteLine(x);
    }
}

public sealed class SealedClass {
    public void WriteIt(string x) {
        Console.WriteLine("SealedClass");
        Console.WriteLine(x);
    }
}

public static void CallNormal() {
    var n = new NormalClass();
    n.WriteIt("a string");
}

public static void CallSealed() {
    var n = new SealedClass();
    n.WriteIt("a string");
}

সমস্ত ক্ষেত্রে, সি # সংকলক (রিলিজ বিল্ড কনফিগারেশনে ভিজ্যুয়াল স্টুডিও 2010) অভিন্ন এমএসআইএল নির্গত করে যা নীচে:

L_0000: newobj instance void <NormalClass or SealedClass>::.ctor()
L_0005: stloc.0 
L_0006: ldloc.0 
L_0007: ldstr "a string"
L_000c: callvirt instance void <NormalClass or SealedClass>::WriteIt(string)
L_0011: ret 

লোকেদের সীলমোহর করা দক্ষতার কারণে যে কারনটি বেনিফিট দেয় তা হ'ল সংকলক জানে যে ক্লাসটি ওভাররেড করা হয়নি, এবং এর ফলে এটি ভার্চুয়াল ইত্যাদির জন্য পরীক্ষা করতে হবে না ইত্যাদি callপরিবর্তে ব্যবহার করতে পারে , callvirtযেমন উপরে প্রমাণিত, এটি নয় সত্য।

আমার পরবর্তী চিন্তা ছিল যে এমএসআইএল অভিন্ন হলেও, সম্ভবত জেআইটি সংকলক সিল করা ক্লাসগুলি আলাদাভাবে আচরণ করে?

আমি ভিজ্যুয়াল স্টুডিও ডিবাগারের অধীনে একটি রিলিজ বিল্ড চালিয়েছি এবং পচনশীল x86 আউটপুট দেখেছি। উভয় ক্ষেত্রে, x86 কোডটি অভিন্ন ছিল, শ্রেণীর নাম এবং ফাংশন মেমরি ঠিকানাগুলি বাদ দিয়ে (অবশ্যই অবশ্যই আলাদা হওয়া উচিত)। এটা এখানে

//            var n = new NormalClass();
00000000  push        ebp 
00000001  mov         ebp,esp 
00000003  sub         esp,8 
00000006  cmp         dword ptr ds:[00585314h],0 
0000000d  je          00000014 
0000000f  call        70032C33 
00000014  xor         edx,edx 
00000016  mov         dword ptr [ebp-4],edx 
00000019  mov         ecx,588230h 
0000001e  call        FFEEEBC0 
00000023  mov         dword ptr [ebp-8],eax 
00000026  mov         ecx,dword ptr [ebp-8] 
00000029  call        dword ptr ds:[00588260h] 
0000002f  mov         eax,dword ptr [ebp-8] 
00000032  mov         dword ptr [ebp-4],eax 
//            n.WriteIt("a string");
00000035  mov         edx,dword ptr ds:[033220DCh] 
0000003b  mov         ecx,dword ptr [ebp-4] 
0000003e  cmp         dword ptr [ecx],ecx 
00000040  call        dword ptr ds:[0058827Ch] 
//        }
00000046  nop 
00000047  mov         esp,ebp 
00000049  pop         ebp 
0000004a  ret 

আমি তখন ভেবেছিলাম সম্ভবত ডিবাগারের নিচে দৌড়ানোর কারণে এটি কম আক্রমণাত্মক অপটিমাইজেশন সম্পাদন করে?

আমি তখন কোনও ডিবাগিং পরিবেশের বাইরে এক্সিকিউটেবল বিল্ড স্ট্যান্ডেলোন রিলিজ চালাতাম, এবং উইনডিবিজি + এসওএস ব্যবহার করে প্রোগ্রামটি শেষ হওয়ার পরে ভেঙে যায় এবং জেআইটি সংকলিত x86 কোডটির বিচ্ছিন্নতা দেখতে পেলাম।

আপনি নীচের কোড থেকে দেখতে পাচ্ছেন, ডিবাগারের বাইরে দৌড়ানোর সময় জেআইটি সংকলক আরও আক্রমণাত্মক হয় এবং এটি WriteItপদ্ধতিটি সরাসরি কলারের মধ্যে প্রবেশ করিয়ে দেয় । তবে গুরুত্বপূর্ণ বিষয়টি হ'ল সিল করা বনাম সিল করা ক্লাসটিকে কল করার সময় এটি অভিন্ন ছিল। সিলযুক্ত বা ননসিল করা শ্রেণীর মধ্যে কোনও পার্থক্য নেই।

এখানে একটি সাধারণ ক্লাস কল করার সময়:

Normal JIT generated code
Begin 003c00b0, size 39
003c00b0 55              push    ebp
003c00b1 8bec            mov     ebp,esp
003c00b3 b994391800      mov     ecx,183994h (MT: ScratchConsoleApplicationFX4.NormalClass)
003c00b8 e8631fdbff      call    00172020 (JitHelp: CORINFO_HELP_NEWSFAST)
003c00bd e80e70106f      call    mscorlib_ni+0x2570d0 (6f4c70d0) (System.Console.get_Out(), mdToken: 060008fd)
003c00c2 8bc8            mov     ecx,eax
003c00c4 8b1530203003    mov     edx,dword ptr ds:[3302030h] ("NormalClass")
003c00ca 8b01            mov     eax,dword ptr [ecx]
003c00cc 8b403c          mov     eax,dword ptr [eax+3Ch]
003c00cf ff5010          call    dword ptr [eax+10h]
003c00d2 e8f96f106f      call    mscorlib_ni+0x2570d0 (6f4c70d0) (System.Console.get_Out(), mdToken: 060008fd)
003c00d7 8bc8            mov     ecx,eax
003c00d9 8b1534203003    mov     edx,dword ptr ds:[3302034h] ("a string")
003c00df 8b01            mov     eax,dword ptr [ecx]
003c00e1 8b403c          mov     eax,dword ptr [eax+3Ch]
003c00e4 ff5010          call    dword ptr [eax+10h]
003c00e7 5d              pop     ebp
003c00e8 c3              ret

বনাম একটি সিলড ক্লাস:

Normal JIT generated code
Begin 003c0100, size 39
003c0100 55              push    ebp
003c0101 8bec            mov     ebp,esp
003c0103 b90c3a1800      mov     ecx,183A0Ch (MT: ScratchConsoleApplicationFX4.SealedClass)
003c0108 e8131fdbff      call    00172020 (JitHelp: CORINFO_HELP_NEWSFAST)
003c010d e8be6f106f      call    mscorlib_ni+0x2570d0 (6f4c70d0) (System.Console.get_Out(), mdToken: 060008fd)
003c0112 8bc8            mov     ecx,eax
003c0114 8b1538203003    mov     edx,dword ptr ds:[3302038h] ("SealedClass")
003c011a 8b01            mov     eax,dword ptr [ecx]
003c011c 8b403c          mov     eax,dword ptr [eax+3Ch]
003c011f ff5010          call    dword ptr [eax+10h]
003c0122 e8a96f106f      call    mscorlib_ni+0x2570d0 (6f4c70d0) (System.Console.get_Out(), mdToken: 060008fd)
003c0127 8bc8            mov     ecx,eax
003c0129 8b1534203003    mov     edx,dword ptr ds:[3302034h] ("a string")
003c012f 8b01            mov     eax,dword ptr [ecx]
003c0131 8b403c          mov     eax,dword ptr [eax+3Ch]
003c0134 ff5010          call    dword ptr [eax+10h]
003c0137 5d              pop     ebp
003c0138 c3              ret

আমার কাছে এটি দৃ solid় প্রমাণ দেয় যে সিল করা বনাম সিল করা ক্লাসগুলিতে কল করার পদ্ধতিগুলির মধ্যে কোনও কার্যকারিতা উন্নতি হতে পারে না ... আমি মনে করি আমি এখন খুশি :-)


আপনি এই উত্তরটিকে নকল হিসাবে বন্ধ করার পরিবর্তে দুবার এই উত্তর পোস্ট করেছেন কেন? তারা আমার কাছে বৈধ নকলের মতো দেখায় যদিও এটি আমার অঞ্চল নয়।
ফ্লেক্সো

1
ইনলাইনিং এড়াতে এবং কোন কল অপারেশন ব্যবহার করা হবে তা দেখার জন্য যদি পদ্ধতিগুলি দীর্ঘতর (32 বাইটের বেশি আইএল কোড) থাকে? যদি এটি ইনলাইন করা থাকে তবে আপনি কলটি দেখতে পাচ্ছেন না যাতে প্রভাবগুলির বিষয়ে বিচার করা যায় না।
ygoe

আমি বিভ্রান্ত: কেন callvirtযখন এই পদ্ধতিগুলি শুরু করার জন্য ভার্চুয়াল নয় তখন সেখানে কেন ?
২ak

@ ফ্রেয়াকিশ আমি কোথায় দেখতে পেয়েছি তা মনে করতে পারছি না, তবে আমি পড়লাম যে সিএলআরটি সিলড callvirtপদ্ধতিগুলির জন্য ব্যবহৃত হয়েছিল কারণ পদ্ধতি কলটি শুরু করার আগে এটি এখনও অবজেক্টটি শূন্য করে ফেলতে হবে এবং আপনি যদি এটির ফ্যাক্টর তৈরি করেন, আপনি কেবল ঠিক ব্যবহার callvirt। এটিকে সরাতে callvirtএবং সরাসরি লাফানোর জন্য, তাদেরকে ((string)null).methodCall()সি ++ এর মতো অনুমতি দেওয়ার জন্য সি # সংশোধন করতে হবে, বা তাদের স্থিরভাবে প্রমাণ করতে হবে যে বস্তুটি নাল ছিল না (যা তারা করতে পারে তবে বিরক্ত করেনি)
অরিওন এডওয়ার্ডস

1
মেশিন কোড স্তরে খননের প্রচেষ্টাতে যাওয়ার জন্য প্রপসগুলি, তবে ' এটি কোনও কার্যকারিতা উন্নতি করতে পারে না তার দৃ proof় প্রমাণ দেয়' এর মতো বিবৃতি দেওয়ার ক্ষেত্রে খুব সাবধানতা অবলম্বন করুন । আপনি যা দেখিয়েছেন তা হল একটি নির্দিষ্ট দৃশ্যের জন্য নেটিভ আউটপুটটিতে কোনও পার্থক্য নেই। এটি একটি ডেটা পয়েন্ট এবং এটি কোনও পরিস্থিতিতে ধরে নেওয়া যায় না এটি সমস্ত পরিস্থিতিতে ঘটেছে। প্রারম্ভিকদের জন্য, আপনার ক্লাসগুলি কোনও ভার্চুয়াল পদ্ধতি সংজ্ঞায়িত করে না, সুতরাং ভার্চুয়াল কলগুলি মোটেই প্রয়োজন হয় না।
ম্যাট ক্রেগ

24

আমি জানি, পারফরম্যান্স বেনিফিটের কোনও গ্যারান্টি নেই। তবে সিলযুক্ত পদ্ধতিতে কিছু নির্দিষ্ট শর্তে পারফরম্যান্স পেনাল্টি হ্রাস করার সুযোগ রয়েছে । (সিল করা ক্লাস সমস্ত পদ্ধতি সিল করে দেওয়ার জন্য করে))

তবে এটি বাস্তবায়ন এবং কার্যকর পরিবেশের সংকলন করে।


বিস্তারিত

আধুনিক অনেক সিপিইউ কর্মক্ষমতা বাড়াতে দীর্ঘ পাইপলাইন কাঠামো ব্যবহার করে। সিপিইউ মেমরির চেয়ে অবিশ্বাস্যভাবে দ্রুত, সিপিইউকে পাইপলাইন ত্বরান্বিত করতে মেমরি থেকে কোড প্রিফেচ করতে হয়। কোডটি যথাযথ সময়ে প্রস্তুত না হলে পাইপলাইনগুলি অলস হয়ে যাবে।

ডায়নামিক প্রেরণ নামে একটি বড় বাধা রয়েছে যা এই 'প্রিফেচিং' অপটিমাইজেশন ব্যাহত করে। আপনি এটি কেবল একটি শর্তাধীন শাখা হিসাবে বুঝতে পারেন।

// Value of `v` is unknown,
// and can be resolved only at runtime.
// CPU cannot know which code to prefetch.
// Therefore, just prefetch any one of a() or b().
// This is *speculative execution*.
int v = random();
if (v==1) a();
else b();

সিপিইউ এই ক্ষেত্রে কার্যকর করার জন্য পরবর্তী কোডটি উপস্থাপন করতে পারে না কারণ শর্তটি সমাধান না হওয়া পর্যন্ত পরবর্তী কোড অবস্থানটি অজানা। সুতরাং এটি বিপত্তিটি পাইপলাইনকে নিষ্ক্রিয় করে তোলে । এবং অলস দ্বারা পারফরম্যান্স পেনাল্টি নিয়মিতভাবে বিশাল।

পদ্ধতি ওভাররাইডের ক্ষেত্রেও একই ঘটনা ঘটে। সংকলক বর্তমান পদ্ধতি কলের জন্য যথাযথ পদ্ধতি ওভাররাইড নির্ধারণ করতে পারে তবে কখনও কখনও এটি অসম্ভব। এই ক্ষেত্রে, সঠিক পদ্ধতিটি কেবল রানটাইমে নির্ধারণ করা যায়। এটি গতিশীল প্রেরণেরও একটি ঘটনা এবং, গতিশীল টাইপযুক্ত ভাষার মূল কারণ সাধারণত স্ট্যাটিকালি-টাইপ করা ভাষার চেয়ে ধীর হয়।

কিছু সিপিইউ (সাম্প্রতিক ইন্টেলের x86 চিপস সহ) পরিস্থিতি সম্পর্কেও পাইপলাইন ব্যবহার করতে অনুমানমূলক এক্সিকিউশন নামক কৌশল ব্যবহার করে। মৃত্যুদন্ড কার্যকর করার পথে কেবল একটি প্রিফেচ করুন। তবে এই কৌশলটির হিট রেট এত বেশি নয়। এবং জল্পনা ব্যর্থতা পাইপলাইন স্টলের কারণ বিশাল কর্মক্ষমতা জরিমানা করে তোলে। (এটি পুরোপুরি সিপিইউ বাস্তবায়নের মাধ্যমে some কিছু মোবাইল সিপিইউ শক্তি সঞ্চয় করতে এই ধরণের অপ্টিমাইজেশন হিসাবে পরিচিত না)

মূলত, সি # একটি স্ট্যাটিকালি সংকলিত ভাষা is তবে সব সময় নয়. আমি সঠিক অবস্থা জানি না এবং এটি সম্পূর্ণরূপে সংকলক বাস্তবায়নের উপর নির্ভর করে। কিছু সংকলক পদ্ধতিটি চিহ্নিত করা থাকলে পদ্ধতিকে ওভাররাইড করে প্রতিরোধ করে গতিশীল প্রেরণের সম্ভাবনা দূর করতে পারে sealed। বোকা সংকলক নাও পারে। এটি এর পারফরম্যান্স সুবিধা sealed


এই উত্তরটি ( অরসেটেড অ্যারের চেয়ে বাছাই করা অ্যারে প্রক্রিয়া করা কেন দ্রুত? ) শাখার পূর্বাভাসটি আরও ভালভাবে বর্ণনা করছে।


1
পেন্টিয়াম শ্রেণীর সিপিইউগুলি প্রত্যক্ষভাবে পরোক্ষ প্রেরণ। কখনও কখনও ফাংশন পয়েন্টার পুনর্নির্দেশ এই কারণে যদি (অস্পষ্ট) তুলনায় দ্রুত হয়।
জোশুয়া

2
নন ভার্চুয়াল বা সিল করা ফাংশনটির একটি সুবিধা হ'ল এগুলি আরও পরিস্থিতিতে ইনলাইন করা যেতে পারে।
কোডসইনচাওস

4

<প্রসঙ্গ-বহির্ভূত-গলাবাজি>

আমি সিল ক্লাস ঘৃণা । এমনকি পারফরম্যান্সের সুবিধাগুলি চমকপ্রদ হলেও (যা আমি সন্দেহ করি), তারা উত্তরাধিকারের মাধ্যমে পুনরায় ব্যবহার প্রতিরোধ করে অবজেক্ট-ওরিয়েন্টেড মডেলটিকে ধ্বংস করে। উদাহরণস্বরূপ, থ্রেড ক্লাসটি সিল করা হয়েছে। যদিও আমি দেখতে পাচ্ছি যে থ্রেডগুলি যতটা সম্ভব দক্ষ হতে পারে, আমি এমন পরিস্থিতিতেও কল্পনা করতে পারি যেখানে থ্রেড সাবক্লাস করতে সক্ষম হওয়ায় দুর্দান্ত সুবিধা হবে benefits শ্রেণীর লেখকগণ, যদি আপনাকে অবশ্যই "পারফরম্যান্স" কারণে আপনার ক্লাসগুলি সিল করতে হয় তবে দয়া করে খুব কমপক্ষে একটি ইন্টারফেস সরবরাহ করুন যাতে আপনার ভুলে যাওয়া বৈশিষ্ট্যটির যে কোনও জায়গায় আমাদের মোড়ক-এবং-প্রতিস্থাপন করতে হবে না।

উদাহরণ: সেফথ্রেডকে থ্রেড শ্রেণিটি আবদ্ধ করতে হয়েছিল কারণ থ্রেড সিল করা হয়েছে এবং কোনও আইথ্রেড ইন্টারফেস নেই; SafeThread স্বয়ংক্রিয়ভাবে থ্রেডগুলিতে আনহ্যান্ডেল ব্যতিক্রমগুলিকে আটকে দেয়, থ্রেড শ্রেণীর থেকে সম্পূর্ণ অনুপস্থিত। [এবং কোন Unhandled ব্যতিক্রম ঘটনা না না আপ মাধ্যমিক থ্রেডের মধ্যে অপরিচালিত ব্যতিক্রম বাছাই]।

</ অফ-বিষয়-গলাবাজি>


35
পারফরম্যান্সের কারণে আমি আমার ক্লাস সিল করি না। আমি ডিজাইন কারণে তাদের সিল। উত্তরাধিকারের জন্য নকশা করা কঠিন এবং সেই প্রচেষ্টা বেশিরভাগ সময় নষ্ট হবে। যদিও ইন্টারফেস সরবরাহ সম্পর্কে আমি সম্পূর্ণরূপে একমত - এটি ক্লাসগুলি অনিলিকরণের থেকে অনেক উচ্চতর সমাধান।
জন স্কিটি

6
উত্তরাধিকারের চেয়ে সাধারণত এনক্যাপসুলেশন একটি ভাল সমাধান। আপনার নির্দিষ্ট থ্রেডের উদাহরণটি ধরতে, থ্রেডের ব্যতিক্রমগুলি আটকে ফেলার ফলে লিসকভ সাবস্টিটিউশন নীতিটি ভেঙে যায় কারণ আপনি থ্রেড ক্লাসের নথিভুক্ত আচরণটি পরিবর্তন করেছেন, এমনকি যদি আপনি এটি থেকে উদ্ভূত হতে পারেন, তবে আপনি যে কোনও জায়গায় সেফথ্রেড ব্যবহার করতে পারবেন তা বলা যুক্তিসঙ্গত হবে না আপনি থ্রেড ব্যবহার করতে পারে। এই ক্ষেত্রে, আপনি থ্রেডকে অন্য শ্রেণিতে আবদ্ধ করা ভাল যা বিভিন্ন নথিভুক্ত আচরণ করে, যা আপনি করতে সক্ষম। কখনও কখনও জিনিস আপনার নিজের ভাল জন্য সিল করা হয়।
গ্রেগ বিচ

1
@ [গ্রেগ বিচ]: মতামত, সত্য নয় - থ্রেড থেকে তার নকশায় একটি জঘন্য তদারকি ঠিক করার পক্ষে উত্তরাধিকারী হতে সক্ষম হওয়া কোনও খারাপ জিনিস নয় ;-) এবং আমি মনে করি আপনি এলএসপিকে ছাড়িয়ে যাচ্ছেন - প্রবণতাযুক্ত সম্পত্তি Q (x) এই কেসটি 'একটি অযৌক্তিক ব্যতিক্রম প্রোগ্রামটিকে ধ্বংস করে দেয়' যা "কাঙ্ক্ষিত সম্পত্তি" নয় :-)
স্টিভেন এ লো লো

1
না, তবে আমার ক্র্যাপী কোডটিতে আমার অংশ রয়েছে যেখানে আমি অন্য বিকাশকারীদের আমার স্টাফটি সিল না করে বা কর্নারের ক্ষেত্রে অনুমতি না দিয়ে অপব্যবহার করতে সক্ষম করেছিলাম। আমার আজকাল বেশিরভাগ কোড হ'ল আসক্তি এবং অন্যান্য চুক্তি সম্পর্কিত জিনিস। এবং আমি এই কথাটি সম্পর্কে সম্পূর্ণ উন্মুক্ত যে আমি কেবল *** এর ব্যথা হওয়ার জন্য এটি করি।
টিউরিং সম্পূর্ণ

2
যেহেতু আমরা এখানে একটি rants প্রসঙ্গ-বহির্ভূত বন্ধ করছি, ঠিক মত আপনি ঘৃণা সিল ক্লাস, আমি ঘৃণা গ্রস্ত ব্যতিক্রম। কিছু যখন মাইসআপে যায় তখন তার চেয়ে খারাপ কিছুই নেই তবে প্রোগ্রামটি চালিত হয়। জাভাস্ক্রিপ্ট আমার প্রিয়। আপনি কিছু কোডে পরিবর্তন আনলেন এবং হঠাৎ বোতামে ক্লিক করা একেবারেই কিছুই করে না। গ্রেট! এএসপি.এনইটি এবং আপডেটপ্যানেল হ'ল আরেকটি; গুরুত্ব সহকারে, যদি আমার বোতাম হ্যান্ডলারটি এটি একটি বড় চুক্তি ছুঁড়ে ফেলে এবং এটি ক্র্যাশ করা দরকার, যাতে আমি জানি যে এমন কিছু আছে যা ঠিক করার প্রয়োজন! একটি বোতাম যা কিছুই না করে ক্র্যাশ স্ক্রিনটি নিয়ে আসে এমন বোতামের চেয়ে বেশি বেহুদা!
রোমান স্টারকভ

4

শ্রেণি চিহ্নিত করার sealedকোনও কার্যকারিতা প্রভাবিত হওয়া উচিত নয়।

এমন কেস রয়েছে যেখানে অপকোডের পরিবর্তে cscএকটি callvirtঅপকোড ছাড়তে হতে পারে call। তবে মনে হয় এই ঘটনাগুলি বিরল।

এবং এটি আমার কাছে মনে হয় যে JIT এর জন্য একই অ-ভার্চুয়াল ফাংশন কলটি callvirtসরিয়ে দিতে সক্ষম হবে call, যদি এটি জানে যে শ্রেণীর কোনও সাবক্লাস নেই (এখনও)। যদি পদ্ধতির শুধুমাত্র একটি বাস্তবায়ন বিদ্যমান থাকে তবে কোনও ভিটিবেল থেকে এর ঠিকানা লোড করার কোনও মানে নেই — কেবলমাত্র একটি বাস্তবায়নকে সরাসরি কল করুন। এই বিষয়টির জন্য, জেআইটি এমনকি ফাংশনটি ইনলাইন করতে পারে।

এটা জে আই টি JIT এর পক্ষ থেকে একটি জুয়া একটি বিট কারণ একটি উপশ্রেণী হয় পরে লোড, জে আই টি JIT দূরে যে মেশিন কোড নিক্ষেপ এবং কোড আবার কম্পাইল, একটি বাস্তব ভার্চুয়াল কল emitting করতে হবে। আমার অনুমান যে অনুশীলনে প্রায়শই এটি ঘটে না।

(এবং হ্যাঁ, ভিএম ডিজাইনাররা এই ক্ষুদ্র পারফরম্যান্সের জয়ের পিছনে সত্যিই আক্রমণাত্মকভাবে কাজ করে))


3

সিলযুক্ত ক্লাসগুলির একটি কর্মক্ষমতা উন্নতি করা উচিত । যেহেতু একটি সিল করা শ্রেণি তৈরি করা যায় না, তাই কোনও ভার্চুয়াল সদস্যকে নন-ভার্চুয়াল সদস্যগুলিতে পরিণত করা যায়।

অবশ্যই, আমরা সত্যিই ছোট লাভের কথা বলছি। আমি কোনও ক্লাস চিহ্নিত না করে কেবল একটি পারফরম্যান্স উন্নতি পেতে সীল হিসাবে চিহ্নিত করি না যতক্ষণ না প্রোফাইলিং এটি সমস্যা হিসাবে প্রকাশ না করে।


তাদের উচিত , তবে এটি প্রদর্শিত হয় না। সিএলআর যদি নন-নাল রেফারেন্স ধরণের ধারণা রাখে তবে একটি সিল করা ক্লাসটি আরও ভাল হবে, কারণ সংকলকটি callপরিবর্তে নির্গত হতে পারে callvirt... আমি আরও অনেক কারণে নন-নাল রেফারেন্স ধরণের পছন্দ করতাম ... দীর্ঘশ্বাস :-(
অরিওন এডওয়ার্ডস

3

আমি "সিলড" ক্লাসগুলিকে সাধারণ ক্ষেত্রে বিবেচনা করি এবং আমার কাছে "সিলড" কীওয়ার্ডটি বাদ দেওয়ার সবসময় কারণ রয়েছে।

আমার জন্য সবচেয়ে গুরুত্বপূর্ণ কারণগুলি হ'ল:

ক) আরও ভাল সংকলন সময় চেক (প্রয়োগ করা হয়নি ইন্টারফেসে কাস্টিং কেবল রানটাইম সময় নয়, সংকলন সময়ে সনাক্ত করা হবে)

এবং, শীর্ষ কারণ:

খ) আমার ক্লাসগুলির অপব্যবহার সেভাবে সম্ভব নয়

আমি আশা করি মাইক্রোসফ্ট "সিল করা" মান তৈরি করেছিল, "সিল না করে"।


আমি বিশ্বাস করি "বাদ দেওয়া" (ছেড়ে দিতে) "নির্গত" (উত্পাদন করতে) হওয়া উচিত?
ব্যবহারকারী 2864740

2

@ বৈভব, আপনি পারফরম্যান্স পরিমাপ করতে কোন ধরণের পরীক্ষা করেছেন?

আমি অনুমান করি যে একজনকে রটার ব্যবহার করতে হবে এবং সিএলআইতে ড্রিল করতে হবে এবং বুঝতে হবে কীভাবে সিল করা ক্লাস পারফরম্যান্সে উন্নতি করবে।

এসএসসিএলআই (রটার)
এসএসসিএলআই: ভাগ করা উত্স প্রচলিত ভাষার অবকাঠামো

কমন ল্যাঙ্গুয়েজ ইনফ্রাস্ট্রাকচার (সিএলআই) হ'ল ইসিএমএ স্ট্যান্ডার্ড যা .NET ফ্রেমওয়ার্কের মূল বর্ণনা করে। শেয়ার্ড সোর্স সিএলআই (এসএসসিএলআই), যাকে রটার নামেও পরিচিত, এটি ইসিএমএ সিএলআই এবং ইসিএমএ সি # ভাষার স্পেসিফিকেশন, মাইক্রোসফ্টের .NET আর্কিটেকচারের কেন্দ্রস্থলে প্রযুক্তির কার্যকরী বাস্তবায়নের উত্স কোডের একটি সংকুচিত সংরক্ষণাগার।


পরীক্ষায় একটি ক্লাস শ্রেণিবদ্ধতা অন্তর্ভুক্ত ছিল, এমন কয়েকটি পদ্ধতি যা ডামি কাজ করছিল (বেশিরভাগ ক্ষেত্রে স্ট্রিং ম্যানিপুলেশন)। এর মধ্যে কয়েকটি পদ্ধতি ভার্চুয়াল ছিল। তারা একে অপরকে এখানে এবং সেখানে ডাকছিল। তারপরে এই পদ্ধতিগুলিকে 100, 10000, এবং 100000 বার কল করুন ... এবং সময়টি পরিমাপ করতে পেরে গেল। তারপরে সিল করা হিসাবে ক্লাস চিহ্নিত করার পরে এগুলি চালাচ্ছেন। এবং আবার পরিমাপ। তাদের মধ্যে কোনও পার্থক্য নেই।
বৈভব

2

সিল করা ক্লাসগুলি কমপক্ষে একটি সামান্য বিট দ্রুত হবে, তবে কখনও কখনও ওয়াইয়াই দ্রুত হতে পারে ... যদি জেআইটি অপ্টিমাইজারটি কলগুলি ইনলাইন করতে পারে যা অন্যথায় ভার্চুয়াল কল হত। সুতরাং, যেখানে অফ-অফ-পদ্ধতিযুক্ত পদ্ধতিগুলি রয়েছে যা অন্তর্ভুক্ত করার জন্য যথেষ্ট ছোট, সেখানে অবশ্যই ক্লাসটি সিলিংয়ের বিষয়টি বিবেচনা করুন।

তবে ক্লাসটি সিল করার সর্বোত্তম কারণটি হ'ল "আমি এটিকে উত্তরাধিকারসূত্রে প্রাপ্ত করার জন্য ডিজাইন করি নি, তাই এটি এমনভাবে ডিজাইন করা হয়েছিল তা ধরে নিয়ে আপনাকে জ্বলতে দেব না, এবং আমি যাচ্ছি না নিজেকে বাস্তবায়নের জন্য আটকে রেখে নিজেকে পোড়াতে, কারণ আমি আপনাকে এটি থেকে উদ্ভূত করতে দিয়েছি। "

আমি জানি এখানে কেউ কেউ বলেছে যে তারা সিলড ক্লাসগুলি ঘৃণা করেছে কারণ তারা যে কোনও কিছু থেকে উদ্ভূত হওয়ার সুযোগ চায় ... তবে এটি সবচেয়ে বেশি রক্ষণাবেক্ষণযোগ্য পছন্দ নয় ... কারণ কোনও শ্রেণিটি ডাইরিভিশন থেকে প্রকাশ করা আপনাকে সমস্ত বিষয় উন্মোচন না করেই আরও অনেক বেশি লক করে রাখে all যে। এটির সাথে অনুরূপ "আমি ব্যক্তিগত ক্লাবগুলির এমন ক্লাসকে ঘৃণা করি ... আমি প্রায়শই ক্লাসটি যা করতে চাই তা করতে পারি না কারণ আমার অ্যাক্সেস নেই।" এনক্যাপসুলেশন গুরুত্বপূর্ণ ... সিলিং হ'ল এনক্যাপসুলেশনের একটি রূপ।


সি # সংকলকটি এখনও callvirtসিলড ক্লাসগুলিতে উদাহরণ পদ্ধতিগুলির জন্য (ভার্চুয়াল পদ্ধতি কল) ব্যবহার করবে কারণ এটি এখনও তাদের উপর একটি নাল-অবজেক্ট চেক করতে হবে। ইনলাইনিংয়ের বিষয়ে, সিএলআর জেআইটি ইনলাইন ভার্চুয়াল পদ্ধতিতে সিল এবং অ সিল না হওয়া উভয় শ্রেণির জন্য কল করতে পারে (এবং করে) ... তাই হ্যাঁ। পারফরম্যান্স জিনিসটি একটি মিথ।
অরিওন এডওয়ার্ডস

1

এগুলিকে দেখতে সত্যিই আপনাকে জেআইটি-সংকলিত কোড ই (শেষ একটি) বিশ্লেষণ করতে হবে ।

সি # কোড

public sealed class Sealed
{
    public string Message { get; set; }
    public void DoStuff() { }
}
public class Derived : Base
{
    public sealed override void DoStuff() { }
}
public class Base
{
    public string Message { get; set; }
    public virtual void DoStuff() { }
}
static void Main()
{
    Sealed sealedClass = new Sealed();
    sealedClass.DoStuff();
    Derived derivedClass = new Derived();
    derivedClass.DoStuff();
    Base BaseClass = new Base();
    BaseClass.DoStuff();
}

মিল কোড

.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       41 (0x29)
  .maxstack  8
  IL_0000:  newobj     instance void ConsoleApp1.Program/Sealed::.ctor()
  IL_0005:  callvirt   instance void ConsoleApp1.Program/Sealed::DoStuff()
  IL_000a:  newobj     instance void ConsoleApp1.Program/Derived::.ctor()
  IL_000f:  callvirt   instance void ConsoleApp1.Program/Base::DoStuff()
  IL_0014:  newobj     instance void ConsoleApp1.Program/Base::.ctor()
  IL_0019:  callvirt   instance void ConsoleApp1.Program/Base::DoStuff()
  IL_0028:  ret
} // end of method Program::Main

জেআইটি- সংকলিত কোড

--- C:\Users\Ivan Porta\source\repos\ConsoleApp1\Program.cs --------------------
        {
0066084A  in          al,dx  
0066084B  push        edi  
0066084C  push        esi  
0066084D  push        ebx  
0066084E  sub         esp,4Ch  
00660851  lea         edi,[ebp-58h]  
00660854  mov         ecx,13h  
00660859  xor         eax,eax  
0066085B  rep stos    dword ptr es:[edi]  
0066085D  cmp         dword ptr ds:[5842F0h],0  
00660864  je          0066086B  
00660866  call        744CFAD0  
0066086B  xor         edx,edx  
0066086D  mov         dword ptr [ebp-3Ch],edx  
00660870  xor         edx,edx  
00660872  mov         dword ptr [ebp-48h],edx  
00660875  xor         edx,edx  
00660877  mov         dword ptr [ebp-44h],edx  
0066087A  xor         edx,edx  
0066087C  mov         dword ptr [ebp-40h],edx  
0066087F  nop  
            Sealed sealedClass = new Sealed();
00660880  mov         ecx,584E1Ch  
00660885  call        005730F4  
0066088A  mov         dword ptr [ebp-4Ch],eax  
0066088D  mov         ecx,dword ptr [ebp-4Ch]  
00660890  call        00660468  
00660895  mov         eax,dword ptr [ebp-4Ch]  
00660898  mov         dword ptr [ebp-3Ch],eax  
            sealedClass.DoStuff();
0066089B  mov         ecx,dword ptr [ebp-3Ch]  
0066089E  cmp         dword ptr [ecx],ecx  
006608A0  call        00660460  
006608A5  nop  
            Derived derivedClass = new Derived();
006608A6  mov         ecx,584F3Ch  
006608AB  call        005730F4  
006608B0  mov         dword ptr [ebp-50h],eax  
006608B3  mov         ecx,dword ptr [ebp-50h]  
006608B6  call        006604A8  
006608BB  mov         eax,dword ptr [ebp-50h]  
006608BE  mov         dword ptr [ebp-40h],eax  
            derivedClass.DoStuff();
006608C1  mov         ecx,dword ptr [ebp-40h]  
006608C4  mov         eax,dword ptr [ecx]  
006608C6  mov         eax,dword ptr [eax+28h]  
006608C9  call        dword ptr [eax+10h]  
006608CC  nop  
            Base BaseClass = new Base();
006608CD  mov         ecx,584EC0h  
006608D2  call        005730F4  
006608D7  mov         dword ptr [ebp-54h],eax  
006608DA  mov         ecx,dword ptr [ebp-54h]  
006608DD  call        00660490  
006608E2  mov         eax,dword ptr [ebp-54h]  
006608E5  mov         dword ptr [ebp-44h],eax  
            BaseClass.DoStuff();
006608E8  mov         ecx,dword ptr [ebp-44h]  
006608EB  mov         eax,dword ptr [ecx]  
006608ED  mov         eax,dword ptr [eax+28h]  
006608F0  call        dword ptr [eax+10h]  
006608F3  nop  
        }
0066091A  nop  
0066091B  lea         esp,[ebp-0Ch]  
0066091E  pop         ebx  
0066091F  pop         esi  
00660920  pop         edi  
00660921  pop         ebp  

00660922  ret  

বস্তুগুলির সৃষ্টি একইরূপে সিলযুক্ত ও উত্পন্ন / বেস শ্রেণীর পদ্ধতিগুলির অনুরোধ করার জন্য সম্পাদিত নির্দেশ কিছুটা পৃথক। রেজিস্ট্রি বা র‌্যাম (মুভ ইন্সট্রাকশন) এ ডেটা স্থানান্তরিত করার পরে, সিল করা পদ্ধতির অনুরোধ, ডায়র্ট পিটিআর [ইকএক্স], ই্যাক্স (সিএমপি নির্দেশ) এর মধ্যে একটি তুলনা কার্যকর করুন এবং তারপরে ড্রেভড / বেস ক্লাসটি সরাসরি পদ্ধতিটি কার্যকর করার সময় পদ্ধতিটি কল করুন। ।

টরবজোরন গ্রানলুন্ডের লেখা প্রতিবেদন অনুসারে, এএমডি এবং ইন্টেল এক্স ৮ process প্রসেসরের জন্য নির্দেশের ল্যাটেন্সি এবং থ্রুপুট , একটি ইন্টেল পেন্টিয়াম 4 এ নিম্নলিখিত নির্দেশগুলির গতি হ'ল :

  • মুভি : লেটেন্সি হিসাবে 1 টি চক্র রয়েছে এবং প্রসেসরের এই ধরণের প্রতি চক্রের 2.5 নির্দেশাবলী বজায় রাখতে পারে
  • সিএমপি : লেটেন্সি হিসাবে 1 টি চক্র রয়েছে এবং প্রসেসর এই ধরণের চক্রের জন্য 2 টি নির্দেশনা বজায় রাখতে পারে

লিঙ্ক : https://gmplib.org/~tege/x86-timing.pdf

এর অর্থ হ'ল , আদর্শভাবে , একটি সিলযুক্ত পদ্ধতি আহ্বান করার জন্য প্রয়োজনীয় সময়টি 2 চক্র হয় যখন একটি উত্পন্ন বা বেস শ্রেণির পদ্ধতিটি আহ্বানের জন্য প্রয়োজনীয় সময়টি 3 চক্র।

সংকলকগুলির অপ্টিমাইজেশানটি একটি সিলযুক্ত এবং সিল না হওয়া সীমাবদ্ধ পারফরম্যান্সের মধ্যে পার্থক্যকে এতটা কম করেছে যে আমরা প্রসেসরের চেনাশোনাগুলির বিষয়ে কথা বলছি এবং এজন্য বেশিরভাগ অ্যাপ্লিকেশনগুলির জন্য অপ্রাসঙ্গিক।


-10

এই কোডটি চালান এবং আপনি দেখতে পাবেন যে সিল করা ক্লাসগুলি 2 গুণ দ্রুত:

class Program
{
    static void Main(string[] args)
    {
        Console.ReadLine();

        var watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < 10000000; i++)
        {
            new SealedClass().GetName();
        }
        watch.Stop();
        Console.WriteLine("Sealed class : {0}", watch.Elapsed.ToString());

        watch.Start();
        for (int i = 0; i < 10000000; i++)
        {
            new NonSealedClass().GetName();
        }
        watch.Stop();
        Console.WriteLine("NonSealed class : {0}", watch.Elapsed.ToString());

        Console.ReadKey();
    }
}

sealed class SealedClass
{
    public string GetName()
    {
        return "SealedClass";
    }
}

class NonSealedClass
{
    public string GetName()
    {
        return "NonSealedClass";
    }
}

আউটপুট: সিল করা শ্রেণি: 00: 00: 00.1897568 নন সিল ক্লাস: 00: 00: 00.3826678


9
এটি নিয়ে বেশ কয়েকটি সমস্যা রয়েছে। প্রথম বন্ধ, আপনি প্রথম এবং দ্বিতীয় পরীক্ষার মধ্যে স্টপওয়াচটি পুনরায় সেট করছেন না। দ্বিতীয়ত, আপনি যে পদ্ধতিটিতে কল করছেন তার অর্থ হ'ল সমস্ত ওপ কোডগুলি কল কল্ট কল কল হবে না যাতে প্রকারটি বিবেচনা করে না।
ক্যামেরন ম্যাকফারল্যান্ড

1
রুসলানজি, আপনি ঘড়ির কল করতে ভুলে গেছেন first প্রথম পরীক্ষা চালানোর পরে পুনরায় সেট করুন ()। o_O:]

হ্যাঁ, উপরের কোডটিতে বাগ রয়েছে। তারপরে আবার কোডটিতে ভুল পরিচয় দেওয়ার জন্য কে নিজেরাই বড়াই করতে পারে? তবে এই উত্তরের সাথে অন্য সকলের চেয়ে একটি গুরুত্বপূর্ণ বিষয় রয়েছে: এটি প্রশ্নে প্রভাবটি পরিমাপ করার চেষ্টা করে। এবং এই উত্তরটিও আপনার সকলের জন্য পরিদর্শন করা এবং [ভর -] ডাউনভোটের কোডও ভাগ করে দেয় (আমি কেন অবাক হয়েছি কেন গণ-ডাউনভোটিং প্রয়োজনীয়?)। অন্য উত্তরগুলির বিপরীতে। এটি আমার মতে শ্রদ্ধার প্রাপ্য ... এছাড়াও দয়া করে নোট করুন যে ব্যবহারকারী নবাগত, তাই খুব একটা স্বাগত পদ্ধতির নয়। কিছু সাধারণ ফিক্স এবং এই কোডটি আমাদের সবার জন্য কার্যকর হয়ে ওঠে। স্থির করুন + স্থির সংস্করণ ভাগ করুন, যদি আপনার সাহস হয়
রোল্যান্ড পিহলাকাস

আমি @ রোল্যান্ডপিহলাকাসের সাথে একমত নই। যেমন আপনি বলেছিলেন, "কোডে ভুলের পরিচয় দেওয়ার জন্য কে নিজেরাই বড়াই করতে পারে"। উত্তর -> না, কিছুই নেই। তবে সে কথাটি নয়। মুল বক্তব্যটি হ'ল এটি একটি ভুল তথ্য যা অন্য নতুন প্রোগ্রামারকে বিভ্রান্ত করতে পারে। অনেকে সহজেই মিস করতে পারেন যে স্টপওয়াচটি পুনরায় সেট করা হয়নি। তারা বিশ্বাস করতে পারে যে মানদণ্ডের তথ্যটি সত্য। এর চেয়ে বেশি ক্ষতিকারক না? যে কেউ দ্রুত উত্তর খুঁজছেন সে এই মন্তব্যগুলি নাও পড়তে পারে, বরং সে একটি উত্তর দেখতে পাবে এবং সে বিশ্বাস করতে পারে।
এমরান হুসেন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.