2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
41
package org.netbeans.modules.turbo;
44
import java.util.Date;
46
import java.util.HashSet;
47
import java.util.Iterator;
50
* Statistics support for {@link Turbo}.
52
* <p>Results analysis allows to determine if cache
59
private static final Statistics NOP_INSTANCE = new NOP();
60
private static final int REMOVED_BATCH_INTERVAL = 1000 *10; // 10s
62
private long requests = 0;
63
private long memoryHits = 0;
64
private long diskHits = 0;
67
private long threads = 0;
68
private long duplicates = 0;
69
private long maxQueueSize = 0;
71
// Memory.liveentitiesMap utilization
72
private long maxMemoryEntries = 0;
73
private long gcCounter = 0;
74
private long newCounter = 0;
75
private int removedInvocaionCounter = 0;
76
private long removedInvocationTime = System.currentTimeMillis() - REMOVED_BATCH_INTERVAL;
77
/** Holds keys string reprentation to avoid memory leaks. */
78
private Set recentKeys;
80
// cache instance identification fields
81
private static volatile int idPool = 1;
83
private final Exception origin;
85
private PrintWriter out;
87
/** Creates new statistics instance according to
88
* <tt>netbeans.experimental.vcsTurboStatistics</tt> system
91
* <li><tt>none</tt> (default) no-op implementaion
92
* <li><tt>mini</tt> logs fast events
93
* <li><tt>performance</tt> logs also heavy events slowing down Turbo and increasing it's memory requirements.
96
public static Statistics createInstance() {
97
if ("none".equalsIgnoreCase(System.getProperty("netbeans.experimental.vcsTurboStatistics", "none"))) { // NOI18N
100
return new Statistics();
104
private Statistics() {
105
origin = new RuntimeException();
110
* Checks if additional logging required for detailed performance evaluation is required.
112
private static boolean logPerformance() {
113
return System.getProperty("netbeans.experimental.vcsTurboStatistics", "mini").equalsIgnoreCase("performance"); // NOI18N
116
/** Key created adding permision to store it in memory layer. */
117
public void keyAdded(Object key) {
118
if (key != null) println("EK+ " + key); // NOi18N
120
long allocated = newCounter - gcCounter;
121
if (allocated > maxMemoryEntries) {
122
maxMemoryEntries = allocated;
124
if (recentKeys != null) {
125
assert recentKeys.add(key.toString()) : "Key added for the second time: " + key;
129
/** Key was removed from memory. */
130
public void keyRemoved(Object key) {
131
if (key != null) println("EK- " + key); // NOi18N
133
if (recentKeys != null) {
134
recentKeys.remove(key.toString());
139
* Detect reclaimed keys. It lods first results on the second call.
141
* <p>It's heavy event.
143
public void computeRemoved(Set keys) {
144
if (logPerformance() == false) return;
146
if (System.currentTimeMillis() - removedInvocationTime > REMOVED_BATCH_INTERVAL) return;
148
removedInvocaionCounter++;
149
Iterator it = keys.iterator();
150
Set currentKeys = new HashSet(keys.size());
151
while (it.hasNext()) {
152
String stringKey = it.next().toString();
153
currentKeys.add(stringKey);
156
if (recentKeys != null) {
157
recentKeys.removeAll(currentKeys);
158
int reclaimed = recentKeys.size();
159
gcCounter += reclaimed;
162
println("MSG [" + new Date().toString() + "] reclaimed keys:" ); // NOI18N
163
Iterator itr = recentKeys.iterator();
164
while (itr.hasNext()) {
165
String next = itr.next().toString();
166
println("EK- " + next); // NOI18N
168
println("MSG EOL reclaimed keys" ); // NOI18N
172
removedInvocationTime = System.currentTimeMillis();
173
recentKeys = currentKeys;
176
/** Turbo request arrived */
177
public void attributeRequest() {
179
if (requests % 1000 == 0) {
180
printCacheStatistics();
184
/** The client request was resolved by memory layer */
185
public void memoryHit() {
189
/** new background thread spawned */
190
public void backgroundThread() {
194
/** Duplicate request eliminated from queue. */
195
public void duplicate() {
199
public void queueSize(int size) {
200
if (size > maxQueueSize) {
205
/** The client request was resolved at providers layer */
206
public void providerHit() {
210
public void shutdown() {
211
printCacheStatistics();
214
// System.out.println(" Statistics goes to " + Statistics.logPath()); // NOI18N
217
private String logPath() {
218
return System.getProperty("java.io.tmpdir") + File.separator + "netbeans-versioning-turbo-" + id + ".log"; // NOI18N
221
private void printCacheStatistics() {
222
println("CS turbo.requests=" + requests); // NOI18N
223
println("CS memory.hits=" + memoryHits + " " + (((float)memoryHits/(float)requests) * 100) + "%"); // NOI18N
224
println("CS provider.hits=" + diskHits + " " + (((float)diskHits/(float)requests) * 100) + "%"); // NOI18N
225
if (removedInvocaionCounter >= 2) {
226
println("CS memory.max=" + maxMemoryEntries); // NOI18N
227
println("CS memory.entries=" + (newCounter - gcCounter)); // NOI18N
228
println("CS memory.entiresReclaimingRatio=" + (((float)gcCounter/(float)newCounter) * 100) + "%"); // NOI18N
230
println("MSG No memory utilization data known, use -J-Dnetbeans.experimental.vcsTurboStatistics=performance.");
232
println("CS queue.threads=" + threads + " queue.duplicates=" + duplicates + " queue.maxSize=" + maxQueueSize); // NOI18N
233
println("MSG --"); // NOI18N
234
println("MSG turbo.log.Statistics on " + new Date().toString()); // NOI18N
237
private synchronized void println(String s) {
239
String filePath = logPath();
241
out = new PrintWriter(new BufferedWriter(new FileWriter(filePath), 512));
242
} catch (IOException e) {
243
out = new PrintWriter(new OutputStreamWriter(System.out), true);
245
out.println("MSG EK followed by +/- denotes new memory cache entry/releasing it"); // NOI18N
246
out.println("MSG CS describes summary statistics of memory and disk caches"); // NOI18N
247
out.println("MSG the MSG prefix denotes free form messages"); // NOI18N
248
out.println("MSG turbo.Statistics instance serving:\n"); // NOI18N
249
StackTraceElement elements[] = origin.getStackTrace();
250
for (int i = 0; i < elements.length; i++) {
251
StackTraceElement element = elements[i];
252
out.println("MSG " + element.toString() ); // NOI18N
260
private static final class NOP extends Statistics {
261
public void keyAdded(Object key) {
264
public void computeRemoved(Set keys) {
267
public void attributeRequest() {
270
public void memoryHit() {
273
public void backgroundThread() {
276
public void duplicate() {
279
public void queueSize(int size) {
282
public void providerHit() {
285
public void shutdown() {