दिलचस्प पोस्ट
एंड्रॉइड छवि देखें पिंच ज़ूमिंग UITextField के लिए केवल अल्फ़ान्यूमेरिक वर्णों की अनुमति दें Concat JSON ऑब्जेक्ट्स सबसे अच्छा PHP इनपुट सफाई कार्यों क्या हैं? जावास्क्रिप्ट नामकरण सम्मेलनों Symfony2 वैचारिक मुद्दा: सामान्य बंडल बनाम विशिष्ट वाले जांचें कि क्या कोई चेतावनी अजगर के साथ सेलेनियम का उपयोग कर रहा है एच 2 इन-मेमोरी डेटाबेस। तालिका नहीं मिली रन-टाइम में अनुदान अनुमतियों की जांच कैसे करें? डी 3 नोड लेबलिंग UIImage की उच्च गुणवत्ता स्केलिंग क्या कस्टम तत्व वैध HTML5 हैं? iPhone ऐप स्थानीयकरण – अंग्रेजी समस्याएं? PHP में यूआरएल स्ट्रिंग से मैं क्वेरी मापदंड कैसे निकालूं? कई-से-कई पुनरावर्ती रिश्तेिंग कोड को आत्म-संदर्भित करने वाला पहला इकाई फ़्रेमवर्क

सी # 'है' ऑपरेटर का प्रदर्शन

मेरे पास एक प्रोग्राम है जिसमें तीव्र प्रदर्शन की आवश्यकता है इसके अंदरूनी लूपों में से एक को देखने के लिए मुझे किसी वस्तु के प्रकार का परीक्षण करना होगा कि क्या वह किसी विशिष्ट इंटरफ़ेस से मिलता है या नहीं।

ऐसा करने का एक तरीका सीएलआर के अंतर्निहित प्रकार-जाँच की कार्यक्षमता के साथ होगा। शायद सबसे बढ़िया तरीका है जो कि 'है' कीवर्ड है:

if (obj is ISpecialType) 

एक और तरीका यह है कि आधार वर्ग को अपना आभासी गेटटीप () फ़ंक्शन देना होगा जो पूर्व-परिभाषित एन्यूम मान देता है (मेरे मामले में, वास्तव में, मुझे केवल एक बूल की आवश्यकता है)। यह विधि तेजी से होगी, लेकिन कम सुरुचिपूर्ण

मैंने सुना है कि विशेष रूप से 'है' कीवर्ड के लिए एक आईएल निर्देश है, लेकिन इसका मतलब यह नहीं है कि यह देशी विधानसभा में अनुवादित होने पर तेज़ी से लागू होता है क्या किसी अन्य तरीके से बना 'के' प्रदर्शन के बारे में कुछ अंतर्दृष्टि साझा कर सकता है?

अद्यतनः सभी सूचित उत्तरों के लिए धन्यवाद! ऐसा लगता है कि उत्तर में कुछ उपयोगी बिंदु सामने आये हैं: एंड्रयू का कहना है कि 'स्वचालित रूप से कलाकारों को प्रदर्शन करना' आवश्यक है, लेकिन बाइनरी व्हायरियर और इयान द्वारा एकत्र किए गए प्रदर्शन डेटा भी बेहद उपयोगी है। यह बहुत अच्छा होगा अगर उत्तर में से एक को संपादित किया जाए तो यह सब जानकारी शामिल हो जाएगी।

वेब के समाधान से एकत्रित समाधान "सी # 'है' ऑपरेटर का प्रदर्शन"

का उपयोग करना प्रदर्शन को नुकसान पहुंचा सकता है, यदि आप एक बार टाइप की जांच करते हैं, तो आप उस प्रकार को डालेंगे। वास्तव में वह वस्तु है जिसे आप जाँच रहे हैं उस वस्तु को डाले गए हैं ताकि किसी भी बाद का कास्टिंग अनावश्यक हो।

