.Net Programming Hints - Performance Improvement

<< Click to Display Table of Contents >>

Navigation:  Programming with Common Vision Blox > Compiler specific hints > .NET languages and CVB Programming Hints >

.Net Programming Hints - Performance Improvement

 

When using unmanaged binaries like the Common Vision Blox DLL or ActiveX controls in a managed application, the data for function calls need to be passed back and forth ("marshaled") between the managed and the unmanaged domain.

The Common Language Runtime (CLR) performs fairly strict and potentially time consuming tests in an effort to ensure the managed application's stability.

Therefore it is generally desirable to keep the managed-unmanaged transitions to a minimum.

 

Marshaling comes in two flavors named COM-Interop and P/Invoke.
The latter is applied to regular DLL function calls, while the first is reserved for COM objects (and therefore also applies to ActiveX controls).
As COM-Interop calls are significantly slower, the general rule to keep the managed-unmanaged transitions to a minimum becomes a lot more urgent when dealing with ActiveX controls.

A poorly shaped loop over an Image control's ImageWidth and ImageHeight properties can easily slow a loop that could otherwise be processed in a few milliseconds down to seconds!

 

Consider for example the following sample code (to be compiled with the /unsafe flag) that inverts plane 0 of an image:

 

[...]        

for (int y = 0; y<axCVimage.ImageHeight; y++)

{   

  IntPtr imageBaseAddress;

  IntPtr addrVPAT;

  Cvb.Image.GetImageVPA(AxCVimage.Image, 0, out imageBaseAddress, out addrVPAT);

   Cvb.Image.tagVPAEntry* pVPAT = (Image.tagVPAEntry*)addrVPAT.ToPointer();

  byte* pImageLine = (byte*)imageBaseAddress + pVPAT[y].YEntry;

   

    for(int x = 0; x<axCVimage.ImageWidth; x++)

     {

        *(pImageLine + pVPAT[x].XEntry) = (byte)(255 - *(pImageLine + pVPAT[x].XEntry));

     }

}

  
 

Simply by caching a few values and taking them outside the loop the function executes about 1 to 2 orders faster:

 

[...]

int imgHeight = axCVimage.ImageHeight;

int imgWidth = axCVimage.ImageWidth;

IntPtr imageBaseAddress;

IntPtr addrVPAT;

Cvb.Image.tagVPAEntry* pVPAT;

Cvb.Image.GetImageVPA(axCVimage.Image, 0, out imageBaseAddress, out addrVPAT);

   pVPAT = (Image.tagVPAEntry*)addrVPAT.ToPointer();

 

  for(int y = 0; y<imgHeight; y++)

   {

      byte* pImageLine = (byte*)imageBaseAddress + pVPAT[y].YEntry;

      for(int x = 0; x<imgWidth; x++)

      {

         *(pImageLine + pVPAT[x].XEntry) = (byte)(255 - *(pImageLine + pVPAT[x].XEntry));

      }

   }