C# Mono performance

Sunday, November 25, 2007 , 5 Comments

I was reading through some server logs last week when I detected a performance problem. One database query was taking much more time than expected. The strange thing being I was sure I'd double-checked it in the past. I repeated the test in my laptop and the same performance hit showed up (even clearer taking into account the laptop CPU difference with the server).
Ok, just to give you some numbers:
  • The code took about 350ms (.NET 1.1) to execute the query and perform a reader.Read() loop until no more registers were read.
  • It included both reading plus processing time: each row had about 15 fields which were read with reader["myfield"] sentences.
  • The sample retrieved about 5000 rows.

Well, running exactly the same code using Mono the time reached 1800ms!! A huge performance loss!

Last week we were talking about Mono's string handling performance: while it outperforms .NET in integer based tests, it was clearly behind using strings. So I decided to make a obvious change: what if I accessed the data fields using the integer indexer instead of the string based one? I mean myfield = reader[0] instead of reader["myfield"]??

Well, then Mono took exactly the same time as .NET, which is slightly better than its string based counterpart.

So, until the string based operations get a bit optimized, you can count on the good-ol integer indexer to boost Mono based database access.



  1. Firebird 1.7.1
    But I don't think it is a provider issue but a much more generic one.

  2. Look at how weird Firebird's .NET Provider implementation is. Not only it takes O(|columns|) time to find a column every time you query a string, it does it using heavy Globalization stuff.
    Is a culture-aware comparison really needed? Ideally, you would use a Hashtable for this in order to answer queries in O(1), but a culture-aware comparison would make this a bit trickier.

    public object this[String name]
    get { return this.GetValue(this.GetOrdinal(name)); }

    public int GetOrdinal(string name)

    for (int i = 0; i < this.fields.Count; i++)
    if (GlobalizationHelper.CultureAwareCompare(name, this.fields[i].Alias))
    return i;
    throw new IndexOutOfRangeException("Could not find specified column in results.");

  3. Yeah, that's why getting rid of it pays off... but anyway, there's a difference between Mono and .NET here...

  4. Here is another database that is compatible with Mono: