All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xceptance.common.collection.LRUFastHashMap Maven / Gradle / Ivy

Go to download

XLT (Xceptance LoadTest) is an extensive load and performance test tool developed and maintained by Xceptance.

The newest version!
/*
 * Copyright (c) 2005-2024 Xceptance Software Technologies GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.xceptance.common.collection;

/**
 * Simple LRU hashmap implementation that does not maintain a linked list
 * for tracking purposes rather uses backup hashmap to retire items and
 * pull them back up if needed. It uses the cheaper open hashing maps underneath.
 * It is not thread-safe!
 *
 * This is an LRU setup that drops an entire segment (up to 33% of the capacity)
 * when the LRU size is exhausted. THis all is done to avoid all the small updates
 * for hot cache entries, we just read here and don't need any update.
 *
 * @author Rene Schwietzke
 * @since 7.0.0
 */
public class LRUFastHashMap
{
    private final int capacity;
    private final int slotSize;

    private FastHashMap m1;
    private FastHashMap m2;
    private FastHashMap m3;

    /**
     * Create a new LRU map with max capacity.
     *
     * @param capacity the max capacity
     */
    public LRUFastHashMap(int capacity)
    {
        this.capacity = capacity;
        this.slotSize = this.capacity / 3;

        m1 = new FastHashMap<>(2 * slotSize, 0.5f);
        m2 = new FastHashMap<>(2 * slotSize, 0.5f);
        m3 = new FastHashMap<>(2 * slotSize, 0.5f);
    }

    /**
     * Fetches a value from the LRU map if it exists, moves the
     * fetched key-value pair in front aka renews it.
     *
     * @param key the key to fetch
     * @return the value of the key or null if it does not exist
     */
    public V get(final K key)
    {
        final V v1 = m1.get(key);
        if (v1 != null)
        {
            return v1;
        }

        final V v2 = m2.get(key);
        if (v2 != null)
        {
            put(key,  v2);
            return v2;
        }

        final V v3 = m3.get(key);
        if (v3 != null)
        {
            put(key,  v3);
            return v3;
        }

        return null;
    }

    /**
     * Fetches a value from the LRU map if it exists but does
     * not update the LRU state. Mainly useful for testing.
     *
     * @param key the key to fetch
     * @return the value of the key or null if it does not exist
     */
    public V getAndNoUpdate(final K key)
    {
        final V v1 = m1.get(key);
        if (v1 != null)
        {
            return v1;
        }

        final V v2 = m2.get(key);
        if (v2 != null)
        {
            return v2;
        }

        return m3.get(key);
    }

    /**
     * Add a key-value pair to the front of the LRU map or moves the existing
     * key to the front and updates the value
     *
     * @param key the key
     * @param value the value
     * @return the old value of the key, if it already existed
     */
    public V put(final K key, final V value)
    {
        // see if we are at capacity first
        if (m1.size() >= slotSize)
        {
            // recycle the old
            final FastHashMap oldM3 = m3;
            oldM3.clear();

            m3 = m2;
            m2 = m1;
            m1 = oldM3;
        }

        // update the cache
        final V old = m1.put(key,  value);

        return old;
    }

    /**
     * Returns the size of the cache
     *
     * @return the current size
     */
    public int size()
    {
        return m1.size() + m2.size() + m3.size();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy