473,785 Members | 2,777 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

How expensive is brush creation?

I am doing quite a bit of custom painting and it means I have to
create a lot of brushes (think one for every file system object in a
directory) per paint. How expensive is this? Should I find a way to
create the brushes once, store them in an member variable, and use
them when I need them? Or is creating brushes a throw-away process
that doesn't take a lot of work?

Thanks for the info.

Tom P.
Aug 5 '08
31 3417
On Aug 5, 1:41*pm, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
wrote:
On Tue, 05 Aug 2008 11:23:04 -0700, Tom P. <padilla.he...@ gmail.comwrote:
[...]
What's the speed difference when you measure your two proposed *
implementations ? *What performance problem are you trying to solve?
[...]
Nothing I've measured but the effort of redesigning my framework to
accommodate static brushes is no small feat.

All the more reason to not do that unless you know for sure you have to.
I am writing a file
manager and I custom paint each listview subitem (using
OnDrawSubItem). I allow custom colors and lineargradient brushes for
each subitem (name, size, and date). I have taken count and I'm
creating over 1000 brushes just to pull up a directory listing of the
root of my dev PC.

1000 brushes? *To display just one directory?

All due respect, I doubt the human brain is capable of comprehending a UI*
presentation with that much variety in it.
Now I'm thinking about adding a color option for
Directories vs. Files (and maybe even readonly etc.) and so I'm forced
to wonder if the painting could get expensive.

Well, it _could_. *Especially if just one directory causes you to create *
1000 different brushes. *But as long as things are performing adequately, *
I don't think you should worry about it. *Even if you do run into *
performance issues, you might reconsider whether it's really necessary to*
use so many different brushes. *That is probably a better solution than*
trying to cache thousands of brushes (as Ignacio points out, the unmanaged *
resource in a brush is relatively scarce and so shouldn't be held on to *
for long periods of time, especially in such large numbers).

Pete
I'm sorry, I must have misspoke. I don't create a thousand different
brushes, I only create about 6 or 9 different brushes... hundreds of
times. Each Item has a NameBrush, a SizeBrush, and a DateBrush for
each circumstance they could be in (unselected, selected, mouseover,
etc.). But they are created over and over and over again for each item
in the filelist. For example, everytime I pass the mouse pointer over
an item I must create three of the unselected brushes to "clear" the
old items look, then I must create three new brushes to paint the new
items mouseover look. That's 6 brushes just to move the mouse from one
item to the next.

Tom P.
Aug 5 '08 #11
On Tue, 05 Aug 2008 11:27:45 -0700, Tom P. <pa***********@ gmail.comwrote:
I appreciate the help but I've got custom colors and lineargradient
brushes just littering this thing. As well as mouseover brushes and
now I'm kicking around the idea of Directory vs. File brushes and
maybe System or ReadOnly brushes. I've got to find a way to make them
permanent but I've also got the issue of creating the brush within the
correct bounds (what if the user changes the size of the column, I
need to resize the brush accordingly).
One possible "in-between" solution you might consider is to keep just one
static brush instance, updated as necessary. Maintain some sort of
description of the brush so you know what's actually in that brush (which
you'd have to do with any static brush caching anyway).

If an item has multiple elements, each that might be drawn with its own
brush, you could increase the number of static brushes to the maximum
number of brushes any one element might use.

That way, if several items with the same visual appearance are drawn in
immediate succession, you can just use the brush(es) from the last drawing
operation rather than recreating the brushes anew each time. At the same
time, it avoids you having to implement a full-fledged brush caching
system (the code for which would be much more complicated, never mind the
system resource cost of keeping thousands of brushes or more around
full-time).

Pete
Aug 5 '08 #12
On 5 août, 20:27, "Peter Duniho" <NpOeStPe...@nn owslpianmk.comw rote:
On Tue, 05 Aug 2008 11:12:01 -0700, <michel.desang. ..@gmail.comwro te:
It is VERY expensive, not because of the brushes themselves, but
because you're feeding the Garbage Collector with all those brushes on
every Paint event.

The GC design is optimized to handle repeated allocation and discarding of *
short-lived objects. *GC is not an issue here at all, though disposal of *
brushes _theoretically_ might be. *I doubt most code would see any issue.
You'd be better off using the system Brushes, which are static. Use:
Brushes.Black

