Когда мучить содержимое хэшмапа, чтобы избежать деградации производительности?

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

Вопрос

Я разыгрываю Java с большой (миллионами) хэшмапом, которая фактически построена с емкостью 10.000.000 и коэффициентом нагрузки 0,75, и он используется для кэширования некоторых значений

Поскольку кэшированные значения становятся бесполезными со временем (больше не доступны), но я не могу удалить бесполезные, пока на пути я хотел бы полностью опустошить кэш, когда его производительность начинает ухудшаться. Как я могу решить, когда это хорошо сделать?

Например, с 10 миллионами мощностей и 0,75 я должен опустошить ее, когда он достигает 7,5 миллионов элементов? Потому что я попробовал различные пороговые значения, но я хотел бы иметь аналитический.

Я уже проверил тот факт, что облегчение его, когда он весьма полон, является импульсом для производительности (первые итерации алгоритма 2-3 после того, как протирание просто заполняет его назад, затем начинает работать быстрее, чем до утиха)

РЕДАКТИРОВАТЬ: Дополнительная информация

HashMap имеет длинные ключи и плавает как значения. Он содержит кэшированную корреляцию содержимого, поскольку это точечный продукт векторов TAG, который я хотел кэшировать их (для повышения производительности).

Так что в основном я делаю вычисление long Ключ, используя хешкоды 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;
}

и используйте его, чтобы получить сохраненные значения. Что происходит, так это то, что, поскольку это иерархическое содержание кластеризации объединяется, а их корреляционные значения с другим содержанием больше не нужны ... поэтому я хочу время от времени вытирать хэшмату, чтобы избежать деградации из -за бесполезных значений внутри нее.

Используя WeakHashMap Непредсказуемо уничтожает данные также, когда они все еще нужны ... Я не контролирую их.

Спасибо

Это было полезно?

Решение

Почему бы не использовать кэш LRU? Из документации Java's LinkedHashmap:

Специальный конструктор предназначен для создания связанной хеш-карты, порядок итерации которого-это порядок, в котором его записи были последним, от наименосленно доступного до наиболее активного (доступа). Этот вид карты хорошо подходит для строительства кэша LRU. Вызывая метод PUT или GET приводит к доступу к соответствующей записи (при условии, что он существует после завершения вызова). Метод 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 ' Картофмейнер Чтобы сделать карту с мягкими ссылками и определенным тайм -аутом.

Мягкие ссылки «очищаются по усмотрению коллекционера мусора в ответ на спрос на память».

Пример:

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

Вы также можете указать слабые, если вы хотите заставить его клавиши вести себя как Kine в слабых чаше.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top