Created
February 3, 2016 06:45
-
-
Save Zodiase/d38ebb1a9155923a0c3d to your computer and use it in GitHub Desktop.
Performance comparison between Math.Abs and conditional negation.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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