Ureader.com  
Microsoft software help and Community
   home   |   control panel login   |   archive   |  
 
DotNet
acad.assignment.mngr
academic
adonet
aspnet
aspnet.announcements
aspnet.build.controls
aspnet.caching
aspnet.datagridcontrol
aspnet.mobile
aspnet.security
aspnet.webcontrols
aspnet.webservices
clr
compactframework
component_services
datatools
distributed_apps
drawing
faqs
framework
framework.wmi
general
internationalization
interop
languages.csharp
languages.jscript
languages.vb
languages.vb.controls
languages.vb.data
languages.vb.upgrade
languages.vc
languages.vc.libraries
myservices
odbcnet
performance
remoting
scripting
sdk
security
setup
vjsharp
vsa
webservi.enhancements
webservices
windowsforms
windowsforms.controls
winforms.databinding
winforms.designtime
xml
  
 
date: Mon, 18 Aug 2008 19:12:57 -0500,    group: microsoft.public.dotnet.framework        back       


Graphics.DrawImage is very slow   
Hi,

I'm trying to improve the painting performance of a control on my form.

The scenario is this - I have a custom control which inherits from Control, 
and I manually paint the entire GUI for it.  The GUI is fairly static, so 
once I've drawn the appropriate image, I cache that to an Image object and 
re-use that.

My code snippet is as follows:

Protected Overrides Sub OnPaint(ByVal e As 
System.Windows.Forms.PaintEventArgs)

    e.Graphics.DrawImage(_displayImage, e.ClipRectangle, e.ClipRectangle, 
GraphicsUnit.Pixel)

End Sub


Where _displayImage is the cached Image object.

Performance absolutely blows.  It's fine to initially paint the screen, but 
if I (for example) load up an instance of calculator and drag it over my 
application, repainting of these controls is incredibly slow.  I can 
literally saturate the GUI of my app (when it's covered with these custom 
controls) with ghostly trails of the calculator window.  Once I stop 
dragging the calc window, *then* my controls seem to update.

Is there some smarter solution?  I've tried using Graphics.DrawImageUnscaled 
but it seems to have no effect on performance.  My control is set to 
DoubleBuffer, UserPaint, and AllPaintingInWMPaint.  I'm surprised that this 
isn't faster, as all I'm doing is drawing an in-memory bitmap to the screen. 
I'm even using clipping so that it should only repaint the affected area.

Why so slow? :-(

Thanks,
Alex
date: Mon, 18 Aug 2008 19:12:57 -0500   author:   Alex Clark ail

Re: Graphics.DrawImage is very slow   
On Mon, 18 Aug 2008 17:12:57 -0700, Alex Clark <quanta@noemail.noemail>  
wrote:

> [...]
> The scenario is this - I have a custom control which inherits from  
> Control,
> and I manually paint the entire GUI for it.  The GUI is fairly static, so
> once I've drawn the appropriate image, I cache that to an Image object  
> and
> re-use that.
>
> [...]
> Performance absolutely blows.

All due respect, that's not a very useful description of the problem.  :)

> It's fine to initially paint the screen, but
> if I (for example) load up an instance of calculator and drag it over my
> application, repainting of these controls is incredibly slow.  I can
> literally saturate the GUI of my app (when it's covered with these custom
> controls) with ghostly trails of the calculator window.  Once I stop
> dragging the calc window, *then* my controls seem to update.

It sounds to me as though the controls aren't getting painted at all.  So  
I'm not sure what it means for it to be "incredibly slow".

That said, you mention that your application is "covered with these custom  
controls".  How many?  The fact is, there are practical limits to just how  
many controls you can put in a window and still expect reasonable drawing  
performance.  If you have a large number, performance will suffer.

It's also impossible to evaluate any sort of performance issue with just a  
code snippet.  You should post a concise-but-complete code sample that  
reliably demonstrates the problem.

Also, because this is a performance issue, you should be as specific about  
the details as you can.  What methods are being called?  How long do they  
take to execute?  How often are they called?  How sensitive to the number  
of controls being used is the issue?  That sort of thing.  Finally, it's  
important to be clear about what the system configuration is, especially  
the video card and CPU.

As a test, you could try using some built-in .NET control instead of your  
own in an otherwise-identical program and see how performance compares.   
That would at least give some information as to whether the performance  
issue is typical, or specific only to your custom control.

Pete
date: Mon, 18 Aug 2008 20:33:08 -0700   author:   Peter Duniho

Re: Graphics.DrawImage is very slow   
Hi Peter,

> All due respect, that's not a very useful description of the problem.  :)
lol, I know, sorry, I'll try to clear that up a bit below.

> It sounds to me as though the controls aren't getting painted at all.  So 
> I'm not sure what it means for it to be "incredibly slow".

The control *does* get repainted, but it's laggy.  If I drag calculator over 
my form, the calculator window sort of "streaks" across it, leaving ghostly 
images behind on the controls.  Eventually they repaint themselves but it 
can take a few seconds.  It's as though there's a long delay between the 
Invalidate and Paint calls, but I don't have any specific code in there that 
would cause that.  It's just taking a long time to refresh itself, it seems.

> That said, you mention that your application is "covered with these custom 
> controls".  How many?  The fact is, there are practical limits to just how 
> many controls you can put in a window and still expect reasonable drawing 
> performance.  If you have a large number, performance will suffer.

In all honesty it doesn't matter if it's covered in them or if it's just 
one, the problem happens regardless.  The most I'd fit on screen would be 
roughly 10 - we're talking full width, and about 64px height (sort of like 
list view items stacked one atop the other).

