001 package jp.osdl.jbento2.analyzer;
002
003 import java.io.IOException;
004 import java.io.Reader;
005 import java.util.regex.Matcher;
006 import java.util.regex.Pattern;
007
008 public class GCParserImpl implements GCParser {
009
010 private static final String ELEMENT_FIRST = "[";
011
012 private static final String ELEMENT_END = "]";
013
014 Pattern numberPattern = Pattern.compile("\\d*\\.\\d*");
015
016 Pattern transitionHeapPattern = Pattern.compile("(\\d*)K->(\\d*)K");
017
018 Pattern numberHeapPattern = Pattern.compile("(\\d*)K");
019
020 Pattern cmsPattern = Pattern.compile("CMS-concurrent-.*");
021
022 Pattern cmsIllegalPattern = Pattern.compile("CMS(\\d*):");
023
024 long currentPermMax = 0;
025
026 long currentPermSize = 0;
027
028 public GCList parse(Reader reader) throws IOException {
029 GCList gcList = new GCList();
030 GCTokenizer gct = new GCTokenizer(reader);
031 String token;
032
033 while ((token = gct.getToken()) != null) {
034 try {
035 Matcher matcher = numberPattern.matcher(token);
036 if (!matcher.matches()) {
037 gct.skipLine();
038 continue;
039 }
040 double startTime = Double.parseDouble(token);
041
042 token = gct.getToken();
043 if (!":".equals(token)) {
044 gct.skipLine();
045 continue;
046 }
047 token = gct.getToken();
048 if (!ELEMENT_FIRST.equals(token)) {
049 gct.skipLine();
050 continue;
051 }
052
053 token = gct.getToken();
054 GCSample sample = getGCSample(token, gct);
055 if (sample != null) {
056 sample.setStartTime((long) (startTime * 1000));
057 sample.calculate();
058 gcList.add(sample);
059 }
060 } catch (Exception ex) {
061 System.out.println("error at " + gct.getLineNumber()
062 + " gc analyzing");
063 ex.printStackTrace();
064 continue;
065 }
066 }
067 return gcList;
068 }
069
070 public GCSample getGCSample(String keyToken, GCTokenizer gct)
071 throws IOException {
072 GCSample sample = null;
073 if ("GC".equals(keyToken)) {
074 sample = new GCSample();
075 sample.setType(GCSample.TYPE_GC);
076 } else if ("Full".equals(keyToken)) {
077 keyToken = gct.getToken();
078 if ("GC".equals(keyToken)) {
079 sample = new GCSample();
080 sample.setType(GCSample.TYPE_FULL_GC);
081 }
082 } else {
083 Matcher matcher = cmsPattern.matcher(keyToken);
084 if (matcher.matches()) {
085 gct.skipLine();
086 return null;
087 }
088 gct.skipLine();
089 throw new IllegalStateException("keyToken '" + keyToken
090 + "' is invalid.");
091 }
092
093 while (true) {
094 String token = gct.getToken();
095 if (ELEMENT_FIRST.equals(token)) {
096 token = gct.getToken();
097 if ("DefNew".equals(token) || "ParNew".equals(token)
098 || "PSYoungGen".equals(token)) {
099 GCTransition newGC = getNewGC(token, gct);
100 sample.setNewGC(newGC);
101 continue;
102 } else if ("Tenured".equals(token)) {
103 GCTransition tenuredGC = getTenuredGC(token, gct);
104 sample.setTenuredGC(tenuredGC);
105 continue;
106 } else if (token.startsWith("CMS")) {
107 processCMS(token, gct, sample);
108 continue;
109 } else if ("Perm".equals(token)) {
110 GCTransition permGC = getPermGC("Perm", gct);
111 sample.setPermGC(permGC);
112 continue;
113 } else if ("1".equals(token) || "YG".equals(token)) {
114 gct.skipLine();
115 return null;
116 }
117 gct.skipLine();
118 throw new IllegalStateException("token '" + token
119 + "' is invalid.");
120 } else if (ELEMENT_END.equals(token)) {
121 break;
122 } else if (":".equals(token)) {
123 continue;
124 } else {
125 if (checkAndSetProcessingTime(token, gct, sample)) {
126 continue;
127 }
128 if (checkAndSetTransitionHeap(token, gct, sample)) {
129 continue;
130 }
131 gct.skipLine();
132 throw new IllegalStateException("token '" + token
133 + "' is invalid.");
134 }
135 }
136 if (sample.getPermGC().getAfterSize() == -1) {
137 sample.getPermGC().setBeforeSize(currentPermSize);
138 sample.getPermGC().setAfterSize(currentPermSize);
139 sample.getPermGC().setMaxSize(currentPermMax);
140 } else {
141 currentPermSize = sample.getPermGC().getAfterSize();
142 currentPermMax = sample.getPermGC().getMaxSize();
143 }
144 return sample;
145 }
146
147 public void processCMS(String keyToken, GCTokenizer gct, GCSample sample)
148 throws IOException {
149 String token = gct.getToken();
150 if (":".equals(token)) {
151 GCTransition tenuredGC = getTenuredGC("CMS", gct);
152 sample.setTenuredGC(tenuredGC);
153 } else if ("(".equals(token)) {
154 gct.skipTo(')');
155 GCTransition tenuredGC = getTenuredGC("CMS", gct);
156 sample.setTenuredGC(tenuredGC);
157 } else if ("Perm".equals(token)) {
158 GCTransition permGC = getPermGC("CMS", gct);
159 sample.setPermGC(permGC);
160 } else {
161 gct.skipLine();
162 throw new IllegalStateException("token '" + token + "' is invalid.");
163 }
164 }
165
166 public GCTransition getNewGC(String keyToken, GCTokenizer gct)
167 throws IOException {
168 GCTransition result = new GCTransition();
169 String token = keyToken;
170
171 while (true) {
172 if ("DefNew".equals(token) || "ParNew".equals(token)
173 || "PSYoungGen".equals(token)) {
174 token = gct.getToken();
175 continue;
176 }
177 if (ELEMENT_END.equals(token)) {
178 break;
179 }
180 if (ELEMENT_FIRST.equals(token)) {
181 gct.skipTo(']');
182 token = gct.getToken();
183 continue;
184 }
185 if (":".equals(token)) {
186 token = gct.getToken();
187 continue;
188 }
189 if ("(".equals(token)) {
190 gct.skipTo(')');
191 token = gct.getToken();
192 continue;
193 }
194 if (checkAndSetTransitionHeap(token, gct, result)) {
195 token = gct.getToken();
196 continue;
197 }
198 if (checkAndSetProcessingTime(token, gct, result)) {
199 token = gct.getToken();
200 continue;
201 }
202 gct.skipLine();
203 throw new IllegalStateException("token '" + token + "' is invalid.");
204 }
205 return result;
206 }
207
208 public GCTransition getTenuredGC(String keyToken, GCTokenizer gct)
209 throws IOException {
210 GCTransition result = new GCTransition();
211
212 String token = keyToken;
213 while (true) {
214 if ("Tenured".equals(token) || "CMS".equals(token)) {
215 token = gct.getToken();
216 continue;
217 }
218 if (ELEMENT_END.equals(token)) {
219 break;
220 }
221 if (ELEMENT_FIRST.equals(token)) {
222 gct.skipTo(']');
223 token = gct.getToken();
224 continue;
225 }
226 if (":".equals(token)) {
227 token = gct.getToken();
228 continue;
229 }
230 if ("(".equals(token)) {
231 gct.skipTo(')');
232 token = gct.getToken();
233 continue;
234 }
235 if (checkAndSetTransitionHeap(token, gct, result)) {
236 token = gct.getToken();
237 continue;
238 }
239 if (checkAndSetProcessingTime(token, gct, result)) {
240 token = gct.getToken();
241 continue;
242 }
243 gct.skipLine();
244 throw new IllegalStateException("token '" + token + "' is invalid.");
245 }
246 return result;
247 }
248
249 public GCTransition getPermGC(String keyToken, GCTokenizer gct)
250 throws IOException {
251 GCTransition result = new GCTransition();
252 while (true) {
253 String token = gct.getToken();
254 if (ELEMENT_END.equals(token)) {
255 break;
256 }
257 if (ELEMENT_FIRST.equals(token)) {
258 gct.skipTo(']');
259 }
260 if (":".equals(token)) {
261 continue;
262 }
263 if (checkAndSetTransitionHeap(token, gct, result)) {
264 continue;
265 }
266 if (checkAndSetProcessingTime(token, gct, result)) {
267 continue;
268 }
269 gct.skipLine();
270 throw new IllegalStateException("token '" + token + "' is invalid.");
271 }
272 return result;
273 }
274
275 public boolean checkAndSetTransitionHeap(String token, GCTokenizer gct,
276 GCTransition transition) throws IOException {
277 Matcher matcher = transitionHeapPattern.matcher(token);
278 if (matcher.matches()) {
279 long before = Long.parseLong(matcher.group(1));
280 long after = Long.parseLong(matcher.group(2));
281 transition.setBeforeSize(before);
282 transition.setAfterSize(after);
283
284 gct.getToken(); // "("
285 matcher = numberHeapPattern.matcher(gct.getToken());
286 if (matcher.matches()) {
287 long max = Long.parseLong(matcher.group(1));
288 transition.setMaxSize(max);
289 }
290 gct.getToken(); // ")"
291 return true;
292 }
293 return false;
294 }
295
296 public boolean checkAndSetProcessingTime(String token, GCTokenizer gct,
297 GCTransition transition) throws IOException {
298 Matcher matcher = numberPattern.matcher(token);
299 if (matcher.matches()) {
300 String nextToken = gct.getToken();
301 if ("secs".equals(nextToken)) {
302 double time = Double.parseDouble(token);
303 transition.setProcessingTime((long) (time * 1000));
304 }
305 return true;
306 }
307 return false;
308 }
309
310 }