oracle / coherence

Oracle Coherence Community Edition
https://coherence.community
Universal Permissive License v1.0
427 stars 70 forks source link

CaffeineCache doesn't track entry and cache size correctly when unit factor is used #75

Closed aseovic closed 2 years ago

aseovic commented 2 years ago

Describe the bug

CaffeineCache calculates the "weight" of individual entries at insertion time, using weigh function:

    private int weigh(Object oKey, Object oValue)
        {
        int cUnits = m_unitCalculator.calculateUnits(oKey, oValue);
        if (cUnits < 0)
            {
            throw new IllegalStateException(String.format(
                    "Negative unit (%s) for %s=%s", cUnits, oKey, oValue));
            }
        return (cUnits / m_nUnitFactor);
        }

This is problematic, because the method above returns 0 if a unit factor is larger than the number of units for a give entry, which is often the case when unit factor is used (typical values for unit factor are 2^10 and 2^20, in order to track and limit cache size in KBs or MBs). Even if the factor is smaller than the entry size, the loss of precision due to integer arithmetic at the single entry level is significant.

To Reproduce

  1. Configure unit factor that is larger than the average entry size
  2. Configure BINARY unit calculator
  3. Add some entries to the cache
  4. Observe that the getUnits method returns zero, even though there are entries in the cache

Expected behavior getUnits methods should return the actual number of bytes consumed by all entries, divided by the unit factor.

In other words, unit factor should only be applied during final calculation for the backing map as a whole, not at the individual entry level.

Environment (please complete the following information):

rlubke commented 2 years ago

Change has been merged