1 /**
2 * Copyright Terracotta, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package net.sf.ehcache;
18
19 import java.io.Serializable;
20
21 /**
22 * An immutable Cache statistics implementation
23 * <p/>
24 * This is like a value object, with the added ability to clear cache statistics on the cache.
25 * That ability does not survive any Serialization of this class. On deserialization the cache
26 * can be considered disconnected.
27 * <p/>
28 * The accuracy of these statistics are determined by the value of {@link Cache#getStatisticsAccuracy()}
29 * at the time the statistic was computed. This can be changed by setting {@link Cache#setStatisticsAccuracy}.
30 * <p/>
31 * Because this class maintains a reference to an Ehcache, any references held to this class will prevent the Ehcache
32 * from getting garbage collected.
33 * <p/>
34 * todo Add missCountExpired. Request from user.
35 *
36 * @author Greg Luck
37 * @version $Id: Statistics.java 5631 2012-05-10 08:31:33Z teck $
38 */
39 public class Statistics implements Serializable {
40
41 /**
42 * Fast but not accurate setting.
43 */
44 public static final int STATISTICS_ACCURACY_NONE = 0;
45
46 /**
47 * Best efforts accuracy setting.
48 */
49 public static final int STATISTICS_ACCURACY_BEST_EFFORT = 1;
50
51 /**
52 * Guaranteed accuracy setting.
53 */
54 public static final int STATISTICS_ACCURACY_GUARANTEED = 2;
55
56 private static final long serialVersionUID = 3606940454221918725L;
57
58 private transient Ehcache cache;
59
60 private final String cacheName;
61
62 private final int statisticsAccuracy;
63
64 private final long cacheHits;
65
66 private final long onDiskHits;
67
68 private final long offHeapHits;
69
70 private final long inMemoryHits;
71
72 private final long misses;
73
74 private final long onDiskMisses;
75
76 private final long offHeapMisses;
77
78 private final long inMemoryMisses;
79
80 private final long size;
81
82 private final long memoryStoreSize;
83
84 private final long offHeapStoreSize;
85
86 private final long diskStoreSize;
87
88 private final float averageGetTime;
89
90 private final long evictionCount;
91
92 private final long searchesPerSecond;
93
94 private final long averageSearchTime;
95
96 private long writerQueueLength;
97
98
99 /**
100 * Creates a new statistics object, associated with a Cache
101 *
102 * @param cache The cache that {@link #clearStatistics()} will call, if not disconnected
103 * @param statisticsAccuracy
104 * @param cacheHits
105 * @param onDiskHits
106 * @param offHeapHits
107 * @param inMemoryHits
108 * @param misses
109 * @param size
110 */
111 public Statistics(Ehcache cache, int statisticsAccuracy, long cacheHits, long onDiskHits, long offHeapHits,
112 long inMemoryHits, long misses, long onDiskMisses, long offHeapMisses,
113 long inMemoryMisses, long size, float averageGetTime, long evictionCount,
114 long memoryStoreSize, long offHeapStoreSize, long diskStoreSize, long searchesPerSecond,
115 long averageSearchTime, long writerQueueLength) {
116 this.cacheName = cache.getName();
117 this.statisticsAccuracy = statisticsAccuracy;
118 this.cacheHits = cacheHits;
119 this.onDiskHits = onDiskHits;
120 this.offHeapHits = offHeapHits;
121 this.inMemoryHits = inMemoryHits;
122 this.misses = misses;
123 this.onDiskMisses = onDiskMisses;
124 this.offHeapMisses = offHeapMisses;
125 this.inMemoryMisses = inMemoryMisses;
126 this.cache = cache;
127 this.size = size;
128 this.averageGetTime = averageGetTime;
129 this.evictionCount = evictionCount;
130 this.memoryStoreSize = memoryStoreSize;
131 this.offHeapStoreSize = offHeapStoreSize;
132 this.diskStoreSize = diskStoreSize;
133 this.searchesPerSecond = searchesPerSecond;
134 this.averageSearchTime = averageSearchTime;
135 this.writerQueueLength = writerQueueLength;
136 }
137
138
139 /**
140 * Clears the statistic counters to 0 for the associated Cache.
141 */
142 public void clearStatistics() {
143 if (cache == null) {
144 throw new IllegalStateException("This statistics object no longer references a Cache.");
145 }
146 cache.clearStatistics();
147 }
148
149 /**
150 * The number of times a requested item was found in the cache.
151 *
152 * @return the number of times a requested item was found in the cache
153 */
154 public long getCacheHits() {
155 return cacheHits;
156 }
157
158 /**
159 * Number of times a requested item was found in the Memory Store.
160 *
161 * @return the number of times a requested item was found in memory
162 */
163 public long getInMemoryHits() {
164 return inMemoryHits;
165 }
166
167 /**
168 * Number of times a requested item was found in the off-heap store.
169 *
170 * @return the number of times a requested item was found in off-heap
171 */
172 public long getOffHeapHits() {
173 return offHeapHits;
174 }
175
176 /**
177 * Number of times a requested item was found in the Disk Store.
178 *
179 * @return the number of times a requested item was found on Disk, or 0 if there is no disk storage configured.
180 */
181 public long getOnDiskHits() {
182 return onDiskHits;
183 }
184
185 /**
186 * @return the number of times a requested element was not found in the cache
187 */
188 public long getCacheMisses() {
189 return misses;
190
191 }
192
193 /**
194 * Number of times a requested item was not found in the Memory Store.
195 *
196 * @return the number of times a requested item was not found in memory
197 */
198 public long getInMemoryMisses() {
199 return inMemoryMisses;
200 }
201
202 /**
203 * Number of times a requested item was not found in the off-heap store.
204 *
205 * @return the number of times a requested item was not found in off-heap
206 */
207 public long getOffHeapMisses() {
208 return offHeapMisses;
209 }
210
211 /**
212 * Number of times a requested item was not found in the Disk Store.
213 *
214 * @return the number of times a requested item was not found on Disk, or 0 if there is no disk storage configured.
215 */
216 public long getOnDiskMisses() {
217 return onDiskMisses;
218 }
219
220 /**
221 * Gets the number of elements stored in the cache. Caclulating this can be expensive. Accordingly,
222 * this method will return three different values, depending on the statistics accuracy setting.
223 * <h3>Best Effort Size</h3>
224 * This result is returned when the statistics accuracy setting is {@link Statistics#STATISTICS_ACCURACY_BEST_EFFORT}.
225 * <p/>
226 * The size is the number of {@link Element}s in the {@link net.sf.ehcache.store.MemoryStore} plus
227 * the number of {@link Element}s in the {@link net.sf.ehcache.store.disk.DiskStore}.
228 * <p/>
229 * This number is the actual number of elements, including expired elements that have
230 * not been removed. Any duplicates between stores are accounted for.
231 * <p/>
232 * Expired elements are removed from the the memory store when
233 * getting an expired element, or when attempting to spool an expired element to
234 * disk.
235 * <p/>
236 * Expired elements are removed from the disk store when getting an expired element,
237 * or when the expiry thread runs, which is once every five minutes.
238 * <p/>
239 * <h3>Guaranteed Accuracy Size</h3>
240 * This result is returned when the statistics accuracy setting is {@link Statistics#STATISTICS_ACCURACY_GUARANTEED}.
241 * <p/>
242 * This method accounts for elements which might be expired or duplicated between stores. It take approximately
243 * 200ms per 1000 elements to execute.
244 * <h3>Fast but non-accurate Size</h3>
245 * This result is returned when the statistics accuracy setting is {@link #STATISTICS_ACCURACY_NONE}.
246 * <p/>
247 * The number given may contain expired elements. In addition if the DiskStore is used it may contain some double
248 * counting of elements. It takes 6ms for 1000 elements to execute. Time to execute is O(log n). 50,000 elements take
249 * 36ms.
250 *
251 * @return the number of elements in the ehcache, with a varying degree of accuracy, depending on accuracy setting.
252 */
253 public long getObjectCount() {
254 return size;
255 }
256
257 /**
258 *
259 * @return the number of objects in the memory store
260 */
261 public long getMemoryStoreObjectCount() {
262 return memoryStoreSize;
263 }
264
265 /**
266 *
267 * @return the number of objects in the off-heap store
268 */
269 public long getOffHeapStoreObjectCount() {
270 return offHeapStoreSize;
271 }
272
273 /**
274 *
275 * @return the number of objects in the disk store
276 */
277 public long getDiskStoreObjectCount() {
278 return diskStoreSize;
279 }
280
281 /**
282 * Accurately measuring statistics can be expensive. Returns the current accuracy setting.
283 *
284 * @return one of {@link #STATISTICS_ACCURACY_BEST_EFFORT}, {@link #STATISTICS_ACCURACY_GUARANTEED}, {@link #STATISTICS_ACCURACY_NONE}
285 */
286 public int getStatisticsAccuracy() {
287 return statisticsAccuracy;
288 }
289
290 /**
291 * Accurately measuring statistics can be expensive. Returns the current accuracy setting.
292 *
293 * @return a human readable description of the accuracy setting. One of "None", "Best Effort" or "Guaranteed".
294 */
295 public String getStatisticsAccuracyDescription() {
296 if (statisticsAccuracy == 0) {
297 return "None";
298 } else if (statisticsAccuracy == 1) {
299 return "Best Effort";
300 } else {
301 return "Guaranteed";
302 }
303 }
304
305 /**
306 * @return the name of the Ehcache, or null if a reference is no longer held to the cache,
307 * as, it would be after deserialization.
308 */
309 public String getAssociatedCacheName() {
310 if (cache != null) {
311 return cache.getName();
312 } else {
313 return cacheName;
314 }
315 }
316
317 /**
318 * @return the name of the Ehcache, or null if a reference is no longer held to the cache,
319 * as, it would be after deserialization.
320 */
321 public Ehcache getAssociatedCache() {
322 if (cache != null) {
323 return cache;
324 } else {
325 return null;
326 }
327 }
328
329 /**
330 * Returns a {@link String} representation of the {@link Ehcache} statistics.
331 */
332 @Override
333 public final String toString() {
334 StringBuilder dump = new StringBuilder();
335
336 dump.append("[ ")
337 .append(" name = ").append(getAssociatedCacheName())
338 .append(" cacheHits = ").append(cacheHits)
339 .append(" onDiskHits = ").append(onDiskHits)
340 .append(" offHeapHits = ").append(offHeapHits)
341 .append(" inMemoryHits = ").append(inMemoryHits)
342 .append(" misses = ").append(misses)
343 .append(" onDiskMisses = ").append(onDiskMisses)
344 .append(" offHeapMisses = ").append(offHeapMisses)
345 .append(" inMemoryMisses = ").append(inMemoryMisses)
346 .append(" size = ").append(size)
347 .append(" averageGetTime = ").append(averageGetTime)
348 .append(" evictionCount = ").append(evictionCount)
349 .append(" ]");
350
351 return dump.toString();
352 }
353
354 /**
355 * The average get time. Because ehcache support JDK1.4.2, each get time uses
356 * System.currentTimeMilis, rather than nanoseconds. The accuracy is thus limited.
357 */
358 public float getAverageGetTime() {
359 return averageGetTime;
360 }
361
362 /**
363 * Gets the number of cache evictions, since the cache was created, or statistics were cleared.
364 */
365 public long getEvictionCount() {
366 return evictionCount;
367 }
368
369 /**
370 * Gets the average execution time (in milliseconds) within the last sample period
371 */
372 public long getAverageSearchTime() {
373 return averageSearchTime;
374 }
375
376 /**
377 * Get the number of search executions that have completed in the last second
378 */
379 public long getSearchesPerSecond() {
380 return searchesPerSecond;
381 }
382
383 /**
384 * Utility method to determine if a given value is a valid statistics
385 * accuracy value or not
386 *
387 * @param statisticsAccuracy
388 * @return true if the value is one of
389 * {@link Statistics#STATISTICS_ACCURACY_BEST_EFFORT},
390 * {@link Statistics#STATISTICS_ACCURACY_GUARANTEED},
391 * {@link Statistics#STATISTICS_ACCURACY_NONE}
392 */
393 public static boolean isValidStatisticsAccuracy(int statisticsAccuracy) {
394 return statisticsAccuracy == STATISTICS_ACCURACY_NONE
395 || statisticsAccuracy == STATISTICS_ACCURACY_BEST_EFFORT
396 || statisticsAccuracy == STATISTICS_ACCURACY_GUARANTEED;
397 }
398
399 /**
400 * Gets the size of the write-behind queue, if any.
401 * The value is for all local buckets
402 * @return Elements waiting to be processed by the write behind writer. -1 if no write-behind
403 */
404 public long getWriterQueueSize() {
405 return writerQueueLength;
406 }
407 }
408