Performance: If you can avoid Math.Max, then maybe it is for the best? (integer testing)

I realized there were quite a few APIs inside of the BCL that were using Math.Max and figured that couldn't be good, not good at all. Math.Max has more meaning when you are talking about floating point values, because of IsNaN checks. After all, if it is more than one line of code, then you are probably better off calling the method.

My tests focus on the concept of picking the largest element in a given array. This is quite popular in locations such as the DataSet, where you can get a Max/Min aggregate of a given column. Also popular in charting applications and spreadsheet style applications where you need to build boundings and all sorts of other goodies. I'm testing three methods, instead of just the two, since three are available. First, I'm testing Math.Max, which internally is just a tenerary operator wrapped in a function call. The function all aspect appears to be optimized away by the JIT... Good job JIT team! The second method is a basic if statement which turns out to be the fastest (because we aren't doing storage in every case). Finally you have a ternary operator thrown in to ensure we really are getting an inlined version of Math.Max earlier in the program.

using System;

public class MaxVersusIf {
    private static void Main(string[] args) {
        int[] values = new int[5000]; Random rand = new Random();
        int i = 0; int j = 0; int max = 0; int iterations = 1000000;
        for(i = 0; i < values.Length; i++) {
            values[i] = rand.Next(0, 100000);
        }
       
        DateTime start, end;
        start = DateTime.Now;
        for(i = 0; i < iterations; i++) {
            for(j = 0; j < values.Length; j++) {
                max = Math.Max(values[j], max);
            }
        }
        end = DateTime.Now;
        Console.WriteLine("Math.Max: {0}... Double Check {1}", end - start, max);

        max = 0;
        start = DateTime.Now;
        for(i = 0; i < iterations; i++) {
            for(j = 0; j < values.Length; j++) {
                if ( values[j] > max ) {
                    max = values[j];
                }
            }
        }
        end = DateTime.Now;
        Console.WriteLine("If Statement: {0}... Double Check {1}", end - start, max);

        max = 0;
        start = DateTime.Now;
        for(i = 0; i < iterations; i++) {
            for(j = 0; j < values.Length; j++) {
                max = (values[j] > max) ? values[j] : max;
            }
        }
        end = DateTime.Now;
        Console.WriteLine("Ternary Operator: {0}... Double Check {1}", end - start, max);
    }
}

The winner is the if statement by a land-slide, so it might be smarter to use that if you have a number of values you are checking, rather than using the built-in prototyping method in the Math library. Other functions, such as Min suffer the same performance hits, and you can probably better write the absolute value functions if you are careful of the MinValue overflow situations.

Math.Max: 00:00:07.3806128... Double Check 99976
If Statement: 00:00:05.5079200... Double Check 99976
Ternary Operator: 00:00:07.3205264... Double Check 99976

Published Thursday, September 23, 2004 11:50 PM by Justin Rogers

Comments

No Comments

Leave a Comment

(required) 
(required) 
(optional)
(required)