159 lines
5.5 KiB
C#
159 lines
5.5 KiB
C#
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.Text;
|
|
using Windows;
|
|
|
|
namespace timerun
|
|
{
|
|
class timerun
|
|
{
|
|
static int Main(string[] args)
|
|
{
|
|
try
|
|
{
|
|
if (args.Length < 1)
|
|
{
|
|
Usage();
|
|
return 1;
|
|
}
|
|
|
|
string program = args[0];
|
|
string arguments = String.Join(" ", args, 1, args.Length - 1);
|
|
|
|
IntPtr job_handle = Kernel32.CreateJobObject();
|
|
if (job_handle == IntPtr.Zero)
|
|
{
|
|
WriteLine("WARNING: Failed to create job object; cannot gather CPU usage info.");
|
|
}
|
|
|
|
using (Process process = new Process())
|
|
{
|
|
process.StartInfo.UseShellExecute = false;
|
|
process.StartInfo.Arguments = arguments;
|
|
process.StartInfo.FileName = program;
|
|
|
|
DateTime timeStarted = DateTime.Now;
|
|
|
|
process.Start();
|
|
|
|
if (job_handle != IntPtr.Zero)
|
|
{
|
|
if (!Kernel32.AssignProcessToJobObject(job_handle, process.Handle))
|
|
{
|
|
WriteLine("WARNING: Failed to assign child process to job.");
|
|
WriteLine("The process may have already terminated.");
|
|
}
|
|
}
|
|
|
|
process.WaitForExit();
|
|
|
|
DateTime timeEnded = DateTime.Now;
|
|
|
|
TimeSpan elapsed = timeEnded - timeStarted;
|
|
|
|
const string times_format = " {0,-32} : {1}";
|
|
|
|
if (job_handle != IntPtr.Zero)
|
|
{
|
|
try
|
|
{
|
|
JOBOBJECT_BASIC_ACCOUNTING_INFORMATION job_info;
|
|
job_info = Kernel32.QueryJobObjectBasicAccountingInformation(job_handle);
|
|
|
|
TimeSpan total_job_time = job_info.TotalUserTime + job_info.TotalKernelTime;
|
|
|
|
WriteLine(
|
|
times_format,
|
|
"CPU time consumed by jobs",
|
|
total_job_time);
|
|
|
|
WriteLine(
|
|
times_format,
|
|
" in user mode",
|
|
job_info.TotalUserTime);
|
|
|
|
WriteLine(
|
|
times_format,
|
|
" in kernel mode",
|
|
job_info.TotalKernelTime);
|
|
|
|
WriteLine(
|
|
times_format,
|
|
"Elapsed time (wall time)",
|
|
elapsed);
|
|
|
|
WriteLine("");
|
|
if (elapsed.TotalMilliseconds > 0)
|
|
{
|
|
double elapsed_ms = elapsed.TotalMilliseconds;
|
|
double total_job_ms = total_job_time.TotalMilliseconds;
|
|
double throughput_ratio = total_job_ms / elapsed_ms;
|
|
double throughput_percent = Math.Round(throughput_ratio * 100.0);
|
|
WriteLine(" Parallel throughput ratio: {0}%", throughput_percent);
|
|
}
|
|
else
|
|
{
|
|
WriteLine(" Too little time elapsed to compute ratio.");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
WriteLine("FAILED to query job info!");
|
|
ShowException(ex);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WriteLine(" Child process times not available.");
|
|
}
|
|
|
|
return process.ExitCode;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ShowException(ex);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
static void WriteLine(string line)
|
|
{
|
|
Console.WriteLine(Prefix + line);
|
|
}
|
|
|
|
static void WriteLine(string format, params object[] args)
|
|
{
|
|
WriteLine(String.Format(format, args));
|
|
}
|
|
|
|
const string Prefix = "TIMERUN: ";
|
|
|
|
static void Usage()
|
|
{
|
|
Console.WriteLine("Usage: TIMERUN program args ...");
|
|
Console.WriteLine();
|
|
Console.WriteLine(" TIMERUN runs a program, then displays CPU usage information for the program");
|
|
Console.WriteLine(" and all of its child processes.");
|
|
}
|
|
|
|
static void ShowException(Exception chain)
|
|
{
|
|
for (Exception ex = chain; ex != null; ex = ex.InnerException)
|
|
{
|
|
Console.WriteLine(ex.GetType().FullName + ": " + ex.Message);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|