2012-01-07 4 views
7

मैंने अपने अनुप्रयोगों में से एक में कैशिंग मुखौटा लागू करने का निर्णय लिया है - इसका उद्देश्य अंततः नेटवर्क ओवरहेड को कम करना और डीबी हिट की मात्रा को सीमित करना है। हम Castle.Windsor का उपयोग हमारे IoC Container के रूप में कर रहे हैं और हमने System.Runtime.Caching नामस्थान का उपयोग करके हमारी सेवा परत के शीर्ष पर कैशिंग कार्यक्षमता जोड़ने के लिए Interceptors के साथ जाने का निर्णय लिया है।विधि नाम और तर्क मानों के आधार पर कैश कुंजी निर्माण

इस समय मैं बिल्कुल सही नहीं समझ सकता कि cache key बनाने के लिए सबसे अच्छा तरीका क्या है। लक्ष्य के लिए विभिन्न तरीकों के बीच एक अंतर बनाने के लिए है और यह भी पारित कर दिया तर्क मान शामिल - जिसका अर्थ है कि इन दो विधि कॉल दो अलग अलग चाबियाँ के तहत कैश्ड किया जाना चाहिए:

IEnumerable<MyObject> GetMyObjectByParam(56); // key1 
IEnumerable<MyObject> GetMyObjectByParam(23); // key2 

के लिए अब मैं दो संभव कार्यान्वयन देख सकते हैं:

विकल्प 1: असेंबली | कक्षा | विधि वापसी प्रकार | विधि का नाम | तर्क प्रकार | तर्क हैश कोड

"MyAssembly.MyClass IEnumerable<MyObject> GetMyObjectByParam(long) { 56 }"; 

विकल्प 2: MD5 या SHA-256 अभिकलन हैश विधि के पूरी तरह से योग्य नाम के आधार पर और पारित तर्क को महत्व देता

string key = new SHA256Managed().ComputeHash(name + args).ToString(); 

मैं के बारे में सोच रहा हूँ दूसरे विकल्प के रूप में पहला विकल्प अधिक प्रसंस्करण समय की आवश्यकता होती है - दूसरी ओर दूसरा विकल्प सभी जेनरेट की गई कुंजी की बिल्कुल 'लंबाई' को लागू करता है।

क्या यह मानना ​​सुरक्षित है कि पहला विकल्प जटिल तर्क प्रकारों का उपयोग करके विधियों के लिए एक अद्वितीय कुंजी उत्पन्न करेगा? या शायद ऐसा करने का एक बिल्कुल अलग तरीका है?

सहायता और राय अत्यधिक सराहना की जाएगी!

उत्तर

3

कुछ बहुत ही उपयोगी लिंक है कि मैं here और here पाया है के आधार पर मैं यह अधिक या कम इस तरह लागू करने का फैसला किया है:

public sealed class CacheKey : IEquatable<CacheKey> 
{ 
    private readonly Type reflectedType; 
    private readonly Type returnType; 
    private readonly string name; 
    private readonly Type[] parameterTypes; 
    private readonly object[] arguments; 

    public User(Type reflectedType, Type returnType, string name, 
     Type[] parameterTypes, object[] arguments) 
    { 
     // check for null, incorrect values etc. 

     this.reflectedType = reflectedType; 
     this.returnType = returnType; 
     this.name = name; 
     this.parameterTypes = parameterTypes; 
     this.arguments = arguments; 
    } 

    public override bool Equals(object obj) 
    { 
     return Equals(obj as CacheKey); 
    } 

    public bool Equals(CacheKey other) 
    { 
     if (other == null) 
     { 
      return false; 
     } 

     for (int i = 0; i < parameterTypes.Count; i++) 
     { 
      if (!parameterTypes[i].Equals(other.parameterTypes[i])) 
      { 
       return false; 
      } 
     } 

     for (int i = 0; i < arguments.Count; i++) 
     { 
      if (!arguments[i].Equals(other.arguments[i])) 
      { 
       return false; 
      } 
     } 

     return reflectedType.Equals(other.reflectedType) && 
      returnType.Equals(other.returnType) && 
      name.Equals(other.name); 
    } 

    private override int GetHashCode() 
    { 
     unchecked 
     { 
      int hash = 17; 

      hash = hash * 31 + reflectedType.GetHashCode(); 
      hash = hash * 31 + returnType.GetHashCode(); 
      hash = hash * 31 + name.GetHashCode(); 

      for (int i = 0; i < parameterTypes.Count; i++) 
      { 
       hash = hash * 31 + parameterTypes[i].GetHashCode(); 
      } 

      for (int i = 0; i < arguments.Count; i++) 
      { 
       hash = hash * 31 + arguments[i].GetHashCode(); 
      } 

      return hash; 
     } 
    } 
} 