> It's also impossible to evaluate any sort of performance issue with just a 
> code snippet.  You should post a concise-but-complete code sample that 
> reliably demonstrates the problem.

I know, sorry, should've posted a snippet but the project is complex.  I'll 
try to extract the relevant stuff into a sample repro project.

> Also, because this is a performance issue, you should be as specific about 
> the details as you can.  What methods are being called?  How long do they 
> take to execute?  How often are they called?  How sensitive to the number 
> of controls being used is the issue?  That sort of thing.  Finally, it's 
> important to be clear about what the system configuration is, especially 
> the video card and CPU.

Methods: barely any.  Once I've created an appropriate bitmap (that's done 
early on) it's pretty much as simple as what I posted in the OP.  I override 
OnPaint, and call e.Graphics.DrawImage with my "here's one I made earlier" 
bitmap.  I clip it so that it should only repaint the invalidated area as 
well.  That is literally all it's doing, but between it getting invalidated 
(me dragging an app over the top of it) and it actually refreshing, there 
can be as much as a 3s delay (if I'm still rapidly dragging the other app 
around the screen).  CPU usage is high at the time as well.

Not really sensitive to the number of controls, it's slow with one, it's 
slow with 12.

System is moderate spec, XP Pro x64, 2GB DDR800, Pentium D 3.4, PCI Express 
128mb Radeon card.

> As a test, you could try using some built-in .NET control instead of your 
> own in an otherwise-identical program and see how performance compares. 
> That would at least give some information as to whether the performance 
> issue is typical, or specific only to your custom control.

No contest, if I use a dozen large Buttons, ComboBoxen, or even ListViews 
the repainting is snappy.  Ironically I did a test a while back with a .NET 
Panel control where I was painting a complex gradient bitmap with bubbles on 
the background (just handling the PaintBackground event).  With clipping and 
some smart caching of the bitmap, performance was beautiful and snappy, even 
in Debug mode.

Maybe it's because I'm inheriting from Control rather than UserControl or 
Panel?
date: Tue, 19 Aug 2008 15:15:28 -0500   author:   Alex Clark ail

Re: Graphics.DrawImage is very slow   
On Tue, 19 Aug 2008 13:15:28 -0700, Alex Clark <quanta@noemail.noemail>  
wrote:

> [...]
>> It sounds to me as though the controls aren't getting painted at all.   
>> So
>> I'm not sure what it means for it to be "incredibly slow".
>
> The control *does* get repainted, but it's laggy.  If I drag calculator  
> over
> my form, the calculator window sort of "streaks" across it, leaving  
> ghostly
> images behind on the controls.  Eventually they repaint themselves but it
> can take a few seconds.  It's as though there's a long delay between the
> Invalidate and Paint calls, but I don't have any specific code in there  
> that
> would cause that.  It's just taking a long time to refresh itself, it  
> seems.

