singrdk/base/Windows/timerun/timerun.cs

143 lines
5.2 KiB
C#

// ----------------------------------------------------------------------------
//
// 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);
}
}
}
}