असल में यह सिर्फ एक सामान्य विचार है - उपरोक्त कोड को Fields के एक संग्रह के साथ आसानी से एक और सामान्य संस्करण में लिखा जा सकता है - संग्रह के प्रत्येक तत्व पर समान नियम लागू किए जाने होंगे। मैं पूरा कोड साझा कर सकता हूं।

2

एक विकल्प जिसे आपने छोड़ दिया है, स्ट्रिंग के लिए GetHashCode() फ़ंक्शन में निर्मित .NET का उपयोग कर रहा है। मैं काफी हद तक निश्चित हूं कि सी # डिक्शनरी में दृश्यों के पीछे एक स्ट्रिंग के साथ <TKey> (मैं उल्लेख करता हूं कि आपने शब्दकोष के साथ टैग को टैग किया है)। मुझे यकीन नहीं है कि .NET शब्दकोश वर्ग आपके Castle.Windsor या system.runtime.caching इंटरफ़ेस से संबंधित है।

कारण है कि आप हैश कुंजी के रूप में GetHashCode का उपयोग नहीं करना चाहते हैं यह है कि कार्यक्षमता विशेष रूप से माइक्रोसॉफ़्ट द्वारा चेतावनी के बिना संस्करणों के बीच बदलने के लिए अस्वीकार कर दी जाती है (जैसा कि अधिक अद्वितीय या तेज़ निष्पादन कार्य प्रदान करने के लिए)। यदि यह कैश मेमोरी में सख्ती से रहेंगे, तो यह कोई चिंता नहीं है क्योंकि .NET ढांचे को अपग्रेड करने से आपके एप्लिकेशन को पुनरारंभ करना होगा, कैश को पोंछना होगा।

स्पष्टीकरण के लिए, बस संयोजित स्ट्रिंग (विकल्प 1) का उपयोग करना पर्याप्त रूप से अद्वितीय होना चाहिए। ऐसा लगता है कि आपने अपनी विधियों को विशिष्ट रूप से अर्हता प्राप्त करने के लिए सबकुछ जोड़ा है।

यदि आप एक एमडी 5 या शा256 की स्ट्रिंग को एक शब्दकोश कुंजी में खिलाते हैं, तो प्रोग्राम शायद दृश्यों के पीछे स्ट्रिंग को फिर से चलाएगा। यह थोड़ी देर हो गया है क्योंकि मैंने डिक्शनरी कक्षा के आंतरिक कार्यों के बारे में पढ़ा है। यदि आप इसे Dictionary<String, IEnumerable<MyObject>> के रूप में छोड़ते हैं (जैसा कि कुंजी के रूप में int वापसी मान का उपयोग करके स्ट्रिंग पर GetHashCode() को कॉल करने का विरोध किया जाता है) तो शब्दकोश को हैश कोड के टकरावों को स्वयं ही संभालना चाहिए।

यह भी ध्यान दें कि (कम से कम मेरी मशीन पर चलने वाले बेंचमार्क प्रोग्राम के अनुसार), एमडी 5 SHA1 से लगभग 10% तेज है और SHA256 जितनी तेज है। स्ट्रिंग.गेटहाशकोड() एमडी 5 की तुलना में लगभग 20 गुना तेज है (यह क्रिप्टोग्राफिक रूप से सुरक्षित नहीं है)। टेस्ट को 32 और 1024 अक्षरों के बीच लंबाई के समान 100,000 यादृच्छिक रूप से जेनरेट किए गए तारों के लिए हैश की गणना करने के लिए कुल समय के लिए लिया गया था। लेकिन सटीक संख्याओं के बावजूद, एक कुंजी के रूप में एक क्रिप्टोग्राफ़िक रूप से सुरक्षित हैश फ़ंक्शन का उपयोग करके केवल आपके प्रोग्राम को धीमा कर दिया जाएगा।

यदि आप चाहें तो मैं अपनी तुलना के लिए स्रोत कोड पोस्ट कर सकता हूं।

+0

हाय पैट्रिक, दो कारण हैं कि मैं 'विकल्प 1' के साथ क्यों नहीं गया - सबसे पहले, कभी-कभी मैं काफी बड़ी पदानुक्रमित वस्तुओं का उपयोग कर रहा हूं जो मुख्य निर्माण के दौरान * तेजी से पर्याप्त * क्रमबद्ध करना मुश्किल है - और अन्य परिदृश्यों में मुझे एहसास हुआ है कि वास्तव में समान मानों को वापस करने के लिए 'String.GetHashCode' विधि के लिए असंभव नहीं है। यही कारण है कि मैंने एक कक्षा लागू की है जो * ठीक से * 'गेटहाशकोड' और 'समान' विधियों को ओवरराइड करता है और अंततः संभावित टकराव का समाधान करता है। मैं आपको सही दिशा में ले जाने के लिए एक +1 दे रहा हूं :) – MonkeyCoder

संबंधित मुद्दे