I think I know what you mean, but you should try to be more precise.  I  
don't think you're calling Invalidate() at all (Windows is doing the  
invalidation internally as the other window moves over your control), and  
no painting is actually done until your OnPaint() method is called.

So, according to your description, it's not that the _painting_ is slow,  
but that the OnPaint() method is not even called until much later than you  
expect it to.

>> That said, you mention that your application is "covered with these  
>> custom
>> controls".  How many?  The fact is, there are practical limits to just  
>> how
>> many controls you can put in a window and still expect reasonable  
>> drawing
>> performance.  If you have a large number, performance will suffer.
>
> In all honesty it doesn't matter if it's covered in them or if it's just
> one, the problem happens regardless.

Then you definitely have something wrong with your own program.

> [...]
> I know, sorry, should've posted a snippet but the project is complex.  
> I'll
> try to extract the relevant stuff into a sample repro project.

If you don't solve it yourself, you should definitely do that.

I'd guess there's at least a 50/50 chance of you finding the problem  
yourself as you whittle your existing program down to something more  
suitable as a sample.

> [...] I clip it so that it should only repaint the invalidated area as
> well.  That is literally all it's doing, but between it getting  
> invalidated
> (me dragging an app over the top of it) and it actually refreshing, there
> can be as much as a 3s delay (if I'm still rapidly dragging the other app
> around the screen).  CPU usage is high at the time as well.

For what it's worth, using the ClipRectangle is probably pointless.  It's  
such a slight optimization and complicates the drawing.  If that code  
should ever have to change in the future, it could wind up broken because  
of the explicit use of ClipRectangle (i.e. something could change to make  
that rectangle unsuitable as a source or destination rectangle).

> [...]
> Maybe it's because I'm inheriting from Control rather than UserControl or
> Panel?

No, that's not the problem.

I wrote a simple test program that has a custom control (derived from  
Control) that just generates a Bitmap for use in an OnPaint() method.  I  
then ran the program and the Calculator accessory at the same time and had  
no trouble at all with performance, even with 20 instances of the control  
on my form.

Granted, I'm using 32-bit Windows.  I suppose you could be running into  
some sort of driver bug related to the 64-bit Windows stuff.  You should  
try the same code on a different computer, preferably a 32-bit XP system.

Barring that, without any sample code, I have to guess.  And my guess is  
that you've got something else going on in your program that is somehow  
tying up the GUI thread when the UI is invalidated by another window  
moving across it.  What that could be I have no idea.  But for sure, this  
is not a general issue that exists in .NET.  Assuming it's not a driver  
problem, this is fixable.  We just need to see a complete code sample that  
reproduces the issue.

Pete
date: Tue, 19 Aug 2008 15:23:55 -0700   author:   Peter Duniho

Re: Graphics.DrawImage is very slow   
Hi Peter,

(VB.NET Code)

This is what I've got in a testbed app.  This is the only code I've written 
inside Form1.

