Who we are

We are the developers of Plastic SCM, a full version control stack (not a Git variant). We work on the strongest branching and merging you can find, and a core that doesn't cringe with huge binaries and repos. We also develop the GUIs, mergetools and everything needed to give you the full version control stack.

If you want to give it a try, download it from here.

We also code SemanticMerge, and the gmaster Git client.

C# Mono performance

Sunday, November 25, 2007 Pablo Santos , 4 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.


Pablo Santos
I'm the CTO and Founder at Códice.
I've been leading Plastic SCM since 2005. My passion is helping teams work better through version control.
I had the opportunity to see teams from many different industries at work while I helped them improving their version control practices.
I really enjoy teaching (I've been a University professor for 6+ years) and sharing my experience in talks and articles.
And I love simple code. You can reach me at @psluaces.


  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...