001: package tide.profiler;
002:
003: import java.text.DecimalFormat;
004: import snow.sortabletable.*;
005: import tide.utils.SyntaxUtils;
006: import tide.editor.MainEditorFrame;
007: import java.io.InputStream;
008: import java.io.BufferedReader;
009: import java.io.InputStreamReader;
010: import snow.utils.*;
011: import java.util.*;
012:
013: public final class JMapReader extends FineGrainTableModel {
014:
015: private int numberOfDiffs = 0;
016: private String[] COLUMN_NAMES = new String[] { "no", "instances",
017: "bytes", "class name" };
018: private int[] COLUMN_PREFERED_SIZES = new int[] { 4, 4, 6, 45 };
019:
020: final private List<MapLine> map = new ArrayList<MapLine>();
021: boolean startCapture = false;
022: String totalLine = "";
023:
024: public JMapReader(Process proc) {
025: Gobbler sg = new Gobbler(proc.getInputStream());
026: sg.start();
027:
028: StreamGobbler sgerr = new StreamGobbler(
029: proc.getErrorStream(),
030: MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc
031: .createWriterForThisDocument(true), "JMap");
032: sgerr.start(); //[Dec2007]: fINDBUGS FOUND THIS missing !
033: }
034:
035: public void addDiffAnalysis(JMapReader newShot) {
036: this .fireTableModelWillChange();
037:
038: System.out.println("previous: " + map.size());
039: System.out.println("actual: " + newShot.map.size());
040:
041: // buld some quick dic and mark the elt as not visited
042: Map<String, MapLine> quickRef = new HashMap<String, MapLine>();
043: for (MapLine ml : map) {
044: quickRef.put(ml.className, ml);
045: ml.visited = false;
046: }
047:
048: int newCount = 0;
049: int oldCount = 0;
050:
051: for (MapLine newMl : newShot.map) {
052: MapLine ml = quickRef.get(newMl.className);
053: if (ml != null) {
054: ml.update(newMl);
055: ml.visited = true;
056: } else {
057: // new !
058: ml = MapLine.newlyAppears(newMl, numberOfDiffs);
059: map.add(ml);
060: ml.visited = true;
061: newCount++;
062: }
063: }
064:
065: // look for disapeared...
066: for (MapLine ml : map) {
067: if (!ml.visited) {
068: ml.disapears();
069: oldCount++;
070: }
071: }
072:
073: System.out.println("new " + newCount + ", old: " + oldCount);
074:
075: numberOfDiffs++;
076:
077: update();
078:
079: // clear intermediate data
080: quickRef.clear();
081: newShot.terminate();
082:
083: }
084:
085: public void deleteCol() {
086: if (numberOfDiffs == 0)
087: return;
088: numberOfDiffs--;
089: this .fireTableModelWillChange();
090: for (MapLine ml : map) {
091: ml.diffs.remove(numberOfDiffs); //(int)
092: }
093:
094: update();
095: }
096:
097: public void addLine(String line) {
098: if (startCapture) {
099: if (line.startsWith("Total")) {
100: totalLine = line;
101: } else {
102: try {
103: map.add(MapLine.parse(line));
104: } catch (Exception e) {
105: System.out.println("Can't parse jmap: " + line);
106: MainEditorFrame.instance.outputPanels.toolsOutputPanel.doc
107: .appendErrorLine(line);
108: }
109: }
110: } else {
111: startCapture = line.startsWith("----");
112: }
113: }
114:
115: @Override
116: public void terminate() {
117: map.clear();
118: }
119:
120: class Gobbler extends Thread {
121: final InputStream inputStream;
122:
123: Gobbler(InputStream inputStream) {
124: this .inputStream = inputStream;
125: }
126:
127: @Override
128: public void run() {
129: try {
130: final InputStreamReader isr = new InputStreamReader(
131: this .inputStream);
132: final BufferedReader br = new BufferedReader(isr);
133:
134: String line;
135: while ((line = br.readLine()) != null) {
136: addLine(line);
137: }
138:
139: System.out.println("JMapReader: " + map.size()
140: + " lines read: " + totalLine);
141: } catch (Exception e) {
142: e.printStackTrace();
143: }
144: }
145: }
146:
147: // Table model
148: //
149: public int getRowCount() {
150: return map.size();
151: }
152:
153: public int getColumnCount() {
154: return COLUMN_NAMES.length + numberOfDiffs;
155: }
156:
157: public Object getValueAt(int row, int col) {
158: if (row < 0)
159: return "bad row:" + row;
160: if (row >= map.size())
161: return "bad row:" + row;
162:
163: MapLine ml = map.get(row);
164: if (col == 0)
165: return ml.no;
166: if (col == 1)
167: return ml.instances;
168: if (col == 2)
169: return formatSize(ml.bytes);
170: if (col == 3)
171: return ml.className;
172: int d = col - 4;
173: if (d < ml.diffs.size())
174: return ml.diffs.get(d);
175: return "?";
176: }
177:
178: @Override
179: public int compareForColumnSort(int pos1, int pos2, int col) {
180: if (col == 2) {
181: MapLine ml1 = map.get(pos1);
182: MapLine ml2 = map.get(pos2);
183: return Integer.valueOf(ml1.bytes).compareTo(ml2.bytes);
184: }
185: return super .compareForColumnSort(pos1, pos2, col);
186: }
187:
188: public void update() {
189: fireTableDataChanged();
190: fireTableModelHasChanged();
191: }
192:
193: static DecimalFormat format00 = new DecimalFormat("0.0");
194:
195: public static String formatSize(long s) {
196: if (s > 1e9) {
197: return format00.format(s / 1.0e9) + " GB";
198: }
199: if (s > 1e6) {
200: return format00.format(s / 1.0e6) + " MB";
201: } else if (s > 1e3) {
202: return format00.format(s / 1.0e3) + " kB";
203: } else {
204: return s + " B";
205: }
206: }
207:
208: @Override
209: public String getColumnName(int column) {
210: if (column >= 0 && column < COLUMN_NAMES.length)
211: return COLUMN_NAMES[column];
212: return "inst diff " + (column - COLUMN_NAMES.length + 1);
213: }
214:
215: @Override
216: public int getPreferredColumnWidth(int column) {
217: if (column >= 0 && column < COLUMN_PREFERED_SIZES.length)
218: return COLUMN_PREFERED_SIZES[column];
219: return 4;
220: }
221:
222: static class MapLine {
223: int no, instances, bytes;
224: String className;
225: List<Integer> diffs = new ArrayList<Integer>();
226: boolean visited = false;
227:
228: static MapLine newlyAppears(MapLine na, int numberOfDiffs) {
229: MapLine ml = new MapLine();
230: ml.no = na.no;
231: ml.instances = na.instances;
232: ml.bytes = na.bytes;
233: ml.className = na.className;
234: for (int i = 0; i < numberOfDiffs; i++) // fill old data
235: {
236: ml.diffs.add(0);
237: }
238: ml.diffs.add(na.instances);
239: return ml;
240: }
241:
242: void disapears() {
243: int oldInst = instances;
244: instances = 0;
245: bytes = 0;
246: diffs.add(-instances);
247: }
248:
249: void update(MapLine na) {
250: int diffI = na.instances - instances;
251: no = na.no;
252: instances = na.instances;
253: bytes = na.bytes;
254: //same !className = na.className;
255: diffs.add(diffI);
256:
257: }
258:
259: /**
260: * 123: 205 6560 java.awt.GradientPaint
261: */
262: static MapLine parse(String line) {
263: MapLine ml = new MapLine();
264: Scanner sc = new Scanner(line);
265: String l1 = sc.next().trim();
266: if (l1.endsWith(":"))
267: l1 = l1.substring(0, l1.length() - 1);
268: ml.no = Integer.parseInt(l1);
269: l1 = sc.next().trim();
270: ml.instances = Integer.parseInt(l1);
271: l1 = sc.next().trim();
272: ml.bytes = Integer.parseInt(l1);
273: ml.className = SyntaxUtils.convertVmNameToFullJavaNames(sc
274: .next().trim());
275: // convert "[C" to "char[]", ...
276:
277: return ml;
278: }
279: }
280: }
|