'---------------
    Protected Overrides Sub OnPaintBackground(ByVal e As 
System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaintBackground(e)

        e.Graphics.DrawImageUnscaled(GetBackgroundImage(e), 0, 0)

    End Sub

    Private Function GetBackgroundImage(ByVal e As PaintEventArgs) As Image

        Static _image As Image
        If Not IsNothing(_image) Then Return _image

        Dim rect As Rectangle
        Dim rgn As New Region
        Dim rnd As New Random(DateTime.Now.Millisecond)
        Dim xc, yc, iDeg As Integer


        If Not IsNothing(_image) Then
            Return _image
        Else
            _image = New Bitmap(picDraw.Width, picDraw.Height)
        End If


        rect = picDraw.ClientRectangle


        Using br As New LinearGradientBrush(rect, Color.Red, Color.Blue, 
LinearGradientMode.ForwardDiagonal)

            Using br2 As New LinearGradientBrush(rect, Color.Green, 
Color.Orange, LinearGradientMode.ForwardDiagonal)

                Using g As Graphics = Graphics.FromImage(_image)

                    g.SetClip(e.ClipRectangle, CombineMode.Replace)
                    g.FillRectangle(br, rect)

                    For x As Integer = 1 To 2000

                        xc = rnd.Next(0, picDraw.Width)
                        yc = rnd.Next(0, picDraw.Height)

                        g.DrawLine(Pens.White, xc, yc, xc + 10, yc + 10)

                        rnd = New Random(rnd.Next)
                        iDeg = rnd.Next(10, 360)
                        g.FillPie(br2, New Rectangle(xc, yc, 10, 10), 0, 
iDeg)

                    Next

                End Using

            End Using

        End Using

        Return _image

    End Function
'----------------------

Note that, in the call to GetBackgroundImage, if the image has already been 
created it just returns that.  This is obviously a simplified scenario 
because it doesn't repaint for resize etc, it literally only gets created 
one time.  Performance is better, but even in Release mode I'm not finding 
it to be fantastic.  I can drag calculator over the form and have a slightly 
laggy update of the image.  I suspect in my app it's more of a problem 
because I have a variety of controls which are all custom painting, and a 
selection of background threads doing monitoring work as well, which is 
probably stealing some degree of priority from the GUI thread.

It's probably a moot point anyway, because we're heading for a WPF rewrite 
soon and a lot of the tests I've done with that seem to display far better 
front end performance.  I just wondered if I was making some kind of 
schoolboy error in the calls to DrawImage, and if there was a much faster 
way to do it.

Thanks,
Alex
date: Thu, 21 Aug 2008 14:43:39 -0500   author:   Alex Clark ail

Re: Graphics.DrawImage is very slow   
On Thu, 21 Aug 2008 12:43:39 -0700, Alex Clark <quanta@noemail.noemail>  
wrote:

> [...] I just wondered if I was making some kind of
> schoolboy error in the calls to DrawImage, and if there was a much faster
> way to do it.

I don't see anything in the code you posted that would explain a  
performance issue (though I'm not sure why you have the second check for a  
null _image value).  I do wonder if the code you posted is _really_ the  
code you're using, since a static local would be shared across all  
instances of the control, which seems like an odd thing to do.

But as far as the performance issue goes, whatever it is, it's in code you  
didn't share.  I'm sure your code is somehow responsible for the slowdown,  
but whether it's a matter of a "schoolboy error" or something that's  
simply inherent in the design and not easily fixed, I can't say.

Pete
date: Thu, 21 Aug 2008 12:56:24 -0700   author:   Peter Duniho

Re: Graphics.DrawImage is very slow   
Hi Peter,

No, it's not the code I'm using, I was just using it to demonstrate a 
complex bitmap being created one time and then drawn on each call to 
OnPaint.

However, only after I posted the code did I recall I'd been testing painting 
through transparent controls (the OnPaint is for the Form, but creating the 
bitmap checks the size of a PictureBox control).  I was actually overlaying 
a transparent PictureBox on the form (dockstyle set to fill).  Once I 
removed that in my test app, the repainting performance was super snappy - 
even in *debug* mode.

So that sorta puts me straight back to the drawing board in terms of my own 
app, but at least it eliminates a good few things.  I think I'll try to 
"turn off" the background threads and see if that boosts foreground painting 
performance.



"Peter Duniho"  wrote in message 
news:op.uf85oah98jd0ej@petes-computer.local...
> On Thu, 21 Aug 2008 12:43:39 -0700, Alex Clark <quanta@noemail.noemail> 
> wrote:
>
>> [...] I just wondered if I was making some kind of
>> schoolboy error in the calls to DrawImage, and if there was a much faster
>> way to do it.
>
> I don't see anything in the code you posted that would explain a 
> performance issue (though I'm not sure why you have the second check for a 
> null _image value).  I do wonder if the code you posted is _really_ the 
> code you're using, since a static local would be shared across all 
> instances of the control, which seems like an odd thing to do.
>
> But as far as the performance issue goes, whatever it is, it's in code you 
> didn't share.  I'm sure your code is somehow responsible for the slowdown, 
> but whether it's a matter of a "schoolboy error" or something that's 
> simply inherent in the design and not easily fixed, I can't say.
>
> Pete
date: Thu, 21 Aug 2008 15:05:16 -0500   author:   Alex Clark ail

Re: Graphics.DrawImage is very slow   
On Thu, 21 Aug 2008 13:05:16 -0700, Alex Clark <quanta@noemail.noemail>  
wrote:

> Hi Peter,
>
> No, it's not the code I'm using, I was just using it to demonstrate a
> complex bitmap being created one time and then drawn on each call to
> OnPaint.

But that wasn't useful.  I can write that kind of code myself in five  
minutes, had already done so, and had already pointed out that it worked  
fine, without any performance issues at all.  Posting another "proof of  
concept" code snippet doesn't add anything to the discussion.

Unless you are posting a _complete_ code sample that you have tested  
yourself and verified that it reproduces the problem you're trying to  
illustrate, any code sample you post isn't going to be helpful in  
understanding the problem you're actually having.

> However, only after I posted the code did I recall I'd been testing  
> painting
> through transparent controls (the OnPaint is for the Form, but creating  
> the
> bitmap checks the size of a PictureBox control).  I was actually  
> overlaying
> a transparent PictureBox on the form (dockstyle set to fill).  Once I
> removed that in my test app, the repainting performance was super snappy  
> - even in *debug* mode.  [...]

I hope that sufficiently illustrates the importance of posting an _actual_  
concise-but-complete code sample that reliably demonstrates the problem.   
:)