Yes, very true. *If one of the pre-defined brushes is adequate, using that *
is much better than creating and disposing one.

Pete
Still, this :
for (int i = 0; i < 1000000; i++)
{
Brush b = new SolidBrush(Colo r.Blue);
}
...in release mode takes something like 160 Mb of RAM and lasts
approximately one second. Even optimized, it has to put some pressure
on the GC. But again, when reading Tom's description I incorrectly
assumed "lots" meant "millions of brushes" (I'm working on a rather
complex real-time video thingy atm where every cycle saved is
crucial). You're absolutely right it amounts to nothing in Tom's case.

Michel
Aug 5 '08 #13
On Aug 5, 2:27 pm, "Tom P." <padilla.he...@ gmail.comwrote:
On Aug 5, 1:12 pm, michel.desang.. .@gmail.com wrote:
On 5 août, 19:54, "Tom P." <padilla.he...@ gmail.comwrote:
I am doing quite a bit of custom painting and it means I have to
create a lot of brushes (think one for every file system object in a
directory) per paint. How expensive is this? Should I find a way to
create the brushes once, store them in an member variable, and use
them when I need them? Or is creating brushes a throw-away process
that doesn't take a lot of work?
Thanks for the info.
Tom P.
It is VERY expensive, not because of the brushes themselves, but
because you're feeding the Garbage Collector with all those brushes on
every Paint event.
You'd be better off using the system Brushes, which are static. Use:
Brushes.Black
instead of:
Brush b = new SolidBrush(Colo r.Black)
If you frequently use the same colors that are outside the 216
predefined ones, you can do this (in a static class, for instance):
private static Brush orangeyBrush;
public static Brush Orangey
{
get
{
if (orangeyBrush == null)
return (orangeyBrush = new
SolidBrush(Colo r.FromArgb(223, 156,0)));
}
}
This mimics what the framework does internally (lazy initialization) .
Michel

I appreciate the help but I've got custom colors and lineargradient
brushes just littering this thing. As well as mouseover brushes and
now I'm kicking around the idea of Directory vs. File brushes and
maybe System or ReadOnly brushes. I've got to find a way to make them
permanent but I've also got the issue of creating the brush within the
correct bounds (what if the user changes the size of the column, I
need to resize the brush accordingly).

I'm gonna have to think this one through. Thanks.

Tom P.

Ok, that's fine
but why you need to create XXXXX number of DIFFERENT brushes? I would
assume that you need one per type at most.
Aug 5 '08 #14
On Tue, 05 Aug 2008 11:56:24 -0700, Ignacio Machin ( .NET/ C# MVP )
<ig************ @gmail.comwrote :
but why you need to create XXXXX number of DIFFERENT brushes? I would
assume that you need one per type at most.
I assume it's because he's doing the drawing in a handler that gets called
once per item, so each item has no knowledge of other items that got drawn.

If one was doing the whole UI at once in a single Paint handler, it would
be easy to batch up all the brushes (or even to sort the drawing by brush,
which would be the best performance). But if he draws 1000 items, and is
creating and disposing the brushes in the item-drawing handler (which is
not fundamentally a bad design at all), then that's 1000 different brushes.

I didn't pick up on that initially, but based on his other replies, that
seems like what's going on.

Pete
Aug 5 '08 #15
On Tue, 05 Aug 2008 11:51:19 -0700, <mi************ **@gmail.comwro te:
Still, this :
for (int i = 0; i < 1000000; i++)
{
Brush b = new SolidBrush(Colo r.Blue);
}
...in release mode takes something like 160 Mb of RAM and lasts
approximately one second.
Well, that's only about 170 bytes per object. Doesn't sound like a big
deal to me. But, what happens when you fix the code so that it is
correctly disposing each brush? At least some of the memory cost is
coming from the unmanaged resource being allocated. And more importantly,
do you have any evidence at all that the GC itself is spending a lot of
time working on dealing with the allocations?
Even optimized, it has to put some pressure
on the GC. But again, when reading Tom's description I incorrectly
assumed "lots" meant "millions of brushes" (I'm working on a rather
complex real-time video thingy atm where every cycle saved is
crucial). You're absolutely right it amounts to nothing in Tom's case.
Even a million short-lived objects shouldn't really be a big deal. Even
if you allocate 100,000 objects in quick succession, each allocation
involves just a single update of a pointer, just as it always does.
Assuming the objects are no longer reachable the next time garbage
collection happens, there's no significant overhead to the collection
process caused by those objects.

If anything, keeping the objects cached statically could increase GC
overhead, because that adds to the number of objects the GC needs to
examine as it traverses the graph of reachable objects.

The real issue here is the unmanaged resources, not the garbage collection.

Pete
Aug 5 '08 #16
On Tue, 05 Aug 2008 11:49:44 -0700, Tom P. <pa***********@ gmail.comwrote:
I'm sorry, I must have misspoke. I don't create a thousand different
brushes, I only create about 6 or 9 different brushes... hundreds of
times. [...]
Right, I finally figured that out. :) I might just not have been reading
carefully enough the first time.

