/***************************************************************************** *********** Startup Stats *************************************************** ***************************************************************************** * Author: Christopher Suski * Last Modified: Feb 16, 2007 * Written For: Windows XP, Visual Studio 2005 * Description: * Statup Stats is a small program used to launch other applications with * or without command line arguments. It records how long the program took to * start and how much memory it used. It considers the start time for a * program to be the amount of processor time used until it no longer needed * the processor. This obviously won't work on any program that doesn't * reach a state where it no longer needs the processor. It also supports * batch files processing using a tab deliminated file, in the form: * processToExecute\targuments\tnumber of time to run * * * Lisence: BSD (below) */ using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.Threading; using System.IO; namespace AndAmp { class StartUpStats { ProcessStartInfo startInfo; Process proc; public long totalProc; public double endMem; public double peakMem; /// /// Initialize the start up stats class with an application /// and argument name. /// /// The executable to launch /// Arguments to pass to the executable public StartUpStats(String appName, String arguments) { startInfo = new ProcessStartInfo(appName, arguments); } /// /// Initialize the start up stats class with an application name /// /// The executable to launch public StartUpStats(String appName) { startInfo = new ProcessStartInfo(appName); } /// /// Launch the program and wait until it is no longer using the processor. /// public void test() { proc = Process.Start(startInfo); TimeSpan lastspan = proc.TotalProcessorTime; bool doneLoading = false; while (!doneLoading) { //We don't want to hog the CPU or we may get false 'completions' Thread.Sleep(5000); TimeSpan ts = proc.TotalProcessorTime; if (ts.Equals(lastspan)) { doneLoading = true; } else { lastspan = ts; } } totalProc = lastspan.Milliseconds; endMem = proc.WorkingSet64/1024; peakMem = proc.PeakWorkingSet64/1024; } /// /// Close the window and wait a bit. /// public void stop() { proc.CloseMainWindow(); Thread.Sleep(5000); } /// /// Main entry point /// /// Command line arguments static void Main(String []args) { StartUpStats process = null; if(args.Length == 1) { process = new StartUpStats(args[0]); } else if (args.Length == 2) { if (args[0] == "-B") { batchProcess(args[1]); return; } else { process = new StartUpStats(args[0], args[1]); } } else { usage(); return; } try { process.test(); Console.WriteLine("Time: " + process.totalProc + "ms"); Console.WriteLine("Working Set: " + process.endMem + "k"); Console.WriteLine("Peak Working Set: " + process.peakMem + "k"); } catch (Exception e) { Console.WriteLine(e.ToString()); usage(); return; } } /// /// Read and start processing a batch file, which is a tab deliminated list. /// /// static void batchProcess(String filename) { //Batch Process generates a CSV file (redirect stdout to a file) //Write header Console.WriteLine("Command, TotalTime(ms), CurrentMem(kb), PeakMem(kb)"); try { using (StreamReader sr = new StreamReader(filename)) { String line; // Read and display lines from the file until the end of // the file is reached. while ((line = sr.ReadLine()) != null) { if (line.StartsWith("#")) //Comment continue; String []split = line.Split(new char[] { '\t' }); int numRuns=0; String exec = null; String argument = null; if (split.Length == 2) { exec = split[0]; numRuns = Int32.Parse(split[1]); } else if (split.Length == 3) { exec = split[0]; argument = split[1]; numRuns = Int32.Parse(split[2]); } else { Console.Error.WriteLine("Error processing Batch command: " + line); continue; } try { String values = averageStats(exec, argument, numRuns); Console.WriteLine(values); } catch (Exception e) { Console.Error.WriteLine("Error starting batch command: " + line); Console.Error.WriteLine(e.ToString()); } } } } catch (FileNotFoundException) { Console.Error.WriteLine("File '" + filename + "' not found."); } catch (Exception e) { Console.WriteLine(e.ToString()); } } /// /// Run a process multiple times and average all the statistics. /// /// The program to run /// Arguments for that program /// Number of times to run the program /// static String averageStats(String exec, String arg, int runs) { double totalPeakMemory=0; double totalEndMemory=0; long totalTotalProcTime=0; //heh for (int i = 0; i < runs; i++) { StartUpStats proc = null; if (arg == null) proc = new StartUpStats(exec); else proc = new StartUpStats(exec, arg); proc.test(); totalEndMemory += proc.endMem; totalPeakMemory += proc.peakMem; totalTotalProcTime += proc.totalProc; proc.stop(); } totalTotalProcTime /= runs; totalEndMemory /= runs; totalPeakMemory /= runs; //return it as a csv string return (exec + " " + arg + ", " + totalTotalProcTime + ", " + totalEndMemory + ", " + totalPeakMemory); } /// /// Print out usage procedure /// static void usage() { Console.Error.WriteLine("Usage:\n\nStartUpStats ApplicatioName [argument]"); Console.Error.WriteLine("\tRun the Applications with the optional argument"); Console.Error.WriteLine("StartUpStats -B fileName"); Console.Error.WriteLine("\tRun a batch file, which contains a series of Applications to start and optional arguments, 1 per line"); } } } /* Copyright (c) 2007, Christopher Suski * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Andamp nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Christopher Suski``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */