Data paging and sorting

by Tobias Hertkorn on May 17th, 2006

I got interested in paging and sorting on large tables. And I found a couple of very good pointers, that I wanted to share with you:

A LOT to read. ;) Does anybody have more pointers? I am especially interested in anything related to the ObjectDataSource.

May 17th, 2006 11:03 am | Comments (5)

Using a more accurate approach to Timing

by Tobias Hertkorn on May 16th, 2006

As of .NET 2.0 there is a new class called StopWatch in System.Diagnostics. It is very easy to use. I just found it, while playing around with my Md5 optimization "project".

For all of you that can't upgrade to Framework 2.0 yet - here is the implementation I used to time my md5 algos. It is loosely based on the high performance timer Daniel Strigl posted on codeproject. I enhanced it a little bit in order to be able to use it running Mono on Linux. In that case it defaults to DateTime.Tick accuracy.

C#:
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using System.Threading;
  4.  
  5. namespace Md5Optimized
  6. {
  7.     public class PerformanceTimer
  8.     {
  9.         public static readonly bool IsHighPerformance;
  10.  
  11.         [DllImport("Kernel32.dll")]
  12.         private static extern bool QueryPerformanceCounter(
  13.                 out long lpPerformanceCount);
  14.  
  15.         [DllImport("Kernel32.dll")]
  16.         private static extern bool QueryPerformanceFrequency(
  17.                 out long lpFrequency);
  18.  
  19.         private long m_startTime;
  20.         private long m_stopTime;
  21.         private static long m_freq;
  22.  
  23.         static PerformanceTimer()
  24.         {
  25.             try
  26.             {
  27.                 IsHighPerformance =
  28.                    QueryPerformanceFrequency(out m_freq);
  29.             }
  30.             catch (Exception)
  31.             {
  32.                 IsHighPerformance = false;
  33.             }
  34.  
  35.         }
  36.  
  37.         public PerformanceTimer()
  38.         {
  39.             m_startTime = 0;
  40.             m_stopTime = 0;
  41.         }
  42.  
  43.         /// <summary>
  44.         /// Start the timer
  45.         /// </summary>
  46.         public void Start()
  47.         {
  48.             // let the waiting threads do their work
  49.             Thread.Sleep(0);
  50.  
  51.             if (IsHighPerformance)
  52.             {
  53.                 QueryPerformanceCounter(out m_startTime);
  54.             }
  55.             else
  56.             {
  57.                 m_startTime = DateTime.Now.Ticks;
  58.             }
  59.         }
  60.  
  61.         /// <summary>
  62.         /// Stop the timer
  63.         /// </summary>
  64.         public void Stop()
  65.         {
  66.             if (IsHighPerformance)
  67.             {
  68.                 QueryPerformanceCounter(out m_stopTime);
  69.             }
  70.             else
  71.             {
  72.                 m_stopTime = DateTime.Now.Ticks;
  73.             }
  74.         }
  75.  
  76.         /// <summary>
  77.         /// Returns the duration of the timer
  78.         /// (in fraction of seconds)
  79.         /// </summary>         
  80.         public double DurationSeconds
  81.         {
  82.             get
  83.             {
  84.                 if (IsHighPerformance)
  85.                 {
  86.                     return (double)(m_stopTime - m_startTime) /
  87.                         (double)m_freq;
  88.                 }
  89.                 else
  90.                 {
  91.                     TimeSpan span =
  92.                         (new DateTime(m_stopTime)) -
  93.                         (new DateTime(m_startTime));
  94.                     return span.TotalSeconds;
  95.                 }
  96.             }
  97.         }
  98.     }
  99. }

Please keep in mind that this class is a quick hack. It works... ;) but only if used correctly.

Download PerformanceTimer.cs

May 16th, 2006 4:45 pm | Comments (9)

Still MD5ing (insomnia style)

by Tobias Hertkorn on April 30th, 2006

Weeeell, turns out there was still a LOT to gain by safe-Code related optimizations. Thank God for insomnia. Now even Microsoft's .NET produces faster MD5 with safe code (about 3%). Sweet! Well, that proves once again, don't ever assume anything, when it comes to optimization, ever. I made the error to assume that pointer operations would be faster, but unfortunatelly (or fortunatelly?!?) that's not the case here.

Btw: Coding stuff like

C#:
  1. buffer[shift] = ...;
  2. buffer[shift + 1] = ...;
  3. buffer[shift + 2] = ...;

is way faster than

C#:
  1. buffer[shift] = ...;
  2. buffer[++shift] = ...;
  3. buffer[++shift] = ...;

even though it is best to avoid arrays as much as you can! ;) But, damn, damn - I am so not looking forward to catagolizing all the optimizations I made. Not even making a list of what is better than something else, since it is obvious that the only way to find that one out is to try - but even just a list of stuff I did ... Oh, well - maybe tomorrow... Or during the next case of insomnia

April 30th, 2006 7:35 pm | Comments (0)

MD5 Optimizations for C#

by Tobias Hertkorn on April 29th, 2006

OMG, I just spent an entire day optimizing - or trying - the MD5 algorithm for C#. Especially since the one shipped with mono right now is slooooooow when all optimizations are enabled (yeah, go figure. ;) ). Now I am frustrated, because optimizing is such a hassle, especially when it involves JIT... Well, the code is now quite a bit faster than the default implementation MD5CryptoServiceProvider. (About 40%) But here is one of the many things that are a bit weird. The MD5-Algo has a step that looks like

C#:
  1. a += ((b & c) | (~b & d)) + _decodeBuf0 + (int)0xd76aa478;

which can be translated into

C#:
  1. a += (d ^ (b & (c ^ d))) + _decodeBuf0 + (int)0xd76aa478;

This actually does increase the speed of the Transform step. But in Microsoft's .NET, using the SAME optimization 10 lines further down is decreasing performance! Why, oh, why? ;) Well, at least mono is well behaved. On the other hand, mono is actually quite surprising, too: It performs best, when there is no Unsafe code involved! Even the highest optimized version, using pointers and all kinds of tricks in unsafe mode is about 5% slower than the safe version!
But here is the problem: Now I have like 10 different types of optimizations. Which are all optimal for a specific framework, platform and/or hardware. (yeah, I tested on several different machines) Btw.: Arrays are extremely slow in Microsoft's .NET, but quite fast in Mono... So, what's the solution to my problem? What we need is a library that has like a calibration routine that will choose the right code. ;)

I'll probably post the code of the optimized code, the framework to choose the right optimization and the Testprograms in a couple of days.

Conclusion:
Once again it became clear that there is no such thing as THE optimization.

For the purists (and my source for the implementation - minus the Appendix):
The MD5 RFC 1321

April 29th, 2006 6:01 pm | Comments (7)
Tobi + C# = T# - Blogged blogoscoop