I don't think that caching a dozen or so brushes long-term should be an
issue, if you decide that's a viable design change. That's not enough to
cause any serious problems with resource consumption, I think.

Still, I wouldn't bother until if and when you find an actual performance
problem. Just remember to dispose any brushes you create, and you'll
probably be fine.

Pete
Aug 5 '08 #17
On Aug 5, 2:09*pm, "Peter Duniho" <NpOeStPe...@nn owslpianmk.com>
wrote:
On Tue, 05 Aug 2008 11:49:44 -0700, Tom P. <padilla.he...@ gmail.comwrote:
I'm sorry, I must have misspoke. I don't create a thousand different
brushes, I only create about 6 or 9 different brushes... hundreds of
times. [...]

Right, I finally figured that out. *:) *I might just not have been reading *
carefully enough the first time.

I don't think that caching a dozen or so brushes long-term should be an *
issue, if you decide that's a viable design change. *That's not enough to *
cause any serious problems with resource consumption, I think.

Still, I wouldn't bother until if and when you find an actual performance*
problem. *Just remember to dispose any brushes you create, and you'll *
probably be fine.

Pete
Thanks for the help guys. Pete is right, I should have done this
sooner but I was stuck thinking about something from one direction.
Thanks to Michel for giving me the kick in the head to realize how
simple a short test could be.

Using the following code...

for (long loop = 0; loop 1000000000;loop ++ )
{
Rectangle tempRect = new Rectangle(0,0,1 00, 18);

tempBrush = new LinearGradientB rush(tempRect,
Color.Blue, Color.Red, 0.01F) ;
tempBrush = null;
}

...takes 0.00013344 secs. (timed using the hardware HiRes API timer).

I think I can spare 0.00013344 secs.

Sorry Pete.

Tom P.
Aug 5 '08 #18
On 5 août, 21:06, "Peter Duniho" <NpOeStPe...@nn owslpianmk.comw rote:
On Tue, 05 Aug 2008 11:51:19 -0700, <michel.desang. ..@gmail.comwro te:
Still, this :
for (int i = 0; i < 1000000; i++)
{
* *Brush b = new SolidBrush(Colo r.Blue);
}
...in release mode takes something like 160 Mb of RAM and lasts
approximately one second.

Well, that's only about 170 bytes per object. *Doesn't sound like a big*
deal to me. *But, what happens when you fix the code so that it is *
correctly disposing each brush? *At least some of the memory cost is *
coming from the unmanaged resource being allocated. *And more importantly, *
do you have any evidence at all that the GC itself is spending a lot of *
time working on dealing with the allocations?
Even optimized, it has to put some pressure
on the GC. But again, when reading Tom's description I incorrectly
assumed "lots" meant "millions of brushes" (I'm working on a rather
complex real-time video thingy atm where every cycle saved is
crucial). You're absolutely right it amounts to nothing in Tom's case.

Even a million short-lived objects shouldn't really be a big deal. *Even *
if you allocate 100,000 objects in quick succession, each allocation *
involves just a single update of a pointer, just as it always does. *
Assuming the objects are no longer reachable the next time garbage *
collection happens, there's no significant overhead to the collection *
process caused by those objects.

If anything, keeping the objects cached statically could increase GC *
overhead, because that adds to the number of objects the GC needs to *
examine as it traverses the graph of reachable objects.

The real issue here is the unmanaged resources, not the garbage collection.

