কীভাবে মেমোরি ক্যাশে সাফ করবেন?


100

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


4
.NET কোর এর জন্য এই উত্তরটি পরীক্ষা করে দেখুন ।
মকলা

উত্তর:


63

Dispose বিদ্যমান মেমোরি ক্যাশে এবং একটি নতুন মেমোরি ক্যাশে অবজেক্ট তৈরি করুন।


4
আমি প্রথমে মেমোরিচ্যাচ.ডিফল্ট ব্যবহার করেছি, যার ফলে ডিসপোজ আমাকে কিছুটা শোক দেয়। তবুও, নিষ্পত্তিটি আমার সন্ধানের সেরা সমাধান হিসাবে শেষ হয়েছিল। ধন্যবাদ
LaustN

11
@ লাস্টএন আপনি কি মেমোরিচ্যাস দ্বারা সৃষ্ট "শোক" সম্পর্কে বিস্তারিত বর্ণনা করতে পারেন? ডিফল্ট? আমি বর্তমানে মেমোরিচ্যাচ.ডিফল্ট ব্যবহার করছি ... এমএসডিএন এর মেমোরি ক্যাশে ডকুমেন্টেশন আমাকে বিস্মিত করে তোলে যে ডিসপোজ করার এবং পুনরুদ্ধার করার পরামর্শ দেওয়া হচ্ছে: "যদি প্রয়োজন না হয় মেমোরিচেস দৃষ্টান্ত তৈরি করবেন না। আপনি যদি ক্লায়েন্ট এবং ওয়েব অ্যাপ্লিকেশনগুলিতে ক্যাশে দৃষ্টান্ত তৈরি করেন, মেমোরি ক্যাশে দৃষ্টান্তগুলি হওয়া উচিত অ্যাপ্লিকেশন জীবন চক্রের প্রথম দিকে তৈরি করা হবে। " এটি। ডিফল্টের জন্য প্রযোজ্য? আমি বলছি না যে ডিসপোজ ব্যবহার করা ভুল, আমি সত্যই এই সমস্ত বিষয়ে স্পষ্টতা খুঁজছি।
ইলোনু ওয়েবদেব

8
থট এটা মূল্য উল্লেখ করে ছিল Dispose না কোনো ডাকা CacheEntryRemovedCallbackবর্তমান ক্যাশে আইটেম সংযুক্ত করা হয়েছে।
মাইক গুথ্রি

8
@ এলোনু: নিম্নলিখিত স্ট্যাক ওভারফ্লো উত্তরটি আপনার ডিফল্ট উদাহরণটি নিষ্পত্তি করার জন্য যে শোকের মুখোমুখি হতে পারে তার কয়েকটি ব্যাখ্যা করে: stackoverflow.com/a/8043556/216440 । উদ্ধৃতি হিসাবে: "ক্যাশের স্থিতিটি সেট করে তা চিহ্নিত করে যে ক্যাশে নিষ্পত্তি হয়েছে public ক্যাশের অবস্থা পরিবর্তনকারী পাবলিক ক্যাশে পদ্ধতিগুলি কল করার যে কোনও প্রচেষ্টা যেমন ক্যাশে প্রবেশকারীগুলি যুক্ত, অপসারণ বা পুনরুদ্ধার পদ্ধতিগুলি অপ্রত্যাশিত হতে পারে আচরণ। উদাহরণস্বরূপ, আপনি ক্যাশে নিষ্পত্তি হওয়ার পরে যদি সেট পদ্ধতিটি কল করেন তবে কোনও অপ-ত্রুটি ঘটবে। "
সাইমন তেউসি

56

গণনা নিয়ে সমস্যা

MemoryCache.GetEnumerator () অধ্যায় মন্তব্য সমূহ সাবধান করে: "। একটি সম্পদ নিবিড় এবং ব্লক অপারেশন হয় MemoryCache উদাহরণস্বরূপ একটি গণনাকারী পুনরুদ্ধার করা হচ্ছে অতএব, গণনাকারী প্রকাশনা অ্যাপ্লিকেশন ব্যবহার করা উচিত।"

এখানেই getEnumerator () বাস্তবায়নের সিউডোকোডে ব্যাখ্যা করা হয়েছে:

