/*****************************************************************************
*********** 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. */