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 }