यदि आप किसी भी तरह कास्ट करने जा रहे हैं, तो यह एक बेहतर तरीका है:

 ISpecialType t = obj as ISpecialType; if (t != null) { // use t here } 

मैं इयान के साथ हूं, शायद आप ऐसा नहीं करना चाहते।

हालांकि, सिर्फ इतना ही, आप जानते हैं, 10,000,000 से अधिक दोहरावों के बीच दोनों के बीच बहुत कम अंतर है

  • Enum चेक 700 मिलीसेकेंड (लगभग) में आता है
  • आईएस जांच 1000 मिलीसेकेंड (लगभग) में आता है

मैं व्यक्तिगत रूप से इस समस्या को इस तरह ठीक नहीं कर सकता, लेकिन अगर मुझे एक विधि चुनने के लिए मजबूर किया गया तो यह आईएस जांच में बनाया जाएगा, प्रदर्शन अंतर कोडिंग ओवरहेड पर विचार करने के लायक नहीं है।

मेरा आधार और व्युत्पन्न कक्षाएं

 class MyBaseClass { public enum ClassTypeEnum { A, B } public ClassTypeEnum ClassType { get; protected set; } } class MyClassA : MyBaseClass { public MyClassA() { ClassType = MyBaseClass.ClassTypeEnum.A; } } class MyClassB : MyBaseClass { public MyClassB() { ClassType = MyBaseClass.ClassTypeEnum.B; } } 

जुबब: जैसा कि परीक्षणों के बारे में अधिक जानकारी के लिए अनुरोध किया गया

मैंने एक कन्सोल ऐप (एक डीबग बिल्ड) से दोनों परीक्षणों का दौरा किया था, प्रत्येक टेस्ट निम्न की तरह दिखता है

 static void IsTest() { DateTime start = DateTime.Now; for (int i = 0; i < 10000000; i++) { MyBaseClass a; if (i % 2 == 0) a = new MyClassA(); else a = new MyClassB(); bool b = a is MyClassB; } DateTime end = DateTime.Now; Console.WriteLine("Is test {0} miliseconds", (end - start).TotalMilliseconds); } 

रिहाई में चल रहा है, मुझे इयान की तरह 60-70 एमएस का अंतर मिलता है।

अतिरिक्त अद्यतन – 25 अक्टूबर 2012
कुछ सालों बाद मैंने इसके बारे में कुछ देखा, कंपाइलर bool b = a is MyClassB छोड़ना चुन सकते हैं bool b = a is MyClassB रिलीज में है क्योंकि बी कहीं भी उपयोग नहीं किया जाता है।

यह कोड । ।

 public static void IsTest() { long total = 0; var a = new MyClassA(); var b = new MyClassB(); var sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 10000000; i++) { MyBaseClass baseRef; if (i % 2 == 0) baseRef = a;//new MyClassA(); else baseRef = b;// new MyClassB(); //bool bo = baseRef is MyClassB; bool bo = baseRef.ClassType == MyBaseClass.ClassTypeEnum.B; if (bo) total += 1; } sw.Stop(); Console.WriteLine("Is test {0} miliseconds {1}", sw.ElapsedMilliseconds, total); } 

। । । लगातार पता चलता है कि लगभग 57 मिलीसेकंड में जांच हो रही है, और इसकी तुलना 29 मिलीसेकंड में आने वाली तुलना में है।

एनबी मैं अभी भी पसंद करता हूं जांचना चाहता हूं, अंतर बहुत छोटा है, इसके बारे में ध्यान रखना

ठीक है, मैं किसी के साथ इस बारे में बात कर रहा था और इस और अधिक परीक्षण करने का फैसला किया। जहाँ तक मैं बता सकता हूं, प्रकार की जानकारी को स्टोर करने के लिए अपने खुद के सदस्य या फ़ंक्शन का परीक्षण करने की तुलना में, दोनों के as और is प्रदर्शन बहुत अच्छा है।

मैंने Stopwatch इस्तेमाल किया, जिसे मैंने अभी सीखा है वह सबसे विश्वसनीय दृष्टिकोण नहीं हो सकता है, इसलिए मैंने भी UtcNow की कोशिश की बाद में, मैंने भी प्रोसेसर के समय दृष्टिकोण की कोशिश की जो UtcNow बनाने के समय के साथ-साथ UtcNow जैसा UtcNow है। मैंने भी कोई आभासी नहीं के साथ आधार कक्षा को पृथक करने की कोशिश की, लेकिन इसमें कोई महत्वपूर्ण प्रभाव नहीं था।

मैं एक ट्रैक्टर Q6600 पर 16 जीबी रैम के साथ भाग गया यहां तक ​​कि 50 मील पुनरावृत्तियों के साथ, संख्याएं अभी भी +/- 50 या इतने मिलिसेक के आसपास उछाल करती हैं इसलिए मैं छोटे मतभेदों में बहुत ज्यादा नहीं पढ़ता।

यह देखने के लिए दिलचस्प था कि x64 तेज बनाया गया था, लेकिन इसे निष्पादित / x86 से धीमी है

x 64 रिलीज़ मोड:
स्टॉपवॉच:
जैसे: 561 एमएमएस
है: 597 मि
आधार संपत्ति: 539ms
बेस फ़ील्ड: 555ms
बेस आरओ क्षेत्र: 552 मि
आभासी GetEnumType () परीक्षा: 556ms
आभासी आईबी () परीक्षा: 588 एमएमएस
समय बनाएं: 10416 एमएमएस

UtcNow:
जैसे: 49 9एमएस
है: 532 एमएमएस
आधार संपत्ति: 47 9
बेस फ़ील्ड: 502ms
बेस आरओ क्षेत्र: 491 एमएमएस
आभासी GetEnumType (): 502ms
वर्चुअल बूल आईएसबी (): 522एमएस
समय बनाएं: 285 एमएमएस (यह नंबर यूटकेएनओ के साथ अविश्वसनीय लगता है। मुझे 109 एम और 806 एमएमएस भी मिलते हैं।)

x86 रिलीज़ मोड:
स्टॉपवॉच:
जैसा: 391 एमएमएस
है: 423 एमएमएस
आधार संपत्ति: 36 9एमएस
बेस फ़ील्ड: 321 एमएमएस
बेस आरओ क्षेत्र: 33 9एमएस
आभासी GetEnumType () परीक्षण: 361ms
वर्चुअल आईएसबी () परीक्षा: 365 एमएमएस
समय बनाएं: 14106 एमएमएस

UtcNow:
जैसे: 348 एमएमएस
है: 375ms
आधार संपत्ति: 32 9एमएस
बेस फ़ील्ड: 286ms
बेस आरओ क्षेत्र: 30 9एमएस
आभासी GetEnumType (): 321ms
वर्चुअल बूल आईएसबी (): 332 एमएमएस
समय बनाएं: 544 एमएस (यह नंबर यूटीएनएनओ के साथ अविश्वसनीय लगता है।)

यहां अधिकांश कोड हैं:

  static readonly int iterations = 50000000; void IsTest() { Process.GetCurrentProcess().ProcessorAffinity = (IntPtr)1; MyBaseClass[] bases = new MyBaseClass[iterations]; bool[] results1 = new bool[iterations]; Stopwatch createTime = new Stopwatch(); createTime.Start(); DateTime createStart = DateTime.UtcNow; for (int i = 0; i < iterations; i++) { if (i % 2 == 0) bases[i] = new MyClassA(); else bases[i] = new MyClassB(); } DateTime createStop = DateTime.UtcNow; createTime.Stop(); Stopwatch isTimer = new Stopwatch(); isTimer.Start(); DateTime isStart = DateTime.UtcNow; for (int i = 0; i < iterations; i++) { results1[i] = bases[i] is MyClassB; } DateTime isStop = DateTime.UtcNow; isTimer.Stop(); CheckResults(ref results1); Stopwatch asTimer = new Stopwatch(); asTimer.Start(); DateTime asStart = DateTime.UtcNow; for (int i = 0; i < iterations; i++) { results1[i] = bases[i] as MyClassB != null; } DateTime asStop = DateTime.UtcNow; asTimer.Stop(); CheckResults(ref results1); Stopwatch baseMemberTime = new Stopwatch(); baseMemberTime.Start(); DateTime baseStart = DateTime.UtcNow; for (int i = 0; i < iterations; i++) { results1[i] = bases[i].ClassType == MyBaseClass.ClassTypeEnum.B; } DateTime baseStop = DateTime.UtcNow; baseMemberTime.Stop(); CheckResults(ref results1); Stopwatch baseFieldTime = new Stopwatch(); baseFieldTime.Start(); DateTime baseFieldStart = DateTime.UtcNow; for (int i = 0; i < iterations; i++) { results1[i] = bases[i].ClassTypeField == MyBaseClass.ClassTypeEnum.B; } DateTime baseFieldStop = DateTime.UtcNow; baseFieldTime.Stop(); CheckResults(ref results1); Stopwatch baseROFieldTime = new Stopwatch(); baseROFieldTime.Start(); DateTime baseROFieldStart = DateTime.UtcNow; for (int i = 0; i < iterations; i++) { results1[i] = bases[i].ClassTypeField == MyBaseClass.ClassTypeEnum.B; } DateTime baseROFieldStop = DateTime.UtcNow; baseROFieldTime.Stop(); CheckResults(ref results1); Stopwatch virtMethTime = new Stopwatch(); virtMethTime.Start(); DateTime virtStart = DateTime.UtcNow; for (int i = 0; i < iterations; i++) { results1[i] = bases[i].GetClassType() == MyBaseClass.ClassTypeEnum.B; } DateTime virtStop = DateTime.UtcNow; virtMethTime.Stop(); CheckResults(ref results1); Stopwatch virtMethBoolTime = new Stopwatch(); virtMethBoolTime.Start(); DateTime virtBoolStart = DateTime.UtcNow; for (int i = 0; i < iterations; i++) { results1[i] = bases[i].IsB(); } DateTime virtBoolStop = DateTime.UtcNow; virtMethBoolTime.Stop(); CheckResults(ref results1); asdf.Text += "Stopwatch: " + Environment.NewLine + "As: " + asTimer.ElapsedMilliseconds + "ms" + Environment.NewLine +"Is: " + isTimer.ElapsedMilliseconds + "ms" + Environment.NewLine + "Base property: " + baseMemberTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Base field: " + baseFieldTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Base RO field: " + baseROFieldTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Virtual GetEnumType() test: " + virtMethTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Virtual IsB() test: " + virtMethBoolTime.ElapsedMilliseconds + "ms" + Environment.NewLine + "Create Time : " + createTime.ElapsedMilliseconds + "ms" + Environment.NewLine + Environment.NewLine+"UtcNow: " + Environment.NewLine + "As: " + (asStop - asStart).Milliseconds + "ms" + Environment.NewLine + "Is: " + (isStop - isStart).Milliseconds + "ms" + Environment.NewLine + "Base property: " + (baseStop - baseStart).Milliseconds + "ms" + Environment.NewLine + "Base field: " + (baseFieldStop - baseFieldStart).Milliseconds + "ms" + Environment.NewLine + "Base RO field: " + (baseROFieldStop - baseROFieldStart).Milliseconds + "ms" + Environment.NewLine + "Virtual GetEnumType(): " + (virtStop - virtStart).Milliseconds + "ms" + Environment.NewLine + "Virtual bool IsB(): " + (virtBoolStop - virtBoolStart).Milliseconds + "ms" + Environment.NewLine + "Create Time : " + (createStop-createStart).Milliseconds + "ms" + Environment.NewLine; } } abstract class MyBaseClass { public enum ClassTypeEnum { A, B } public ClassTypeEnum ClassType { get; protected set; } public ClassTypeEnum ClassTypeField; public readonly ClassTypeEnum ClassTypeReadonlyField; public abstract ClassTypeEnum GetClassType(); public abstract bool IsB(); protected MyBaseClass(ClassTypeEnum kind) { ClassTypeReadonlyField = kind; } } class MyClassA : MyBaseClass { public override bool IsB() { return false; } public override ClassTypeEnum GetClassType() { return ClassTypeEnum.A; } public MyClassA() : base(MyBaseClass.ClassTypeEnum.A) { ClassType = MyBaseClass.ClassTypeEnum.A; ClassTypeField = MyBaseClass.ClassTypeEnum.A; } } class MyClassB : MyBaseClass { public override bool IsB() { return true; } public override ClassTypeEnum GetClassType() { return ClassTypeEnum.B; } public MyClassB() : base(MyBaseClass.ClassTypeEnum.B) { ClassType = MyBaseClass.ClassTypeEnum.B; ClassTypeField = MyBaseClass.ClassTypeEnum.B; } } 

एंड्रयू सही है वास्तव में कोड विश्लेषण के साथ दृश्य स्टूडियो द्वारा एक अनावश्यक कलाकारों के रूप में रिपोर्ट किया जाता है।

एक विचार (आप क्या कर रहे हैं, यह जानने के बिना, अंधेरे में एक शॉट का थोड़ा सा), लेकिन मुझे हमेशा से सलाह दी जाती है कि आप इस तरह की जांच करें, और इसके बदले एक और वर्ग की जगह लें। इसलिए प्रकार के आधार पर कुछ जांच करने और अलग-अलग कार्रवाइयां करने के बजाय, क्लास को पता है कि खुद को कैसे संसाधित करें …

उदाहरण के लिए ओब्ज़ आईएसपेशियलटाइप या आईटीआईपी हो सकता है;

दोनों के पास एक डस्टफ () विधि परिभाषित है आईटीइपे के लिए यह सिर्फ वापसी या कस्टम सामान कर सकता है, जबकि आईएसस्पर्शल टाइप अन्य सामान कर सकता है।

यह तब पूरी तरह से किसी भी कास्टिंग को निकालता है, कोड क्लीनर बनाता है और बनाए रखने में आसान है, और कक्षा जानता है कि यह स्वयं का कार्य कैसे करना है

मैंने प्रकार की तुलना की दो संभावनाओं पर प्रदर्शन प्रदर्शन किया

  1. myobject.GetType () == प्रकार (MyClass)
  2. myobject है MyClass

इसका नतीजा: "है" का प्रयोग लगभग 10x तेज है !!!

आउटपुट:

प्रकार-तुलना के लिए समय: 00: 00: 00.456

तुलना के लिए समय: 00: 00: 00.042

मेरा कोड:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; namespace ConsoleApplication3 { class MyClass { double foo = 1.23; } class Program { static void Main(string[] args) { MyClass myobj = new MyClass(); int n = 10000000; Stopwatch sw = Stopwatch.StartNew(); for (int i = 0; i < n; i++) { bool b = myobj.GetType() == typeof(MyClass); } sw.Stop(); Console.WriteLine("Time for Type-Comparison: " + GetElapsedString(sw)); sw = Stopwatch.StartNew(); for (int i = 0; i < n; i++) { bool b = myobj is MyClass; } sw.Stop(); Console.WriteLine("Time for Is-Comparison: " + GetElapsedString(sw)); } public static string GetElapsedString(Stopwatch sw) { TimeSpan ts = sw.Elapsed; return String.Format("{0:00}:{1:00}:{2:00}.{3:000}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds); } } } 

प्वाइंट एंड्रयू हरे ने प्रदर्शन करते समय प्रदर्शन को खो दिया था और जांच की गई थी और फिर कास्ट मान्य था, लेकिन सी # 7.0 में हम कर सकते हैं चुड़ैल पैटर्न की जांच करें, बाद में अतिरिक्त कलाकारों से बचने के लिए:

 if (obj is ISpecialType st) { //st is in scope here and can be used } 

इसके अलावा अधिक अगर आपको कई प्रकारों के बीच सी # 7.0 पैटर्न मिलान निर्माण के बीच की जांच करना है, तो अब आप प्रकार पर switch करने की अनुमति देते हैं:

 public static double ComputeAreaModernSwitch(object shape) { switch (shape) { case Square s: return s.Side * s.Side; case Circle c: return c.Radius * c.Radius * Math.PI; case Rectangle r: return r.Height * r.Length; default: throw new ArgumentException( message: "shape is not a recognized shape", paramName: nameof(shape)); } } 

आप यहां दस्तावेज़ में सी # में मिलान करने वाले पैटर्न के बारे में अधिक पढ़ सकते हैं।

अगर किसी को भी आश्चर्य हो रहा है, तो मैंने यूनिटी इंजन 2017.1 में टेस्ट किया है, I5-4200U CPU के साथ एक नोटबुक पर रनटाइम संस्करण। NET4.6 (प्रायोगिक) के साथ। परिणाम:

Average Relative To Local Call LocalCall 117.33 1.00 is 241.67 2.06 Enum 139.33 1.19 VCall 294.33 2.51 GetType 276.00 2.35

पूर्ण लेख: http://www.ennoble-studios.com/tuts/unity-c-performance-comparison-is-vs-enum-vs-virtual-call.html

मुझे हमेशा से इस तरह से जांचने से बचने के लिए सलाह दी गई है, और इसके बजाय एक और वर्ग है इसलिए प्रकार के आधार पर कुछ जांच करने और अलग-अलग कार्रवाइयां करने के बजाय, क्लास को पता है कि खुद को कैसे संसाधित करें …

उदाहरण के लिए ओब्ज़ आईएसपेशियलटाइप या आईटीआईपी हो सकता है;

दोनों के पास एक डस्टफ () विधि परिभाषित है आईटीइपे के लिए यह सिर्फ वापसी या कस्टम सामान कर सकता है, जबकि आईएसस्पर्शल टाइप अन्य सामान कर सकता है।

यह तब पूरी तरह से किसी भी कास्टिंग को निकालता है, कोड क्लीनर बनाता है और बनाए रखने में आसान है, और कक्षा जानता है कि यह स्वयं के कार्यों को कैसे करना है