|
namespace ZED.Utility.Development
{
using Microsoft.VisualBasic;
using System;
using System.IO;
using System.Text;
/// <copyright>
/// ###########################################################################
/// ## Copyright (c) 2008 Warrick Procter. ##
/// ## ##
/// ## This work is covered by the "Code Project Open License", a copy of ##
/// ## which is enclosed with this package as: ##
/// ## "Code Project Open License (CPOL).txt", ##
/// ## and is available from http://www.codeproject.com/. ##
/// ## ##
/// ## No other use is permitted without the express prior written ##
/// ## permission of Warrick Procter. ##
/// ## For permission, try these contact addresses (current at the time of ##
/// ## writing): ##
/// ## procter_AT_xtra_DOT_co_DOT_nz ##
/// ## The address for service of company "ZED Limited", New Zealand. ##
/// ## ##
/// ## Redistribution and use in source and binary forms, with or without ##
/// ## modification, are permitted provided that the following conditions ##
/// ## are met: ##
/// ## 1. Redistributions of source code must retain the above copyright ##
/// ## notice, this list of conditions and the following disclaimer. ##
/// ## 2. Redistributions in binary form must reproduce the above copyright ##
/// ## notice in the documentation and/or other materials provided with ##
/// ## the distribution. ##
/// ###########################################################################
/// </copyright>
/// <disclaimer>
/// ###########################################################################
/// ## REPRESENTATIONS, WARRANTIES AND DISCLAIMER ##
/// ## ------------------------------------------ ##
/// ## THIS WORK IS PROVIDED "AS IS", "WHERE IS" AND "AS AVAILABLE", WITHOUT ##
/// ## ANY EXPRESS OR IMPLIED WARRANTIES OR CONDITIONS OR GUARANTEES. YOU, ##
/// ## THE USER, ASSUME ALL RISK IN ITS USE, INCLUDING COPYRIGHT ##
/// ## INFRINGEMENT, PATENT INFRINGEMENT, SUITABILITY, ETC. AUTHOR EXPRESSLY ##
/// ## DISCLAIMS ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES OR CONDITIONS, ##
/// ## INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF ##
/// ## MERCHANTABILITY, MERCHANTABLE QUALITY OR FITNESS FOR A PARTICULAR ##
/// ## PURPOSE, OR ANY WARRANTY OF TITLE OR NON-INFRINGEMENT, OR THAT THE ##
/// ## WORK (OR ANY PORTION THEREOF) IS CORRECT, USEFUL, BUG-FREE OR FREE OF ##
/// ## VIRUSES. YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU DISTRIBUTE THE ##
/// ## WORK OR DERIVATIVE WORKS. ##
/// ###########################################################################
/// </disclaimer>
/// <history>
/// 2008-05-11 [Warrick Procter] Created.
/// </history>
/// <summary>
/// clsBaseSpeedTestAB - Speed tests.
/// </summary>
/// <overview>
/// </overview>
/// <remarks>
/// </remarks>
/// <notes>
/// </notes>
public abstract class clsBaseSpeedTestAB
{
protected string f_DescribeA;
protected string f_DescribeB;
protected string f_DescribeControl;
protected TimeSpan f_ElapsedA;
protected TimeSpan f_ElapsedB;
protected TimeSpan f_ElapsedControl;
protected int f_RepeatA;
protected int f_RepeatB;
protected int f_RepeatControl;
protected int f_Repetitions;
protected TimeSpan f_TimeSpanA;
protected TimeSpan f_TimeSpanB;
protected int f_UnitInt;
protected double f_UnitsA;
protected double f_UnitsB;
protected string f_UnitStr;
protected const int kREPETITIONS = 0x186a0;
/// <summary>
/// Construct a default new speed test with kREPETITIONS repetitions.
/// </summary>
/// <remarks></remarks>
public clsBaseSpeedTestAB()
{
this.f_DescribeControl = "Empty method to measure method overhead.";
this.f_Repetitions = 0x186a0;
this.Initialise();
}
/// <summary>
/// Construct a new speed test with prescribed repetitions.
/// </summary>
/// <param name="aRepetitions"></param>
/// <remarks></remarks>
public clsBaseSpeedTestAB(int aRepetitions)
{
this.f_DescribeControl = "Empty method to measure method overhead.";
this.f_Repetitions = aRepetitions;
this.Initialise();
}
/// <summary>
/// Append the results to file.
/// </summary>
/// <param name="aFilePath">Path of the file to write to.</param>
/// <remarks></remarks>
public void AppendResults(string aFilePath)
{
StreamWriter xStrm = new StreamWriter(aFilePath, true);
xStrm.WriteLine();
xStrm.WriteLine(this.GetResults());
xStrm.Close();
}
/// <summary>
/// OVERRIDABLE: Get the number of repetitions.
/// </summary>
/// <returns>Int32 number of repetitions.</returns>
protected virtual int GetRepetitions()
{
return this.f_Repetitions;
}
/// <summary>
/// OVERRIDABLE: Get the results stringbuilder
/// </summary>
/// <returns></returns>
protected virtual StringBuilder GetResults()
{
StringBuilder xStr = new StringBuilder();
xStr.AppendLine("TEST RESULTS:");
xStr.Append(this.f_Repetitions.ToString("#,##0"));
xStr.AppendLine(" repetitions.");
xStr.Append("Test A: ");
xStr.AppendLine(this.f_DescribeA);
xStr.Append("Test B: ");
xStr.AppendLine(this.f_DescribeB);
xStr.Append(this.f_ElapsedControl.ToString().PadRight(0x11, ' '));
xStr.AppendLine(" hh:mm:ss.ff Equivalent Elapsed Time Control Process.");
xStr.Append(this.f_ElapsedA.ToString().PadRight(0x11, ' '));
xStr.AppendLine(" hh:mm:ss.ff Total Elapsed Time Process A.");
xStr.Append(this.f_ElapsedB.ToString().PadRight(0x11, ' '));
xStr.AppendLine(" hh:mm:ss.ff Total Elapsed Time Process B.");
xStr.Append(this.f_TimeSpanA.ToString().PadRight(0x11, ' '));
xStr.AppendLine(" hh:mm:ss.ff Net Elapsed Time Process A.");
xStr.Append(this.f_TimeSpanB.ToString().PadRight(0x11, ' '));
xStr.AppendLine(" hh:mm:ss.ff Net Elapsed Time Process B.");
xStr.Append("Net Unit Processing Time A: ");
xStr.Append(this.f_UnitsA.ToString("#,##0.000").PadLeft(13, ' '));
xStr.Append(" ");
xStr.AppendLine(this.f_UnitStr);
xStr.Append("Net Unit Processing Time B: ");
xStr.Append(this.f_UnitsB.ToString("#,##0.000").PadLeft(13, ' '));
xStr.Append(" ");
xStr.AppendLine(this.f_UnitStr);
xStr.AppendLine(this.GetResultsSummary().ToString());
return xStr;
}
/// <summary>
/// OVERRIDABLE: Get the summary of results.
/// </summary>
/// <returns></returns>
protected virtual StringBuilder GetResultsSummary()
{
double xFraction;
StringBuilder xStr = new StringBuilder();
if (this.f_TimeSpanB.Ticks == 0L)
{
xFraction = 0.0;
}
else
{
xFraction = (100.0 * this.f_TimeSpanA.Ticks) / ((double) this.f_TimeSpanB.Ticks);
}
xStr.Append(xFraction.ToString("#,##0.000"));
xStr.AppendLine("% Percentage: Process A divided by Process B.");
return xStr;
}
/// <summary>
/// Initialise fields.
/// </summary>
/// <remarks></remarks>
protected virtual void Initialise()
{
this.f_ElapsedA = TimeSpan.Zero;
this.f_RepeatA = 0;
this.f_ElapsedB = TimeSpan.Zero;
this.f_RepeatB = 0;
this.f_ElapsedControl = TimeSpan.Zero;
this.f_RepeatControl = 0;
}
/// <summary>
/// Get the string results.
/// </summary>
/// <returns></returns>
public string Results()
{
return this.GetResults().ToString();
}
/// <summary>
/// OVERRIDABLE: Conduct the speed test.
/// </summary>
/// <remarks></remarks>
public virtual void RunTest()
{
int xRepetitions = this.GetRepetitions();
this.f_Repetitions = xRepetitions;
if (xRepetitions <= 0)
{
Interaction.MsgBox("Please set a positive number of repetitions.", MsgBoxStyle.OkOnly, null);
}
else
{
this.Initialise();
this.RunTestA();
this.RunTestB();
DateTime xStart = DateAndTime.Now;
for (int xCnt = 1; xCnt <= xRepetitions; xCnt++)
{
this.SpeedTestControl();
}
TimeSpan xSpan = (TimeSpan) (DateAndTime.Now - xStart);
this.f_ElapsedControl += xSpan;
this.f_RepeatControl += xRepetitions;
long xTicks = (long) Math.Round((double) (((double) (this.f_ElapsedControl.Ticks * this.f_Repetitions)) / ((double) this.f_RepeatControl)));
this.f_ElapsedControl = new TimeSpan(xTicks);
this.f_UnitInt = 1;
this.f_UnitStr = "secs";
this.f_UnitsA = this.f_TimeSpanA.TotalSeconds / ((double) this.f_RepeatA);
this.f_UnitsB = this.f_TimeSpanB.TotalSeconds / ((double) this.f_RepeatA);
this.ScaleUnits();
}
}
/// <summary>
/// OVERRIDABLE: Run the Control Test and Test A.
/// </summary>
/// <remarks></remarks>
protected virtual void RunTestA()
{
int xCnt;
DateTime xStart = DateAndTime.Now;
for (xCnt = 1; xCnt <= this.f_Repetitions; xCnt++)
{
this.SpeedTestControl();
}
TimeSpan xSpanControl = (TimeSpan) (DateAndTime.Now - xStart);
this.f_ElapsedControl += xSpanControl;
this.f_RepeatControl += this.f_Repetitions;
this.SetUpTestA();
xStart = DateAndTime.Now;
for (xCnt = 1; xCnt <= this.f_Repetitions; xCnt++)
{
this.SpeedTestA();
}
TimeSpan xSpanTest = (TimeSpan) (DateAndTime.Now - xStart);
this.f_ElapsedA = xSpanTest;
this.f_RepeatA = this.f_Repetitions;
if (xSpanTest.Ticks > xSpanControl.Ticks)
{
this.f_TimeSpanA = this.f_ElapsedA - xSpanControl;
}
else
{
this.f_TimeSpanA = TimeSpan.Zero;
}
}
/// <summary>
/// OVERRIDABLE: Run the Control Test and Test B.
/// </summary>
/// <remarks></remarks>
protected virtual void RunTestB()
{
int xCnt;
DateTime xStart = DateAndTime.Now;
for (xCnt = 1; xCnt <= this.f_Repetitions; xCnt++)
{
this.SpeedTestControl();
}
TimeSpan xSpanControl = (TimeSpan) (DateAndTime.Now - xStart);
this.f_ElapsedControl += xSpanControl;
this.f_RepeatControl += this.f_Repetitions;
this.SetUpTestB();
xStart = DateAndTime.Now;
for (xCnt = 1; xCnt <= this.f_Repetitions; xCnt++)
{
this.SpeedTestB();
}
TimeSpan xSpanTest = (TimeSpan) (DateAndTime.Now - xStart);
this.f_ElapsedB = xSpanTest;
this.f_RepeatB = this.f_Repetitions;
if (xSpanTest.Ticks > xSpanControl.Ticks)
{
this.f_TimeSpanB = this.f_ElapsedB - xSpanControl;
}
else
{
this.f_TimeSpanB = TimeSpan.Zero;
}
}
/// <summary>
/// OVERRIDABLE: Scale result units so they register between 0.000 and 1000.999.
/// </summary>
/// <remarks></remarks>
protected virtual void ScaleUnits()
{
while (((this.f_UnitsA > 100.0) | (this.f_UnitsB > 100.0)) & (this.f_UnitStr != "hours"))
{
if (this.f_UnitStr == "secs")
{
this.f_UnitsA /= 60.0;
this.f_UnitsB /= 60.0;
this.f_UnitStr = "mins";
}
else if (this.f_UnitStr == "mins")
{
this.f_UnitsA /= 60.0;
this.f_UnitsB /= 60.0;
this.f_UnitStr = "hours";
}
}
while (((this.f_UnitsA < 1.0) | (this.f_UnitsB < 1.0)) & (this.f_UnitStr != "nanosecs"))
{
if (this.f_UnitStr == "secs")
{
this.f_UnitsA *= 1000.0;
this.f_UnitsB *= 1000.0;
this.f_UnitStr = "millisecs";
}
else if (this.f_UnitStr == "millisecs")
{
this.f_UnitsA *= 1000.0;
this.f_UnitsB *= 1000.0;
this.f_UnitStr = "microsecs";
}
else if (this.f_UnitStr == "microsecs")
{
this.f_UnitsA *= 1000.0;
this.f_UnitsB *= 1000.0;
this.f_UnitStr = "nanosecs";
}
}
}
/// <summary>
/// Overriden speed test A setup.
/// </summary>
/// <remarks></remarks>
protected abstract void SetUpTestA();
/// <summary>
/// Overriden speed test A setup.
/// </summary>
/// <remarks></remarks>
protected abstract void SetUpTestB();
/// <summary>
/// Show the results in a message box..
/// </summary>
/// <remarks></remarks>
public void ShowResults()
{
Interaction.MsgBox(this.GetResults().ToString(), MsgBoxStyle.OkOnly, null);
}
/// <summary>
/// Overridden Speed Test A.
/// </summary>
/// <remarks></remarks>
protected abstract void SpeedTestA();
/// <summary>
/// Overridden Speed Test B.
/// </summary>
/// <remarks></remarks>
protected abstract void SpeedTestB();
/// <summary>
/// Control speed test method. Just measures infrastructure overhead.
/// </summary>
/// <remarks></remarks>
public void SpeedTestControl()
{
}
/// <summary>
/// Write the results to stream.
/// </summary>
/// <param name="aFileStream">The stream to write to.</param>
/// <remarks></remarks>
public void WriteResults(Stream aFileStream)
{
new StreamWriter(aFileStream).WriteLine(this.GetResults());
}
/// <summary>
/// Write the results to file.
/// </summary>
/// <param name="aFilePath">Path of the file to write to.</param>
/// <remarks></remarks>
public void WriteResults(string aFilePath)
{
StreamWriter xStrm = new StreamWriter(aFilePath);
xStrm.WriteLine(this.GetResults());
xStrm.Close();
}
/// <summary>
/// Write the results to file.
/// </summary>
/// <param name="aFilePath">Path of the file to write to.</param>
/// <param name="aAppend">True to append to the file, otherwise False.</param>
/// <remarks></remarks>
public void WriteResults(string aFilePath, bool aAppend)
{
StreamWriter xStrm = new StreamWriter(aFilePath, aAppend);
xStrm.WriteLine(this.GetResults());
xStrm.Close();
}
/// <summary>
/// Get the net millisecond time elapsed for process A repetitions.
/// </summary>
/// <value>Timespan in milliseconds.</value>
/// <remarks></remarks>
public TimeSpan NetTimeA
{
get
{
return this.f_TimeSpanA;
}
}
/// <summary>
/// Get the net millisecond time elapsed for process B repetitions.
/// </summary>
/// <value>Timespan in milliseconds.</value>
/// <remarks></remarks>
public double NetTimeB
{
get
{
double xDblB = (1000.0 * this.f_ElapsedB.TotalSeconds) / ((double) this.f_RepeatB);
double xDblC = (1000.0 * this.f_ElapsedControl.TotalSeconds) / ((double) this.f_RepeatControl);
if (xDblC > xDblB)
{
return 0.0;
}
return (xDblB - xDblC);
}
}
/// <summary>
/// Get/Set the number of test repetitions.
/// </summary>
/// <value></value>
/// <remarks></remarks>
public int Repetitions
{
get
{
return this.f_Repetitions;
}
set
{
this.f_Repetitions = value;
this.Initialise();
}
}
/// <summary>
/// Get the total time elapsed for process A repetitions.
/// </summary>
/// <value>Timespan.</value>
/// <remarks></remarks>
public TimeSpan TotalTimeA
{
get
{
return this.f_ElapsedA;
}
}
/// <summary>
/// Get the total time elapsed for process B repetitions.
/// </summary>
/// <value>Timespan.</value>
/// <remarks></remarks>
public TimeSpan TotalTimeB
{
get
{
return this.f_ElapsedB;
}
}
/// <summary>
/// Get the total time elapsed for process Control. repetitions
/// </summary>
/// <value>Timespan.</value>
/// <remarks></remarks>
public TimeSpan TotalTimeControl
{
get
{
return new TimeSpan((long) Math.Round((double) (((double) this.f_ElapsedControl.Ticks) / 3.0)));
}
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.