Pete
The only evidence I have is "Effective C#" by Bill Wagner, in which
chapter 16, "Minimize Garbage", deals with the handling of brushes in
paint handlers. It's a coincidence, I read it yesterday, so I thought
I'd jump in. Extracts :

"No matter how you look at it, allocating and destroying a heap-based
object takes more processor time than not allocating and not
destroying a heap-based object. [...] One very common bad practice is
to allocate GDI objects in a Windows Paint handler [...] The static
property Brushes.Black illustrates another technique that you should
use to avoid repeatedly allocating similar objects. Create static
member variables for commonly used instances of the reference types
you need. [...] Every time you need to draw something in your window
using the color Black, you need a black brush. you create and destroy
a huge number of black brushes during the course of a program. [...]
The garbage collector does an efficient job of managing the memory
that your application uses. But remember that creating and destroying
heap objects still takes time. Avoid creating excessive objects; don't
create what you don't need. Also avoid creating multiple objects of
reference types in local functions. Instead, consider promoting local
variables to member variables, or create static objects of the most
common instances of your types."

The first sentence seems to apply quite nicely here.

Oh, and Brush and SolidBrush both implement IDisposable and inherit
from MarshalByRef. So, let me disagree completely with you on that GC
matter...

Michel
Aug 5 '08 #19
On Tue, 05 Aug 2008 12:39:59 -0700, <mi************ **@gmail.comwro te:
The only evidence I have is "Effective C#" by Bill Wagner, in which
chapter 16, "Minimize Garbage", deals with the handling of brushes in
paint handlers.
Well, I don't know anything about that book. But you should be careful
about believing everything you read, as well as about what you apply it to.

It's trivially true (and thus uninteresting) that it's faster to not do
something than to do it. But that doesn't mean that the act of doing it
is a significant cost that warrants complicating the code just so you can
avoid doing it.
[...]
Oh, and Brush and SolidBrush both implement IDisposable and inherit
from MarshalByRef. So, let me disagree completely with you on that GC
matter...
I have no idea what you mean. Even if I hadn't specifically pointed out
that the object needs to be disposed (which I in fact did), what's that
got to do with whether or not the memory management overhead is
significant? What's your point?

Pete
Aug 5 '08 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2355
by: Chris Lacey | last post by:
Hi, I'm currently writing a scheduling service which starts a number DotNet executables, each within a new AppDomain, every ten seconds. The guts of the code is as follows: // For each executable in the list of tasks for (int i = 0; i < this.processTasks.Length; i++) {
1
4865
by: Rene | last post by:
I would like to get a reference to a Brush using the color name of the brush. For example, right now if I want a brush with a certain color, I would hard code something like Brushes.PeachPuff, this will get me a PeachPuff brush, but what if my brush depended on a string passed by the user? If all I had was a string with the name "PeachPuff" how can I create Brushes.PeachPuff using the string value? Thank you.
2
43463
by: boxim | last post by:
having a moment, cant you just Brush br = new Brush(Color.Black);??? saying you cant cos it's an abstract class need to get to a brush from a color tia sam martin
5
2286
by: Dennis | last post by:
When I instantiate a Brush resource such as a solidbrush, do I need to dispose the resource when I'm finished or will it automatically be disposed when the function/sub it's used in ends? Thank you for any replies. -- Dennis in Houston
1
3861
by: =?Utf-8?B?UEtsZW1t?= | last post by:
how to serialize a brush object with the XmlSerializer without knowing the brush type?
2
1539
by: Johnny J. | last post by:
I've got an inherited control where I want the user to be able to specify a color property. Using that color, I'm drawing a line private m_UserDefinedColor as Color ..... Dim g as Graphics=this.CreateGraphics Dim myPen as Pen = new Pen(m_UserDefinedColor) g.DrawLine(myPen, X1, Y, X2 - 1, Y)
0
1282
by: steve | last post by:
When drawing with a hatch brush with a statement such as myGraphics.FillPolygon(hatchBrush, polygon.vertices); the hatch brush is always oriented in the same direction. Is there a way of rotating the brush so that I can give it a different orientation for each polygon? I.e. if it was a triangle and it was drawn upright then the brush would appear as normal but if the triangle was drawn upside down the hatch brush pattern would...
0
9645
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9480
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10151
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
7499
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6740
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5381
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5511
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3647
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2879
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.