DeltaCache.java

  1. /*
  2.  * Copyright (C) 2010, Google Inc. and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */

  10. package org.eclipse.jgit.internal.storage.pack;

  11. import java.lang.ref.ReferenceQueue;
  12. import java.lang.ref.SoftReference;

  13. import org.eclipse.jgit.storage.pack.PackConfig;

  14. class DeltaCache {
  15.     private final long size;

  16.     private final int entryLimit;

  17.     private final ReferenceQueue<byte[]> queue;

  18.     private long used;

  19.     DeltaCache(PackConfig pc) {
  20.         size = pc.getDeltaCacheSize();
  21.         entryLimit = pc.getDeltaCacheLimit();
  22.         queue = new ReferenceQueue<>();
  23.     }

  24.     boolean canCache(int length, ObjectToPack src, ObjectToPack res) {
  25.         // If the cache would overflow, don't store.
  26.         //
  27.         if (0 < size && size < used + length) {
  28.             checkForGarbageCollectedObjects();
  29.             if (0 < size && size < used + length)
  30.                 return false;
  31.         }

  32.         if (length < entryLimit) {
  33.             used += length;
  34.             return true;
  35.         }

  36.         // If the combined source files are multiple megabytes but the delta
  37.         // is on the order of a kilobyte or two, this was likely costly to
  38.         // construct. Cache it anyway, even though its over the limit.
  39.         //
  40.         if (length >> 10 < (src.getWeight() >> 20) + (res.getWeight() >> 21)) {
  41.             used += length;
  42.             return true;
  43.         }

  44.         return false;
  45.     }

  46.     void credit(int reservedSize) {
  47.         used -= reservedSize;
  48.     }

  49.     Ref cache(byte[] data, int actLen, int reservedSize) {
  50.         // The caller may have had to allocate more space than is
  51.         // required. If we are about to waste anything, shrink it.
  52.         //
  53.         data = resize(data, actLen);

  54.         // When we reserved space for this item we did it for the
  55.         // inflated size of the delta, but we were just given the
  56.         // compressed version. Adjust the cache cost to match.
  57.         //
  58.         if (reservedSize != data.length) {
  59.             used -= reservedSize;
  60.             used += data.length;
  61.         }
  62.         return new Ref(data, queue);
  63.     }

  64.     byte[] resize(byte[] data, int actLen) {
  65.         if (data.length != actLen) {
  66.             byte[] nbuf = new byte[actLen];
  67.             System.arraycopy(data, 0, nbuf, 0, actLen);
  68.             data = nbuf;
  69.         }
  70.         return data;
  71.     }

  72.     private void checkForGarbageCollectedObjects() {
  73.         Ref r;
  74.         while ((r = (Ref) queue.poll()) != null)
  75.             used -= r.cost;
  76.     }

  77.     static class Ref extends SoftReference<byte[]> {
  78.         final int cost;

  79.         Ref(byte[] array, ReferenceQueue<byte[]> queue) {
  80.             super(array, queue);
  81.             cost = array.length;
  82.         }
  83.     }
  84. }