Create a new Dictionary object (let's call it AllCache)
For Each per-processor segment in the cache (one Dictionary object per processor)
{
    Lock the segment/Dictionary (using lock construct)
    Iterate through the segment/Dictionary and add each name/value pair one-by-one
       to the AllCache Dictionary (using references to the original MemoryCacheKey
       and MemoryCacheEntry objects)
}
Create and return an enumerator on the AllCache Dictionary

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

ডকুমেন্টেশনে সতর্কতাটি সঠিক। GetEnumerator () এড়িয়ে চলুন - উপরের সমস্ত উত্তর যা লিনকিউ ক্যোয়ারী ব্যবহার করে including

একটি ভাল এবং আরও নমনীয় সমাধান

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

// By Thomas F. Abraham (http://www.tfabraham.com)
namespace CacheTest
{
    using System;
    using System.Diagnostics;
    using System.Globalization;
    using System.Runtime.Caching;

    public class SignaledChangeEventArgs : EventArgs
    {
        public string Name { get; private set; }
        public SignaledChangeEventArgs(string name = null) { this.Name = name; }
    }

    /// <summary>
    /// Cache change monitor that allows an app to fire a change notification
    /// to all associated cache items.
    /// </summary>
    public class SignaledChangeMonitor : ChangeMonitor
    {
        // Shared across all SignaledChangeMonitors in the AppDomain
        private static event EventHandler<SignaledChangeEventArgs> Signaled;

        private string _name;
        private string _uniqueId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);

        public override string UniqueId
        {
            get { return _uniqueId; }
        }

        public SignaledChangeMonitor(string name = null)
        {
            _name = name;
            // Register instance with the shared event
            SignaledChangeMonitor.Signaled += OnSignalRaised;
            base.InitializationComplete();
        }

        public static void Signal(string name = null)
        {
            if (Signaled != null)
            {
                // Raise shared event to notify all subscribers
                Signaled(null, new SignaledChangeEventArgs(name));
            }
        }

        protected override void Dispose(bool disposing)
        {
            SignaledChangeMonitor.Signaled -= OnSignalRaised;
        }

        private void OnSignalRaised(object sender, SignaledChangeEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(e.Name) || string.Compare(e.Name, _name, true) == 0)
            {
                Debug.WriteLine(
                    _uniqueId + " notifying cache of change.", "SignaledChangeMonitor");
                // Cache objects are obligated to remove entry upon change notification.
                base.OnChanged(null);
            }
        }
    }

    public static class CacheTester
    {
        public static void TestCache()
        {
            MemoryCache cache = MemoryCache.Default;

            // Add data to cache
            for (int idx = 0; idx < 50; idx++)
            {
                cache.Add("Key" + idx.ToString(), "Value" + idx.ToString(), GetPolicy(idx));
            }

            // Flush cached items associated with "NamedData" change monitors
            SignaledChangeMonitor.Signal("NamedData");

            // Flush all cached items
            SignaledChangeMonitor.Signal();
        }

        private static CacheItemPolicy GetPolicy(int idx)
        {
            string name = (idx % 2 == 0) ? null : "NamedData";

            CacheItemPolicy cip = new CacheItemPolicy();
            cip.AbsoluteExpiration = System.DateTimeOffset.UtcNow.AddHours(1);
            cip.ChangeMonitors.Add(new SignaledChangeMonitor(name));
            return cip;
        }
    }
}

8
অনুপস্থিত অঞ্চল কার্যকারিতা বাস্তবায়নের মতো বলে মনে হচ্ছে।
জোয়েন

খুব সুন্দর. আমি চেইনড মেমোরিচেস মনিটর এবং গাইড ব্যবহার করে কিছু বাস্তবায়নের চেষ্টা করছি তবে কার্যকারিতা শক্ত করার চেষ্টা করার সাথে সাথে এটি কিছুটা কুৎসিত হতে শুরু করেছিল।
চাও

7
আমি সাধারণ ব্যবহারের জন্য এই প্যাটার্নটি সুপারিশ করব না। 1. এটির ধীর, বাস্তবায়নের কোনও দোষ নেই, তবে নিষ্পত্তি করার পদ্ধতিটি অত্যন্ত ধীর। ২. যদি আপনার মেয়াদ উত্তীর্ণ হওয়ার সাথে সাথে ক্যাশে থেকে আইটেমগুলি উচ্ছেদের করা হয়, তবে পরিবর্তন মনিটরের কল হবে। ৩. আমার মেশিনটি সমস্ত সিপিইউ গ্রাস করেছিল এবং আমি যখন পারফরম্যান্স টেস্ট চালাচ্ছিলাম তখন ক্যাশে থেকে 30 কে আইটেম সাফ করতে সত্যই দীর্ঘ সময় নিচ্ছিল। 5+ মিনিট অপেক্ষা করার পরে কয়েকবার আমি কেবল পরীক্ষাগুলি মেরে ফেলেছি।
হারুন এম

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

9
@ অ্যারোনএম কি এই সমাধানটি কেবল ক্যাশে নিষ্পত্তি এবং নতুনটিকে ইনস্ট্যান্ট করার চেয়ে আরও ভাল?
রবসিক্লোস

35

Http://connect.microsoft.com/VisualStudio/feedback/details/723620/memorycache-class-needs-a-clear- মিথাদ থেকে

কর্মক্ষেত্রটি হ'ল:

List<string> cacheKeys = MemoryCache.Default.Select(kvp => kvp.Key).ToList();
foreach (string cacheKey in cacheKeys)
{
    MemoryCache.Default.Remove(cacheKey);
}

34
ডকুমেন্টেশন থেকে : মেমোরি ক্যাশে উদাহরণের জন্য একটি এনুমুলেটর পুনরুদ্ধার করা একটি সংস্থান-নিবিড় এবং ব্লক করা ক্রিয়াকলাপ। সুতরাং, উত্পাদনকারী অ্যাপ্লিকেশনগুলিতে গণক ব্যবহার করা উচিত নয়।
ট্রুউইল

