tbiro.com

Forums 
   HackPerfCounter
   RADPass
   SHEdit
   Toys
 
   Contact me
   My PGP Key
 

The long way home


Ah, let's talk about optimizing your code. Who knows the fastest way to XOR a two dimensional array in C? Or I have a better idea: let's not. Optimizing the code was not what it used to be. In the good old days performance could be used to justify the craziest things (Hey, who ate my cake? It was faster than going to the store for another one. Ah, makes sense, sorry I asked)

But things have changed and most of the time it is cheaper to add a new server to the farm than to pay 3 developers for a week to squeze a 10% improvement. Slow code wins the day because it is cheaper. The black art of optimizing your binaries is just not what it used to be even five years ago.

And then take the books. Most new editions would have you think that knowing how to optimize is no longer important. I do not think it is important from a performance point of view but rather to know another way of doing the same thing. And if this is the case it is just as important to be able to optimize as it is to un-optimize.

It all starts with a simple enough application.

Read something form a MDB database, write it to an Excel document. I choose to use the OleDB providers for both and to read with an OleDbReader. All was fine during testing and deployment but at some point I started getting error notification emails with a weird and random error.

Error Message: Unable to cast COM object of type 'System.__ComObject' to interface type 'IRowset'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{0C733A7C-2A1C-11CE-ADE5-00AA0044773D}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).
Error Source: System.Data

Strangely enough I could find nothing wrong in the code causing the problem

    ...
    using (OleDbDataReader reader = monthCommand.ExecuteReader())
    {
        while (reader.Read()) // error happens on this line
        {
    ...

but after some fiddling with the way the connection was maintained it seemed to be working again and life was good.

Yesterday though the darn thing started throwing the same error and no ammount of persuasion from me was able to make it stop. I tried everything short of rebooting the production server. Did I mention that it only happened in production?

So I'm working feverishly to fix this thing, the client nagging me all the way (he neded the produced report ASAP) so I decided to take the not-so-inspired way and use a DataSet to hold the data. Clearly the error is related to the way the reader is converted to a IRowset. A Microsoft KB article says that the thread that creates the Reader should be the same as the one that consumes it. Somehow I suppose they were not. A similar application of mine is doing everything on a uniue worker thread and I never got this error so I suppose this scenario might be correct.

So what to do? By now it is T+1H and the client is getting impatient. I see two ways:

  • move the processing on its own thread, pray the assumption above is correct.
  • Replace the Reader wit a DataSet and thus eliminate the object causing the error. (Everybody, all at once: eeeeeewwwwwwww)

Estimated effort for solution 1: 2+ hours

Estimated effort for solution 2: 0.5 hours

Client yells at me again so my mind is made: the DataSet it is.

Instead of using the reader fill the DataSet and close the connection.

    ...
    OleDbDataAdapter adapter = new OleDbDataAdapter(monthCommand);
    DataSet dataSet = new DataSet();

    adapter.Fill(dataSet);

    mdbConnection.Close();

    for(Int32 index=0; index<dataSet.Tables[0].Rows.Count; index++)
        {
    ...

By far not so elegant as the reader aproach but this one works all the time so my client prefers it. In the end software engineering had to bow to the problem and just make the friggin thing work!

Comments: tb@tbiro.com






Sitemap generated by Sitemap Manager