Skip to content

Instantly share code, notes, and snippets.

@Zodiase
Created February 3, 2016 06:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zodiase/d38ebb1a9155923a0c3d to your computer and use it in GitHub Desktop.
Save Zodiase/d38ebb1a9155923a0c3d to your computer and use it in GitHub Desktop.
Performance comparison between Math.Abs and conditional negation.
using System;
using System.Diagnostics;
namespace CsTests
{
class Program
{
public static void Main (string[] args)
{
Console.WriteLine ("Hello World!");
DisplayTimerProperties();
Console.WriteLine();
Console.WriteLine("Press the Enter key to begin:");
Console.ReadLine();
Console.WriteLine();
Time_Abs_vs_If();
}
public static void DisplayTimerProperties()
{
// Display the timer frequency and resolution.
if (Stopwatch.IsHighResolution)
{
Console.WriteLine("Operations timed using the system's high-resolution performance counter.");
}
else
{
Console.WriteLine("Operations timed using the DateTime class.");
}
long frequency = Stopwatch.Frequency;
Console.WriteLine(" Timer frequency in ticks per second = {0}", frequency);
long nanosecPerTick = (1000L*1000L*1000L) / frequency;
Console.WriteLine(" Timer is accurate within {0} nanoseconds", nanosecPerTick);
}
private static void Time_Abs_vs_If()
{
long nanosecPerTick = (1000L*1000L*1000L) / Stopwatch.Frequency;
const long numIterations = 10000;
// Define the operation title names.
String [] operationNames = {
"Operation: Math.Abs with integers",
"Operation: If with \"-\" with integers",
"Operation: Math.Abs with floats",
"Operation: If with \"-\" with floats",
};
// Time four different implementations for parsing
// an integer from a string.
for (int operation = 0; operation <= 3; operation++)
{
// Define variables for operation statistics.
long numTicks = 0;
long numRollovers = 0;
long maxTicks = 0;
long minTicks = Int64.MaxValue;
int indexFastest = -1;
int indexSlowest = -1;
long milliSec = 0;
int testRange = 1000;
Stopwatch time10kOperations = Stopwatch.StartNew();
// Run the current operation 10001 times.
// The first execution time will be tossed
// out, since it can skew the average time.
for (int i=0; i<=numIterations; i++)
{
long ticksThisTime = 0;
int intValue = 0;
float floatValue = 0;
Stopwatch timePerParse;
switch (operation)
{
case 0:
// Get non-negative integer numbers using Abs function.
// Start a new stopwatch timer.
timePerParse = Stopwatch.StartNew();
for (int rawValue = -testRange, end = testRange; rawValue < end; rawValue++) {
intValue = Math.Abs (rawValue);
}
// Stop the timer, and save the
// elapsed ticks for the operation.
timePerParse.Stop();
ticksThisTime = timePerParse.ElapsedTicks;
break;
case 1:
// Get non-negative integer numbers using If statement and negation.
// Start a new stopwatch timer.
timePerParse = Stopwatch.StartNew();
for (int rawValue = -testRange, end = testRange; rawValue < end; rawValue++) {
intValue = (rawValue < 0) ? -rawValue : rawValue;
}
// Stop the timer, and save the
// elapsed ticks for the operation.
timePerParse.Stop();
ticksThisTime = timePerParse.ElapsedTicks;
break;
case 2:
// Get non-negative float numbers using Abs function.
// Start a new stopwatch timer.
timePerParse = Stopwatch.StartNew();
for (float rawValue = -(float)testRange, end = (float)testRange; rawValue < end; rawValue++) {
floatValue = Math.Abs (rawValue);
}
// Stop the timer, and save the
// elapsed ticks for the operation.
timePerParse.Stop();
ticksThisTime = timePerParse.ElapsedTicks;
break;
case 3:
// Get non-negative float numbers using If statement and negation.
// Start a new stopwatch timer.
timePerParse = Stopwatch.StartNew();
for (float rawValue = -(float)testRange, end = (float)testRange; rawValue < end; rawValue++) {
floatValue = (rawValue < 0) ? -rawValue : rawValue;
}
// Stop the timer, and save the
// elapsed ticks for the operation.
timePerParse.Stop();
ticksThisTime = timePerParse.ElapsedTicks;
break;
default:
break;
}
// Use variable to get rid of the warning.
if (intValue > 0) {}
if (floatValue > 0) {}
// Skip over the time for the first operation,
// just in case it caused a one-time
// performance hit.
if (i == 0)
{
time10kOperations.Reset();
time10kOperations.Start();
}
else
{
// Update operation statistics
// for iterations 1-10001.
if (maxTicks < ticksThisTime)
{
indexSlowest = i;
maxTicks = ticksThisTime;
}
if (minTicks > ticksThisTime)
{
indexFastest = i;
minTicks = ticksThisTime;
}
numTicks += ticksThisTime;
if (numTicks < ticksThisTime)
{
// Keep track of rollovers.
numRollovers ++;
}
}
}
// Display the statistics for 10000 iterations.
time10kOperations.Stop();
milliSec = time10kOperations.ElapsedMilliseconds;
Console.WriteLine();
Console.WriteLine("{0} Summary:", operationNames[operation]);
Console.WriteLine(" Slowest time: #{0}/{1} = {2} ticks",
indexSlowest, numIterations, maxTicks);
Console.WriteLine(" Fastest time: #{0}/{1} = {2} ticks",
indexFastest, numIterations, minTicks);
Console.WriteLine(" Average time: {0} ticks = {1} nanoseconds",
numTicks / numIterations,
(numTicks * nanosecPerTick) / numIterations );
Console.WriteLine(" Total time looping through {0} operations: {1} milliseconds",
numIterations, milliSec);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment