1 /* 2 * ArrayCache 3 * 4 * Author: Lasse Collin <lasse.collin (at) tukaani.org> 5 * 6 * This file has been put into the public domain. 7 * You can do whatever you want with this file. 8 */ 9 10 package org.tukaani.xz; 11 12 /** 13 * Caches large arrays for reuse (base class and a dummy cache implementation). 14 * <p> 15 * When compressing or decompressing many (very) small files in a row, the 16 * time spent in construction of new compressor or decompressor objects 17 * can be longer than the time spent in actual compression or decompression. 18 * A large part of this initialization overhead comes from allocation and 19 * garbage collection of large arrays. 20 * <p> 21 * The {@code ArrayCache} API provides a way to cache large array allocations 22 * for reuse. It can give a major performance improvement when compressing or 23 * decompressing many tiny files. If you are only (de)compressing one or two 24 * files or the files a very big, array caching won't improve anything, 25 * although it won't make anything slower either. 26 * <p> 27 * <b>Important: The users of ArrayCache don't return the allocated arrays 28 * back to the cache in all situations.</b> 29 * This a reason why it's called a cache instead of a pool. 30 * If it is important to be able to return every array back to a cache, 31 * {@link ResettableArrayCache} can be useful. 32 * <p> 33 * In compressors (OutputStreams) the arrays are returned to the cache 34 * when a call to {@code finish()} or {@code close()} returns 35 * successfully (no exceptions are thrown). 36 * <p> 37 * In decompressors (InputStreams) the arrays are returned to the cache when 38 * the decompression is successfully finished ({@code read} returns {@code -1}) 39 * or {@code close()} or {@code close(boolean)} is called. This is true even 40 * if closing throws an exception. 41 * <p> 42 * Raw decompressors don't support {@code close(boolean)}. With raw 43 * decompressors, if one wants to put the arrays back to the cache without 44 * closing the underlying {@code InputStream}, one can wrap the 45 * {@code InputStream} into {@link CloseIgnoringInputStream} when creating 46 * the decompressor instance. Then one can use {@code close()}. 47 * <p> 48 * Different cache implementations can be extended from this base class. 49 * All cache implementations must be thread safe. 50 * <p> 51 * This class also works as a dummy cache that simply calls {@code new} 52 * to allocate new arrays and doesn't try to cache anything. A statically 53 * allocated dummy cache is available via {@link #getDummyCache()}. 54 * <p> 55 * If no {@code ArrayCache} is specified when constructing a compressor or 56 * decompressor, the default {@code ArrayCache} implementation is used. 57 * See {@link #getDefaultCache()} and {@link #setDefaultCache(ArrayCache)}. 58 * <p> 59 * This is a class instead of an interface because it's possible that in the 60 * future we may want to cache other array types too. New methods can be 61 * added to this class without breaking existing cache implementations. 62 * 63 * @since 1.7 64 * 65 * @see BasicArrayCache 66 */ 67 public class ArrayCache { 68 /** 69 * Global dummy cache instance that is returned by {@code getDummyCache()}. 70 */ 71 private static final ArrayCache dummyCache = new ArrayCache(); 72 73 /** 74 * Global default {@code ArrayCache} that is used when no other cache has 75 * been specified. 76 */ 77 private static volatile ArrayCache defaultCache = dummyCache; 78 79 /** 80 * Returns a statically-allocated {@code ArrayCache} instance. 81 * It can be shared by all code that needs a dummy cache. 82 */ 83 public static ArrayCache getDummyCache() { 84 return dummyCache; 85 } 86 87 /** 88 * Gets the default {@code ArrayCache} instance. 89 * This is a global cache that is used when the application 90 * specifies nothing else. The default is a dummy cache 91 * (see {@link #getDummyCache()}). 92 */ 93 public static ArrayCache getDefaultCache() { 94 // It's volatile so no need for synchronization. 95 return defaultCache; 96 } 97 98 /** 99 * Sets the default {@code ArrayCache} instance. 100 * Use with care. Other libraries using this package probably shouldn't 101 * call this function as libraries cannot know if there are other users 102 * of the xz package in the same application. 103 */ 104 public static void setDefaultCache(ArrayCache arrayCache) { 105 if (arrayCache == null) 106 throw new NullPointerException(); 107 108 // It's volatile so no need for synchronization. 109 defaultCache = arrayCache; 110 } 111 112 /** 113 * Creates a new {@code ArrayCache} that does no caching 114 * (a dummy cache). If you need a dummy cache, you may want to call 115 * {@link #getDummyCache()} instead. 116 */ 117 public ArrayCache() {} 118 119 /** 120 * Allocates a new byte array. 121 * <p> 122 * This implementation simply returns {@code new byte[size]}. 123 * 124 * @param size the minimum size of the array to allocate; 125 * an implementation may return an array that 126 * is larger than the given {@code size} 127 * 128 * @param fillWithZeros if true, the caller expects that the first 129 * {@code size} elements in the array are zero; 130 * if false, the array contents can be anything, 131 * which speeds things up when reusing a cached 132 * array 133 */ 134 public byte[] getByteArray(int size, boolean fillWithZeros) { 135 return new byte[size]; 136 } 137 138 /** 139 * Puts the given byte array to the cache. The caller must no longer 140 * use the array. 141 * <p> 142 * This implementation does nothing. 143 */ 144 public void putArray(byte[] array) {} 145 146 /** 147 * Allocates a new int array. 148 * <p> 149 * This implementation simply returns {@code new int[size]}. 150 * 151 * @param size the minimum size of the array to allocate; 152 * an implementation may return an array that 153 * is larger than the given {@code size} 154 * 155 * @param fillWithZeros if true, the caller expects that the first 156 * {@code size} elements in the array are zero; 157 * if false, the array contents can be anything, 158 * which speeds things up when reusing a cached 159 * array 160 */ 161 public int[] getIntArray(int size, boolean fillWithZeros) { 162 return new int[size]; 163 } 164 165 /** 166 * Puts the given int array to the cache. The caller must no longer 167 * use the array. 168 * <p> 169 * This implementation does nothing. 170 */ 171 public void putArray(int[] array) {} 172 } 173