Posts filed under 'WinForms'
Fast rendering images in c#
I will start this article with example: let say, we have some kind of GPS application. Our goal is to draw object’s current position on map. We represent object by symbol and maybe by some string near it. The symbol and its related text not changing, the only thing changing is position of the object on the map. We have to update object position very frequently, let say once at 500 ms.
Obvious, this is waste of CPU time to draw the symbol and text again and again each 500 ms. One way to improve performance is to store our object representation image (symbol or/and text, whatever) in memory, and each time copy its bits to different place on the map. At this point, everyone who claims to be Windows programmer should flash in his head word “BitBlt”. If you didn’t, I suggest you to review Windows programming basics, start from reading ‘Programming Windows’ by Charles Petzold. In short, BitBlt is Windows API function, which is copying bits from one Device Context (DC) to other. The common use of this function is implementation of Double Buffering – well known techniques to draw without “flickering”.
In demo application I prepared (download link here – hosted by RapidShare), I drawing text “Test string” using 3 ways:
- Graphics.DrawString
- Graphics.DrawImageUnscaled (which is fastest method in DrawImageXXX series)
- Calling directly to unmanaged BitBlt function
To see differences in performance, I call each way 10000 times, and mesuring start and end times. Here are results (Athlon 64 bit dual core):
- Calling Graphics.DrawString – 3984.375 ms
- Calling Graphics.DrawImageUnscaled – 7765.625 ms
- Calling BitBlt – 1015.ms
Copying bits from memory is x8 times faster than drawing image directly!!! And x4 times faster rendering text. In additional, you have in your desposal all raster operations, which you can use inside BitBlt method, such as invert colors – very useful staff. By the way, .NET framework do provide one method which is wraps BitBlt – Graphics.CopyFromSceen method. As expected, inside it Microsoft guys calling BitBlt with 2 DCs: current graphics and Desktop hwnd (hwnd = NULL).
As far I know, this is the best you can do using GDI. Still, you can notice that my application even using BitBlt consuming very high CPU (on my machine – 50%). In case you need better performance, consider to use XNA (managed DirectX).
2 comments January 5, 2008
Making UI fast and responsive
Your application looks “heavy”? It takes time to move child window inside it, rearrange buttons, and overall performance is bad? Probably one of the reasons you using wrong threads for UI update. Here Ian Griffiths explains the right way to do this much better than I will could to.
Add comment December 23, 2007