1 28 29 30 package com.caucho.tools.profiler; 31 32 import com.caucho.util.CharBuffer; 33 import com.caucho.util.L10N; 34 import com.caucho.util.Sprintf; 35 import com.caucho.vfs.XmlWriter; 36 37 import javax.servlet.ServletException ; 38 import javax.servlet.http.HttpServlet ; 39 import javax.servlet.http.HttpServletRequest ; 40 import javax.servlet.http.HttpServletResponse ; 41 import java.io.IOException ; 42 import java.util.Collection ; 43 44 47 public class ProfilerServlet 48 extends HttpServlet 49 { 50 private static final L10N L = new L10N(ProfilerServlet.class); 51 52 private final ProfilerManager _profilerManager = ProfilerManager.getLocal(); 54 55 public ProfilerManager createProfiler() 56 { 57 return _profilerManager; 58 } 59 60 public void init() 61 { 62 } 63 64 protected void doGet(HttpServletRequest req, HttpServletResponse res) 65 throws ServletException , IOException 66 { 67 handleRequest(req, res); 68 handleResponse(req, res); 69 } 70 71 protected void doPost(HttpServletRequest req, HttpServletResponse res) 72 throws ServletException , IOException 73 { 74 handleRequest(req, res); 75 handleResponse(req, res); 76 } 77 78 protected void handleRequest(HttpServletRequest request, 79 HttpServletResponse response) 80 throws ServletException , IOException 81 { 82 } 83 84 protected void handleResponse(HttpServletRequest request, 85 HttpServletResponse response) 86 throws ServletException , IOException 87 { 88 String format = request.getParameter("format"); 89 boolean isXml = "xml".equals(format); 90 91 response.setContentType("text/html"); 92 93 response.setHeader("Cache-Control", "no-cache, post-check=0, pre-check=0"); 94 response.setHeader("Pragma", "no-cache"); 95 response.setHeader("Expires", "Thu, 01 Dec 1994 16:00:00 GMT"); 96 97 if (isXml) 98 writeXml(request, response); 99 else 100 writeHtml(request, response); 101 } 102 103 protected void writeHtml(HttpServletRequest request, 104 HttpServletResponse response) 105 throws ServletException , IOException 106 { 107 response.setContentType("text/html"); 108 109 String sort = request.getParameter("sort"); 110 111 ProfilerNodeComparator comparator; 112 113 if ("count".equals(sort)) 114 comparator = new CountComparator(); 115 else 116 comparator = new TimeComparator(); 117 118 comparator.setDescending(true); 119 120 XmlWriter out = new XmlWriter(response.getWriter()); 121 122 out.setStrategy(XmlWriter.HTML); 123 out.setIndenting(false); 124 125 out.println( 126 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"); 127 128 String contextPath = request.getContextPath(); 129 130 if (contextPath == null || contextPath.length() == 0) 131 contextPath = "/"; 132 133 String title = L.l("Profiling Results for {0}", contextPath); 134 135 out.startElement("html"); 136 137 out.startElement("head"); 138 out.writeElement("title", title); 139 140 out.startElement("style"); 141 out.writeAttribute("type", "text/css"); 142 143 out.println( 144 "h1 { background: #ccddff; margin : 0 -0.5em 0.25em -0.25em; padding: 0.25em 0.25em; }"); 145 out.println( 146 "h2 { background: #ccddff; padding: 0.25em 0.5em; margin : 0.5em -0.5em; }"); 147 out.println("table { border-collapse : collapse; }"); 148 out.println("th { background : #c78ae6; border-left : 1px; border-right : 1px}"); 149 out.println("tr { border-bottom : 1px dotted; }"); 150 out.println(".number { text-align : right; }"); 151 out.println("table table tr { border-bottom : none; }"); 152 153 out.endElement("style"); 154 155 out.endElement("head"); 156 157 out.startElement("body"); 158 out.writeElement("h1", title); 159 160 out.startElement("table"); 161 out.writeAttribute("border", 0); 162 163 out.startElement("tr"); 164 165 out.writeLineElement("th", L.l("Name")); 166 167 out.writeLineElement("th", L.l("Average Time")); 168 out.writeLineElement("th", L.l("Min Time")); 169 out.writeLineElement("th", L.l("Max Time")); 170 out.writeLineElement("th", L.l("Total Time")); 171 172 out.writeLineElement("th", L.l("Invocation Count")); 173 174 out.endElement("tr"); 175 176 Collection <ProfilerNode> children 177 = _profilerManager.getChildProfilerNodes(null, comparator); 178 179 displayChildren(children, comparator, out, 0); 180 181 out.endElement("table"); 182 183 out.endElement("body"); 184 185 out.endElement("html"); 186 } 187 188 private void display(ProfilerNode node, 189 ProfilerNodeComparator comparator, 190 XmlWriter out, 191 int depth) 192 { 193 Collection <ProfilerNode> children 194 = _profilerManager.getChildProfilerNodes(node, comparator); 195 196 long thisTime = node.getTime(); 197 long minTime = node.getMinTime(); 198 long maxTime = node.getMaxTime(); 199 200 long childrenTime = 0; 201 202 for (ProfilerNode child : children) { 203 childrenTime += child.getTime(); 204 } 205 206 long totalTime = childrenTime + thisTime; 207 208 long invocationCount = node.getInvocationCount(); 209 long averageThisTime; 210 long averageTotalTime; 211 long averageChildrenTime; 212 213 if (invocationCount <= 0) { 214 averageThisTime = -1; 215 averageTotalTime = -1; 216 averageChildrenTime = -1; 217 } 218 else { 219 averageThisTime = thisTime / invocationCount; 220 averageTotalTime = totalTime / invocationCount; 221 averageChildrenTime = childrenTime / invocationCount; 222 } 223 224 out.startElement("tr"); 225 226 out.writeAttribute("class", "level" + depth); 227 228 230 out.startLineElement("td"); 231 232 out.startElement("table"); 233 out.startElement("tr"); 234 235 out.startLineElement("td"); 236 237 if (depth > 0) { 238 for (int i = depth; i > 0; i--) { 239 out.write(" "); 240 out.write(" "); 241 } 242 243 out.write("→"); 244 } 245 out.endLineElement("td"); 246 247 out.startLineElement("td"); 248 out.writeAttribute("class", "text"); 249 out.writeText(node.getName()); 250 out.endLineElement("td"); 251 252 out.endElement("tr"); 253 out.endElement("table"); 254 255 out.endLineElement("td"); 256 257 out.startLineElement("td"); 258 out.writeAttribute("class", "number"); 259 if (averageThisTime < 0) 260 out.write(" "); 261 else { 262 String averageTimeString = createTimeString(averageTotalTime, averageThisTime, averageChildrenTime); 263 out.writeAttribute("title", averageTimeString); 264 printTime(out, averageTotalTime); 265 } 266 267 out.endLineElement("td"); 268 269 out.startLineElement("td"); 270 out.writeAttribute("class", "number"); 271 if (minTime < Long.MAX_VALUE) 272 printTime(out, minTime); 273 else 274 out.print(" "); 275 out.endLineElement("td"); 276 277 out.startLineElement("td"); 278 out.writeAttribute("class", "number"); 279 if (Long.MIN_VALUE < maxTime) 280 printTime(out, maxTime); 281 else 282 out.print(" "); 283 out.endLineElement("td"); 284 285 out.startLineElement("td"); 286 out.writeAttribute("class", "number"); 287 String timeString = createTimeString(totalTime, thisTime, childrenTime); 288 out.writeAttribute("title", timeString); 289 printTime(out, totalTime); 290 out.endLineElement("td"); 291 292 out.startLineElement("td"); 293 out.writeAttribute("class", "number"); 294 out.print(invocationCount); 295 out.endLineElement("td"); 296 297 out.endElement("tr"); 298 299 301 displayChildren(children, comparator, out, depth + 1); 302 } 303 304 protected void writeXml(HttpServletRequest request, 305 HttpServletResponse response) 306 throws ServletException , IOException 307 { 308 ProfilerNodeComparator comparator = new TimeComparator(); 309 310 comparator.setDescending(true); 311 312 XmlWriter out = new XmlWriter(response.getWriter()); 313 314 out.setStrategy(XmlWriter.XML); 315 out.setIndenting(false); 316 317 String contextPath = request.getContextPath(); 318 319 if (contextPath == null || contextPath.length() == 0) 320 contextPath = "/"; 321 322 out.startElement("profile"); 323 out.writeLineElement("name", contextPath); 324 325 Collection <ProfilerNode> children 326 = _profilerManager.getChildProfilerNodes(null, comparator); 327 328 for (ProfilerNode child : children) 329 displayXml(child, comparator, out); 330 331 out.endElement("profile"); 332 } 333 334 private void displayXml(ProfilerNode node, 335 ProfilerNodeComparator comparator, 336 XmlWriter out) 337 { 338 Collection <ProfilerNode> children 339 = _profilerManager.getChildProfilerNodes(node, comparator); 340 341 long thisTime = node.getTime(); 342 long minTime = node.getMinTime(); 343 long maxTime = node.getMaxTime(); 344 345 long childrenTime = 0; 346 347 for (ProfilerNode child : children) { 348 childrenTime += child.getTime(); 349 } 350 351 long totalTime = childrenTime + thisTime; 352 353 long invocationCount = node.getInvocationCount(); 354 355 out.startBlockElement("node"); 356 out.writeLineElement("name", node.getName()); 357 358 if (minTime < Long.MAX_VALUE) 359 out.writeLineElement("min-time", String.valueOf(minTime)); 360 else 361 out.writeLineElement("min-time", "0"); 362 if (maxTime >= 0) 363 out.writeLineElement("max-time", String.valueOf(maxTime)); 364 else 365 out.writeLineElement("max-time", "0"); 366 out.writeLineElement("time", String.valueOf(thisTime)); 367 out.writeLineElement("total-time", String.valueOf(totalTime)); 368 out.writeLineElement("children-time", String.valueOf(childrenTime)); 369 out.writeLineElement("count", String.valueOf(invocationCount)); 370 371 for (ProfilerNode child : children) 372 displayXml(child, comparator, out); 373 374 out.endBlockElement("node"); 375 } 376 377 private String createTimeString(long totalTime, 378 long thisTime, 379 long childrenTime) 380 { 381 CharBuffer cb = new CharBuffer(); 382 383 cb.append("totalTime="); 384 formatTime(cb, totalTime); 385 386 cb.append(" thisTime="); 387 formatTime(cb, thisTime); 388 389 cb.append(" childrenTime="); 390 formatTime(cb, childrenTime); 391 392 return cb.toString(); 393 } 394 395 private void displayChildren(Collection <ProfilerNode> children, 396 ProfilerNodeComparator comparator, 397 XmlWriter out, 398 int depth) 399 { 400 402 for (ProfilerNode child : children) 403 display(child, comparator, out, depth); 404 } 405 406 private void printTime(XmlWriter out, long time) 407 { 408 CharBuffer cb = new CharBuffer(); 409 formatTime(cb, time); 410 out.writeText(cb.toString()); 411 } 412 413 private void formatTime(CharBuffer cb, long nanoseconds) 414 { 415 long milliseconds = nanoseconds / 1000000; 416 417 long minutes = milliseconds / 1000 / 60; 418 419 if (minutes > 0) { 420 Sprintf.sprintf(cb, "%d:", minutes); 421 milliseconds -= minutes * 60 * 1000; 422 } 423 424 long seconds = milliseconds / 1000; 425 426 if (minutes > 0) 427 Sprintf.sprintf(cb, "%02d.", seconds); 428 else 429 Sprintf.sprintf(cb, "%d.", seconds); 430 431 milliseconds -= seconds * 1000; 432 433 Sprintf.sprintf(cb, "%03d", milliseconds); 434 } 435 } 436 | Popular Tags |