/** * Run this tool with the specified command line arguments. This method works as following: * * <ol> * <li>It calls {@link #init()} to initialize this tool. * <li>It prints the {@link #getName() name}, {@link #getVersion() version}, and {@link * #getCopy() copyright} to the {@link Runtime#console() console}. * <li>If this tool has been invoked without arguments, it prints a description of all command * line {@link Runtime#printOptions() options} and, optionally, an {@link #getExplanation() * explanation}. It then exits. * <li>It {@link Runtime#process(String[]) processes} the specified command line arguments and * {@link #prepare() prepares} for processing the files. If any errors have been {@link * Runtime#seenError() reported} during the two method calls, it exits. * <li>For each file name specified on the command line, it {@link #locate(String) locates} the * file, {@link #parse(Reader,File) parses} the contents, and {@link #process(Node) * processes} the resulting AST. If the <code>-performance</code> command line option has * been specified, it repeatedly parses and processes each file, measuring both latency and * heap utilization. It then exits. * </ol> * * @param args The command line arguments. */ public void run(String[] args) { // Initialize this tool. init(); // Print the tool description and exit if there are no arguments. if (0 == args.length) { runtime.console().p(getName()).p(", v. ").p(getVersion()).p(", ").pln(getCopy()); runtime.console().pln().pln("Usage: <option>* <file-name>+").pln().pln("Options are:"); runtime.printOptions(); final String explanation = getExplanation(); if (null != explanation) { runtime.console().pln().wrap(0, explanation).pln(); } runtime.console().pln().flush(); if (runtime.hasValue("optionNoExit") && runtime.test("optionNoExit")) { return; } else { runtime.exit(); } } // Process the command line arguments and print tool name. int index = runtime.process(args); if ((!runtime.hasValue("optionSilent")) || (!runtime.test("optionSilent"))) { runtime.console().p(getName()).p(", v. ").p(getVersion()).p(", ").pln(getCopy()).flush(); } final boolean diagnose = runtime.hasValue("optionDiagnostics") && runtime.test("optionDiagnostics"); if (index >= args.length && !diagnose) { runtime.error("no file names specified"); } // Prepare for processing the files. prepare(); // Print diagnostics. if (diagnose) diagnose(); // Stop if there have been errors already. if (runtime.seenError()) { if (runtime.test("optionNoExit")) { return; } else { runtime.exit(); } } // Process the files. final boolean silent = runtime.test("optionSilent"); final boolean doGC = runtime.test("optionGC"); final boolean measure = runtime.test("optionPerformance"); final boolean parserOnly = runtime.test("optionMeasureParser"); final boolean processOnly = runtime.test("optionMeasureProcessing"); final int warmUp = measure ? runtime.getInt("runsWarmUp") : 0; final int total = measure ? runtime.getInt("runsTotal") : 1; final Statistics time = measure ? new Statistics() : null; final Statistics memory = measure ? new Statistics() : null; final Statistics fileSizes = measure ? new Statistics() : null; final Statistics latencies = measure ? new Statistics() : null; final Statistics heapSizes = measure ? new Statistics() : null; // If measuring, we need to print a legend. if (measure) { runtime .console() .p("Legend: file, size, time (ave, med, stdev), ") .pln("memory (ave, med, stdev)") .pln() .flush(); } while (index < args.length) { // If we are neither silent nor measuring, report on activity. if ((!silent) && (!measure)) { runtime.console().p("Processing ").p(args[index]).pln(" ...").flush(); } // Locate the file. File file = null; try { file = locate(args[index]); } catch (IllegalArgumentException x) { runtime.error(x.getMessage()); } catch (FileNotFoundException x) { runtime.error(x.getMessage()); } catch (IOException x) { if (null == x.getMessage()) { runtime.error(args[index] + ": I/O error"); } else { runtime.error(args[index] + ": " + x.getMessage()); } } catch (Throwable x) { runtime.error(); x.printStackTrace(); } // Parse and process the file. if (null != file) { if (measure) { time.reset(); memory.reset(); } for (int i = 0; i < total; i++) { Node ast = null; boolean success = false; // Perform GC if requested. if (doGC) { System.gc(); } // Measure performance if requested. long startTime = 0; long startMemory = 0; if (measure && (!processOnly)) { startMemory = java.lang.Runtime.getRuntime().freeMemory(); startTime = System.currentTimeMillis(); } // Parse the input. Reader in = null; try { in = runtime.getReader(file); ast = parse(in, file); success = true; } catch (IllegalArgumentException x) { runtime.error(x.getMessage()); } catch (FileNotFoundException x) { runtime.error(x.getMessage()); } catch (UnsupportedEncodingException x) { runtime.error(x.getMessage()); } catch (IOException x) { if (null == x.getMessage()) { runtime.error(args[index] + ": I/O error"); } else { runtime.error(args[index] + ": " + x.getMessage()); } } catch (ParseException x) { runtime.error(); System.err.print(x.getMessage()); } catch (Throwable x) { runtime.error(); x.printStackTrace(); } finally { if (null != in) { try { in.close(); } catch (IOException x) { // Nothing to see here. Move on. } } } if (success && (null != ast) && (!parserOnly)) { // Measure processing only if requested. if (measure && processOnly) { startMemory = java.lang.Runtime.getRuntime().freeMemory(); startTime = System.currentTimeMillis(); } // Process the AST. try { process(ast); } catch (VisitingException x) { runtime.error(); x.getCause().printStackTrace(); } catch (Throwable x) { runtime.error(); x.printStackTrace(); } } // Collect performance data for this run if requested. if (measure) { final long endTime = System.currentTimeMillis(); final long endMemory = java.lang.Runtime.getRuntime().freeMemory(); if (i >= warmUp) { time.add(endTime - startTime); memory.add(startMemory - endMemory); } } } // Collect performance data for all the file's runs if // requested. if (measure) { final long fileSize = file.length(); final double latency = time.mean(); final double heapSize = memory.mean(); fileSizes.add(fileSize / 1024.0); latencies.add(latency); heapSizes.add(heapSize / 1024.0); runtime .console() .p(args[index]) .p(' ') .p(fileSize) .p(' ') .p(Statistics.round(latency)) .p(' ') .p(time.median()) .p(' ') .p(Statistics.round(time.stdev())) .p(' ') .p(Statistics.round(heapSize)) .p(' ') .p(memory.median()) .p(' ') .pln(Statistics.round(memory.stdev())) .flush(); } } // Next file. index++; } // Wrap up. wrapUp(); // Print overall statistics, if requested. if (measure) { final double totalTime = latencies.sum(); final double totalMemory = heapSizes.sum(); final double throughput = 1000.0 / Statistics.fitSlope(fileSizes, latencies); final double heapUtil = Statistics.fitSlope(fileSizes, heapSizes); runtime .console() .pln() .p("Total time : ") .p(Statistics.round(totalTime)) .pln(" ms") .p("Total memory : ") .p(Statistics.round(totalMemory)) .pln(" KB") .p("Average throughput : ") .p(Statistics.round(throughput)) .pln(" KB/s") .p("Average heap utilization : ") .p(Statistics.round(heapUtil)) .pln(":1") .flush(); } // Done. if (!runtime.test("optionNoExit")) runtime.exit(); }
public void prepare() { super.prepare(); // Perform consistency checks on command line arguments. }