4
@ এমবারডুড এটি একজন গণক পুনরুদ্ধার করার মতোই - আপনার বাস্তবায়নের Select()কাজটি কী?
রবসিক্লোস

4
ব্যক্তিগতভাবে, আমি প্রতিটি ইউনিট পরীক্ষার জন্য মেমরি ক্যাশেটি সাফ করার জন্য এটি আমার ইউনিট পরীক্ষায় [টেস্টআইনিটাইজাল] ফাংশনটিতে ব্যবহার করছি। অন্যথায় ক্যাশে 2 টি কার্যের মধ্যে পারফরম্যান্সের তুলনা করার চেষ্টা করার সময় ইউনিট পরীক্ষাগুলি অনিচ্ছাকৃত ফলাফল দেয়।
জ্যাকব মরিসন

6
@JacobMorrison তর্কসাপেক্ষ, ইউনিট পরীক্ষা একটি "প্রকাশনা অ্যাপ্লিকেশান" আছেন :)
Mels

4
@ মেলগুলি যুক্তিযুক্তভাবে, ইউনিট পরীক্ষাগুলি "উত্পাদন অ্যাপ্লিকেশন" হিসাবে একই স্ট্যান্ডার্ডে লেখা উচিত! :)
ইথারম্যান

21
var cacheItems = cache.ToList();

foreach (KeyValuePair<String, Object> a in cacheItems)
{
    cache.Remove(a.Key);
}

4
এটি @ টনির প্রতিক্রিয়া হিসাবে একই ঝুঁকি রয়েছে; তার অধীনে আমার মন্তব্য দেখুন।
ট্রুউইল

@ ট্রুইউইল @ টনি কে বা ছিলেন?
অ্যালেক্স আঙ্গাস

4
@ অ্যালেক্সআঙ্গাস - তিনি তার নাম পরিবর্তন করে ম্যাজিট্রে রেখেছিলেন। আরও দেখুন stackoverflow.com/questions/4183270/...
TrueWill

10

পারফরম্যান্স যদি কোনও সমস্যা না হয় তবে এই দুর্দান্ত ওয়ান-লাইনারটি কৌশলটি সম্পাদন করবে:

cache.ToList().ForEach(a => cache.Remove(a.Key));

7

দেখে মনে হচ্ছে একটি ট্রিম পদ্ধতি আছে।

সুতরাং আপনি যা করতে চান তা সমস্ত সামগ্রী সাফ করার জন্য

cache.Trim(100)

সম্পাদনা: আরও কিছু খনন করার পরে, মনে হচ্ছে ট্রিম অনুসন্ধান করা আপনার সময়ের জন্য উপযুক্ত নয়

https://connect.microsoft.com/VisualStudio/feedback/details/831755/memorycache-trim-method-doesnt-evict-100-of-the-items

আমি কীভাবে একটি সিস্টেম সাফ করব un রুনটাইম.ক্যাচিং em মেমোরিচিচি


3

আপনি এটির মতোও কিছু করতে পারেন:


Dim _Qry = (From n In CacheObject.AsParallel()
           Select n).ToList()
For Each i In _Qry
    CacheObject.Remove(i.Key)
Next

3

এটি জুড়ে দৌড়ে, এবং এর উপর ভিত্তি করে, কিছুটা আরও কার্যকর, সমান্তরাল পরিষ্কার পদ্ধতি লিখেছিলেন:

    public void ClearAll()
    {
        var allKeys = _cache.Select(o => o.Key);
        Parallel.ForEach(allKeys, key => _cache.Remove(key));
    }

4
এটি দ্রুত (বা ধীর) কিনা তা পরীক্ষা করার জন্য আপনি পরীক্ষা করেছেন?
পল জর্জ

1

আমি কেবল ক্যাশে সাফ করার জন্য আগ্রহী ছিলাম এবং সি # গ্লোবাল ক্যাচিংপ্রোভিডার ব্যবহার করার সময় এটি একটি বিকল্প হিসাবে পেয়েছিলাম

                var cache = GlobalCachingProvider.Instance.GetAllItems();
                if (dbOperation.SuccessLoadingAllCacheToDB(cache))
                {
                    cache.Clear();
                }

0

ম্যাজিরিট উত্তরের কিছুটা উন্নত সংস্করণ।

var cacheKeys = MemoryCache.Default.Where(kvp.Value is MyType).Select(kvp => kvp.Key).ToList();
foreach (string cacheKey in cacheKeys)
{
    MemoryCache.Default.Remove(cacheKey);
}

0

আপনি মেমোরিচিচি.ড্যাফল্ট ক্যাশে নিষ্পত্তি করতে পারেন এবং তারপরে মেমোরিচেস পুনরায় তৈরি করতে প্রাইভেট ফিল্ড সিঙ্গলটনকে পুনরায় সেট করতে পারেন ull

       var field = typeof(MemoryCache).GetField("s_defaultCache",
            BindingFlags.Static |
            BindingFlags.NonPublic);
        field.SetValue(null, null);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.