Pete
date: Thu, 21 Aug 2008 16:32:15 -0700   author:   Peter Duniho

Re: Graphics.DrawImage is very slow   
Hi Peter,

I wasn't trying to insult or "dumb down" with the example, I just wanted to 
create something as concise as possible.  I thought at the time that because 
it was a complex bitmap with lots of gradients that maybe *that* was the 
cause of the slow drawing performance, i.e. that maybe GDI+ was having 
issues painting things more complex than just solid colours.

While trying to deconstruct my app I found what I believe to be the cause. 
The container control that these controls are in also has custom foreground 
painting, but *that* is what seems to have performance issues.  My guess is 
that as calc (or any app) is dragged over the top of my form, the container 
control gets the WM_INVALIDATE message (it's the first thing to be obscured) 
and then my child custom controls get invalidated.  Because it happens 
synchronously, and my container control is slow to paint, it's holding up 
the child controls from processing the message and repainting themselves.

Thanks for your help,
Alex
date: Fri, 22 Aug 2008 13:55:16 -0500   author:   Alex Clark ail

Re: Graphics.DrawImage is very slow   
On Fri, 22 Aug 2008 11:55:16 -0700, Alex Clark <quanta@noemail.noemail>  
wrote:

> Hi Peter,
>
> I wasn't trying to insult or "dumb down" with the example,

I'm not saying you were.

> I just wanted to
> create something as concise as possible.

But what you posted didn't reproduce the problem.

It's well and good to keep the example short.  But the highest priorities  
are "no code missing" and "reproduces the problem".

Without meeting those goals, especially the latter, a code example isn't  
likely to help others answer your question.

That's my point.

Pete
date: Fri, 22 Aug 2008 13:06:07 -0700   author:   Peter Duniho

Re: Graphics.DrawImage is very slow   
Dear Alex,

How did you paint the container control and the custom control? If you 
don't put the custom controls on the container control, do you still have 
the performance problem?

I'm looking forward to hearing from you.

Sincerely,
Zhi-Xin Ye
Microsoft Managed Newsgroup Support Team

Delighting our customers is our #1 priority. We welcome your comments and 
suggestions about how we can improve the support we provide to you. Please 
feel free to let my manager know what you think of the level of service 
provided. You can send feedback directly to my manager at: 
msdnmg@microsoft.com.

==================================================
Get notification to my posts through email? Please refer to 
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues 
where an initial response from the community or a Microsoft Support 
Engineer within 1 business day is acceptable. Please note that each follow 
up response may take approximately 2 business days as the support 
professional working with you may need further investigation to reach the 
most efficient resolution. The offering is not appropriate for situations 
that require urgent, real-time or phone-based interactions or complex 
project analysis and dump analysis issues. Issues of this nature are best 
handled working with a dedicated Microsoft Support Engineer by contacting 
Microsoft Customer Support Services (CSS) at 
http://support.microsoft.com/select/default.aspx?target=assistance&ln=en-us.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
date: Wed, 27 Aug 2008 07:13:32 GMT   author:   (Zhi-Xin Ye [MSFT])

Re: Graphics.DrawImage is very slow   
Hi Zhi-Xin,

It's a long story but I think I nailed most of the performance issues, it's 
repainting much faster and smoother now, so the issue is solved.

Many thanks,
Alex



"Zhi-Xin Ye [MSFT]"  wrote in message 
news:5Y%23fwRBCJHA.1768@TK2MSFTNGHUB02.phx.gbl...
> Dear Alex,
>
> How did you paint the container control and the custom control? If you
> don't put the custom controls on the container control, do you still have
> the performance problem?
>
> I'm looking forward to hearing from you.
>
> Sincerely,
> Zhi-Xin Ye
> Microsoft Managed Newsgroup Support Team
>
> Delighting our customers is our #1 priority. We welcome your comments and
> suggestions about how we can improve the support we provide to you. Please
> feel free to let my manager know what you think of the level of service
> provided. You can send feedback directly to my manager at:
> msdnmg@microsoft.com.
>
> ==================================================
> Get notification to my posts through email? Please refer to
> http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.
>
> Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
> where an initial response from the community or a Microsoft Support
> Engineer within 1 business day is acceptable. Please note that each follow
> up response may take approximately 2 business days as the support
> professional working with you may need further investigation to reach the
> most efficient resolution. The offering is not appropriate for situations
> that require urgent, real-time or phone-based interactions or complex
> project analysis and dump analysis issues. Issues of this nature are best
> handled working with a dedicated Microsoft Support Engineer by contacting
> Microsoft Customer Support Services (CSS) at
> http://support.microsoft.com/select/default.aspx?target=assistance&ln=en-us.
> ==================================================
> This posting is provided "AS IS" with no warranties, and confers no 
> rights.
>
date: Wed, 27 Aug 2008 12:08:12 -0500   author:   Alex Clark ail

Re: Graphics.DrawImage is very slow   
Hi, Alex,

Could you share how you solved the problem? I got into the same issue.

thanks,

bill

"Alex Clark" wrote:

> Hi Zhi-Xin,
> 
> It's a long story but I think I nailed most of the performance issues, it's 
> repainting much faster and smoother now, so the issue is solved.
> 
> Many thanks,
> Alex
> 
> 
> 
> "Zhi-Xin Ye [MSFT]"  wrote in message 
> news:5Y%23fwRBCJHA.1768@TK2MSFTNGHUB02.phx.gbl...
> > Dear Alex,
> >
> > How did you paint the container control and the custom control? If you
> > don't put the custom controls on the container control, do you still have
> > the performance problem?
> >
> > I'm looking forward to hearing from you.
> >
> > Sincerely,
> > Zhi-Xin Ye
> > Microsoft Managed Newsgroup Support Team
> >
> > Delighting our customers is our #1 priority. We welcome your comments and
> > suggestions about how we can improve the support we provide to you. Please
> > feel free to let my manager know what you think of the level of service
> > provided. You can send feedback directly to my manager at:
> > msdnmg@microsoft.com.
> >
> > ==================================================
> > Get notification to my posts through email? Please refer to
> > http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.
> >
> > Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
> > where an initial response from the community or a Microsoft Support
> > Engineer within 1 business day is acceptable. Please note that each follow
> > up response may take approximately 2 business days as the support
> > professional working with you may need further investigation to reach the
> > most efficient resolution. The offering is not appropriate for situations
> > that require urgent, real-time or phone-based interactions or complex
> > project analysis and dump analysis issues. Issues of this nature are best
> > handled working with a dedicated Microsoft Support Engineer by contacting
> > Microsoft Customer Support Services (CSS) at
> > http://support.microsoft.com/select/default.aspx?target=assistance&ln=en-us.
> > ==================================================
> > This posting is provided "AS IS" with no warranties, and confers no 
> > rights.
> > 
> 
> 
>
date: Wed, 3 Sep 2008 11:54:01 -0700   author:   bill

Google
 
Web ureader.com


    COPYRIGHT 2007, YARDI TECHNOLOGY LIMITED, ALL RIGHT RESERVE  |   contact us