[Mono-list] Application performance question

Chad Robinson crj at lucubration.com
Fri Jan 13 16:02:46 EST 2006


This is my first foray into Mono (and C#), and I'm impressed. The developers
have done a wonderful job getting things running. I'm sorry if this question
seems lame or has come up before, but I haven't seen it addressed yet;
hopefully somebody can give me some insight.

I have Mono deployed on a Linux Pentium 4 3.2Ghz system with HyperThreading.
Plenty of RAM. Mono version from Web site as of yesterday, using GMCS.

I'm trying to write a performance-sensitive application, so I'm doing some
load testing at a fundamental level. I wrote the fairly simple application
attached below this message. It's pretty obvious. It just creates a collection
keyed with a ulong, and stores 100,000 items in it. It then references 200,000
keys, changing a field if the entry exists, adding a new entry if it doesn't.
(Net 100,000 changed, 100,000 added.) Finally, it deletes all 200,000 of the keys.

There are two blocks of code. One uses a traditional Hashtable. The other uses
the generic Dictionary class.

I'm confused. My understanding is that Dictionary is supposed to be much more
efficient here because it doesn't box and unbox. But, when I run the generic
version, it takes 4.18s to run on average, while the Hashtable version takes
2.54s to run. Despite the boxing, the Hashtable runs MUCH faster. This is
running with --optimize=all (doesn't seem to change anything either way).

On a Windows 2000 system with a 3.0GHz non-HyperThreading processor and Visual
Studio 2005, I get what I expect. The Hashtable version still takes about 2.5s
(just slightly faster), but the Dictionary version blows it away at 1.48s,
which is what you'd expect by eliminating the boxing.

My questions is why the Dictionary is so much slower on Linux. Can others
replicate this behavior?

If so, is it a fixable bug, or some other type of problem? I know generics are
part of the IL itself, so perhaps Mono isn't just handling them efficiently?

If that's the case, I can cope with it. I'll just use Hashtable for now, which
provides at least acceptable (and similar) performance across both platforms.
But if I'm doing something wrong, or there's something I can try/fix, I'd love
to know about it.

Regards,
Chad

--------------------------------------

using System;
using System.Collections;
using System.Collections.Generic;

public class Me {
    public class MyObject {
        public uint u1;
        public float f1;
        public uint u2;
        public uint u3;

        public MyObject(uint u1, float f1, uint u2, uint u3) {
            this.u1 = u1;
            this.f1 = f1;
            this.u2 = u2;
            this.u3 = u3;
        }

        public MyObject() {
            this.u1 = 1;
            this.f1 = 2.5F;
            this.u2 = 3;
            this.u3 = 4;
        }
    }

	public static void Main() {
		DateTime start = DateTime.Now, finish;

/*		
		      Dictionary<ulong, MyObject> dic = new Dictionary<ulong, MyObject>();

				MyObject po;

				for (ulong i = 0; i < 1000000; i++) {
					po = new MyObject();
					dic.Add(i, po);
				}

				for (ulong i = 0; i < 2000000; i++) {
					po = null;

					if (dic.TryGetValue(i, out po)) {
						po.u1 = (uint) i;
					} else {
						po = new MyObject();
						dic.Add(i, po);
					}
				}

				for (ulong i = 0; i < 2000000; i++) {
					if (dic.ContainsKey(i))
						dic.Remove(i);
				}
*/
		Hashtable dic = new Hashtable();
		MyObject po;

		for (ulong i = 0; i < 1000000; i++) {
			po = new MyObject();
			dic.Add(i, po);
		}

		for (ulong i = 0; i < 2000000; i++) {
			po = (MyObject)dic[i];

			if (po != null) {
				po.u1 = (uint)i;
			} else {
				po = new MyObject();
				dic.Add(i, po);
			}
		}

		for (ulong i = 0; i < 2000000; i++) {
			dic.Remove(i);
		}
		
		finish = DateTime.Now;
		Console.WriteLine(finish - start);
	}
}


More information about the Mono-list mailing list