[Mono-list] lies and microbenmarks (Was: Mono 0.23 windows installer)

David Jeske jeske@chat.net
Sun, 9 Mar 2003 10:37:24 -0800


--DKU6Jbt7q3WqK7+M
Content-Type: text/plain; charset=us-ascii

On Sat, Mar 08, 2003 at 07:28:08PM -0500, Duncan Mak wrote:
> I'm going on go have dinner now, but I just uploaded Johannes' new
> windows installer for Mono 0.23, it's available here:
> 
> http://primates.ximian.com/~duncan/mono-0.23-win32-1.exe

Wow, that was easy to install. Mono has come a long way.

I know that if there are two things in the world not to trust, they
are lies and microbenmarks. However, here are some mono vs. MS
microbenmarks for the Windows installer above.

Summary Observations:
  - mint failed to run the test
  - CSC speeds up MS more than Mono (somewhat expected)
  - mono is slower than MS
  - while many of the mono slowdowns seem related to JIT
    optimizations (which the new JIT will change and improve),
    the 2x slowdown in index_string_test points to a string,
    hashing, memory allocation, or other hashtable inefficiency
  - the mono 40% slowdown in object_test is interesting, both
    because the performance of method calls is very important,
    and because the CSC output makes the slowdown even worse
    by making MS faster and Mono slower.

* Compiled with MCS:

  (times are in seconds, lower is better)

test            iterations   Win-MS   Win-Mono   Mono-speedup
---------------------------------------------------------
loop_test           500000   0.03      0.02           33%
index_test         1000000   1.292     1.993      -   54%
index_string_test  1000000   0.341     1.081      -  217%
nested_int_test         23   0.01      0.02       -   50%
nested_test             23   0.02      0.331      - 1555%
return_test        5000000   0         0.01          n/a
object_test        5000000   0.05      0.07       -   40%


* Compiled with CSC:

  (times are in seconds, lower is better)
  (percentages are speedup of CSC output over MCS output)

test            iterations      Win-MS          Win-Mono 
----------------------------------------------------------
loop_test           500000   0.02  (+33%)   0.02    (  0%)
index_test         1000000   1.172 (+ 9%)   2.003   (- 0.5%)
index_string_test  1000000   0.33  (+ 3%)   1.091   (- 1%)
nested_int_test         23   0.01  (  0%)   0.02    (  0%)
nested_test             23   0.01  (+50%)   0.12    (+63%)
return_test        5000000   0.01   n/a     0.01    (  0%)
object_test        5000000   0.03  (+40%)   0.081   (-15%)

* Details

  Machine: Win2k, P4-1.8M, 768M (thinkpad A31)
  Win-MS: Microsoft .NET Framework v1.0.3705
  Win-Mono: mono-0.23 from duncan's installer
  Microbenchmark SW: http://mozart.chat.net/~jeske/Projects/ScriptPerf/
                     (C# version attached)

-- 
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + jeske@chat.net

--DKU6Jbt7q3WqK7+M
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="scriptperf.cs"

// Allow easy reference to classes in the System namespace
using System;
using System.Collections;


// This is the test class

class testObject {
  public virtual int dothis(int iter) {
    return iter;
  }
}

// This "class" exists only to house the application's entry-point function
class MainApp {

    public delegate void test_function(int INDEX);

    // loop_test

    public static void loop_test(int INDEX) {
      for(int x=0;x<INDEX;x++) {
        for(int j=0;j<19;j++) {
          // do nothing
        }
      }
    }

    // index_access

    public static void index_test(int INDEX) {
      Hashtable table = new Hashtable();
      for (int i=0;i<INDEX;i++) {
        table[i] = i;
      }
      for (int i=0;i<INDEX;i++) {
        i = (int) table[i];
      }
    }

    // index_string_test

    public static void index_string_test(int INDEX) {
      Hashtable table = new Hashtable();
      for (int i=0;i<INDEX;i++) {
        table["some_string"] = i;
      }
      for (int i=0;i<INDEX;i++) {
        i = (int) table["some_string"];
      }
    }

    // list_append_test

    public static void list_append_test(int INDEX) {
      ArrayList list = new ArrayList();
      for (int x=0;x<INDEX;x++) {
        list.Add(5);
      }
    }

    // list_traverse_test

    // system_test

    // basic fp arith

    public static void basic_fp_test(int INDEX) {
      double j = 3.14159265359;
      double k = 3.14159265359;

      for(int i=0;i<INDEX;i++) {
        j = (j * (1/2.71828182846)) + 2.71828182846;
        k = (k / 2.71828182846) - 2.71828182846;
      }
    }
    
    // complex FP arith

    public static void complex_fp_test(int INDEX) {
      double j = 0;

      for(int i=0;i<INDEX;i++) {
        j = j + Math.Sin( 3.14159265359 );
        j = j + Math.Sqrt ( 69.283848 );
      }
    }

    // file access test

    // nested loop test

    public static void nested_test(int NESTED) {
      double n = 0;
      int a,b,c,d,e;

      for(a=0;a<NESTED;a++) {
        n = n + 0.0342;
        for(b=0;b<NESTED;b++) {
          n = n + 0.723;
          for (c=0;c<NESTED;c++) {
            n = n * 0.0342;
            for (d=0;d<NESTED;d++) {
              n = n * 0.723;
              for (e=0;e<NESTED;e++) {
                n = n - 0.0342;
              }
            }
          }
        }
      }
    }

    // nested INT loop test

    public static void nested_int_test(int NESTED) {
      int n = 0;
      int a,b,c,d,e;

      for(a=0;a<NESTED;a++) {
        n = n + 34;
        for(b=0;b<NESTED;b++) {
          n = n + 9;
          for (c=0;c<NESTED;c++) {
            n = n + 5;
            for (d=0;d<NESTED;d++) {
              n = n + 3;
              for (e=0;e<NESTED;e++) {
                n = n - 100;
              }
            }
          }
        }
      }
    }

    // return test

    public static int doThisR(int a, int b) {
      return a;
    }

    public static void return_test(int INDEX) {
      int a;
      for(int x=0;x<INDEX;x++) {
        a = doThisR(1,2);
      }
    }

    // return 2 arguments test

    // function call test

    // object tests...

    public static void object_test(int INDEX) {
      int y;
      testObject obj = new testObject();

      for (int x=0;x<INDEX;x++) {
         y = obj.dothis(10);
      }
    }

    // ###########################################################

    public static void timefunk(String label, test_function f, int count) {
      int start, end, elapsed;
      start = Environment.TickCount;
      f(count);
      end = Environment.TickCount;

      elapsed = end-start;

      Console.WriteLine(label + "   " + count + " elapsed: " + (elapsed / 1000.0));
    }


    // Static method called "Main" is application's entry point function
    public static void Main() {
//	timefunk("list_append_test",new test_function(list_append_test),50000);
//	timefunk("list_traverse_test",new test_function(index_test),50000);

	timefunk("loop_test",new test_function(loop_test),500000);
	timefunk("index_test",new test_function(index_test),1000000);
	timefunk("index_string_test",new test_function(index_string_test),1000000);
	timefunk("nested_int_test",new test_function(nested_int_test),23);
	timefunk("nested_test",new test_function(nested_test),23);

	timefunk("return_test",new test_function(return_test),5000000);
	timefunk("object_test",new test_function(object_test),5000000);

    }
}

--DKU6Jbt7q3WqK7+M--