متى تقوم باستمرار محتويات Hashmap لتجنب تدهور الأداء؟

StackOverflow https://stackoverflow.com/questions/2426756

سؤال

أنا woking على جافا مع hashmap كبيرة (الملايين) التي تم بناؤها بالفعل بسعة 10.000.000 وعامل الحمل من .75 وتستخدم لذاكرة التخزين المؤقت بعض القيم

نظرا لأن القيم المخزنة مؤقتا تصبح عديمة الفائدة مع مرور الوقت (لم يتم الوصول إليها بعد الآن)، إلا أنني لا أستطيع إزالة عدد غير مجدي أثناء وجوده في الطريقة التي أود أن أفرغ بها ذاكرة التخزين المؤقت بالكامل عندما يبدأ أدائها في الانخفاض. كيف يمكنني أن أقرر متى سيكون من الجيد القيام بذلك؟

على سبيل المثال، مع 10 ملايين السعة و .75 يجب أن أفرغه عندما يصل إلى 7.5 ملايين العناصر؟ لأنني جربت العديد من قيم العتبة ولكن أود الحصول على تحليلي واحد.

لقد قمت بالفعل باختبار حقيقة أن الظهور عندما تكون ممتلئة تماما هي دفعة لبراعة (أول تكرارات خوارزمية من 2-3 بعد مسحها فقط، ثم يبدأ تشغيل أسرع من قبل المسح)

تحرير: معلومات إضافية

Hashmap طالما أن مفاتيح وتطفو كقيم. يحتوي على ارتباط مخزن مؤقت للمحتويات، لأنه منتج نقطة من ناقلات العلامات، أردت ذاكرة التخزين المؤقت لهم (زيادة الأداء).

لذلك أساسا ما أقوم به هو حساب long مفتاح باستخدام Hashcodes من المحتويات 2:

static private long computeKey(Object o1, Object o2)
{
    int h1 = o1.hashCode();
    int h2 = o2.hashCode();

    if (h1 < h2)
    {
        int swap = h1;
        h1 = h2;
        h2 = swap;
    }

    return ((long)h1) << 32 | h2;
}

واستخدامها لاسترداد القيم المخزنة. ما يحدث هو أنه نظرا لأن محتويات تجميع التسلسل الهرمي يتم دمجها وقيم الارتباط مع محتويات أخرى ليست هناك حاجة إلى المزيد .. لهذا السبب أريد مسح Hashmap من وقت لآخر، لتجنب التدهور بسبب القيم عديمة الفائدة داخلها.

باستخدام أ WeakHashMap سوف تمحو البيانات غير المتوقعة أيضا عندما لا تزال هناك حاجة إليها .. ليس لدي أي سيطرة عليه.

شكرا

هل كانت مفيدة؟

المحلول

لماذا لا تستخدم ذاكرة التخزين المؤقت LRU؟ من وثائق Java's Linkedhammap:

يتم توفير منشئ خاص لإنشاء خريطة تجزئة مرتبطة بها هو الترتيب هو الترتيب الذي تم الوصول إليه آخر إدخالاتها، من الأقل - يتم الوصول إليها مؤخرا إلى معظمها مؤخرا (ترتيب الوصول). هذا النوع من الخريطة مناسب تماما لبناء مخابئ LRU. يؤدي استدعاء طريقة وضع أو الحصول على طريقة الوصول إلى الإدخال المقابل (على افتراض أنه موجود بعد اكتمال الاحتجاز). تقوم طريقة Putall بإنشاء إمكانية إدخال إدخال واحد لكل تعيين في الخريطة المحددة، بالترتيب الذي يتم توفير تعيينات القيمة الرئيسية بواسطة جهاز إدخال إدخال الخريطة المحدد. لا توجد طرق أخرى تولد الوصول إلى الدخول. على وجه الخصوص، لا تؤثر العمليات على وجهات نظر التجميع على ترتيب تكرر خريطة الدعم.

في الأساس، كل مرة واحدة حيث تصبح خريطةك كبيرة جدا، ما عليك سوى حذف قيم X الأولى التي يمنحك فيها جهاز الكمبيوتر.

انظر الوثائق ل removeEldestEntry أن يكون هذا القيام به تلقائيا.

هنا هو الكود الذي يوضح:

 public static void main(String[] args) {
    class CacheMap extends LinkedHashMap{
      private int maxCapacity;
      public CacheMap(int initialCapacity, int maxCapacity) {
        super(initialCapacity, 0.75f, true);
        this.maxCapacity = maxCapacity;
      }

      @Override
      protected boolean removeEldestEntry(Map.Entry eldest) {
        return size()>maxCapacity;
      }
    }

    int[] popular = {1,2,3,4,5};
    CacheMap myCache = new CacheMap(5, 10);
    for (int i=0; i<100; i++){
      myCache.put(i,i);
      for (int p : popular) {
        myCache.get(p);
      }
    }

    System.out.println(myCache.toString()); 
    //{95=95, 96=96, 97=97, 98=98, 99=99, 1=1, 2=2, 3=3, 4=4, 5=5}
  }

نصائح أخرى

هل تحققت ضعف إضعاف ب يمكن لمعجم القمامة تحديد وقت إزالة الأشياء وقد يوفر لك بديلا مقبولا بدلا من الترميز بشيء بنفسك.

هذه المقالة لديه معلومات أكثر فائدة.

قد ترغب في استخدام مجموعات Google mapmaker. لجعل خريطة مع مراجع ناعمة ومهارة محددة.

المراجع الناعمة "يتم مسحها وفقا لتقدير جامع القمامة استجابة لطلب الذاكرة."

مثال:

ConcurrentMap<Long, ValueTypeHere> cacheMap = new MapMaker()
    .concurrencyLevel(32)
    .softValues()
    .expiration(30, TimeUnit.MINUTES)
    .makeMap();

يمكنك أيضا تحديد الضعيف إذا كنت ترغب في جعل مفاتيحها تتصرف مثل تلك الموجودة في وضع ضعيف.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top