Starting a Thread takes too long

  • Thread starter Thread starter Armin Zingler
  • Start date Start date
A

Armin Zingler

Hi,

surprise, it's me - again. Yeah, I know, many questions these days....

I'm doing work in background threads in order to keep the UI thread
responsive. I know that these threads consume 100% CPU time, but if
I set their priority to BelowNormal, the UI thread should still stay
responsive. The only thing that the UI thread does is starting other
threads. On an average, it starts about 10 threads per second. This
shouldn't put too much load on the UI thread.

However, at a certain point in time, the UI thread freezes. As I
know that the only thing the UI thread does is starting threads,
I logged the execution time of "starting a thread". The result
is surprising: It takes between 0.2 ms and 4 seconds!

Does anybody have an explanation why there is such a big deviation
between the execution times within a thread that has a higher priority
than all other threads?

Thanks again for reading! :-)
 
Am 14.01.2011 23:55, schrieb Armin Zingler:
I logged the execution time of "starting a thread". The result
is surprising: It takes between 0.2 ms and 4 seconds!

Conclusion (after more digging):

On a triple-core, the line

t.Start 't is System.Threading.Thread

executed in a thread with Priority=Normal while three
more threads with Priority=BelowNormal are running,
takes up to 4.489 seconds.

WOW!
 
Armin said:
Am 14.01.2011 23:55, schrieb Armin Zingler:

Conclusion (after more digging):

On a triple-core, the line

t.Start 't is System.Threading.Thread

executed in a thread with Priority=Normal while three
more threads with Priority=BelowNormal are running,
takes up to 4.489 seconds.

WOW!

Is it any quicker to use a thread from the existing .NET thread pool?
For example...

ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf MyFunc))
 
Armin Zingler wrote :
Hi,

surprise, it's me - again. Yeah, I know, many questions these days....

I'm doing work in background threads in order to keep the UI thread
responsive. I know that these threads consume 100% CPU time, but if
I set their priority to BelowNormal, the UI thread should still stay
responsive. The only thing that the UI thread does is starting other
threads. On an average, it starts about 10 threads per second. This
shouldn't put too much load on the UI thread.

However, at a certain point in time, the UI thread freezes. As I
know that the only thing the UI thread does is starting threads,
I logged the execution time of "starting a thread". The result
is surprising: It takes between 0.2 ms and 4 seconds!

Does anybody have an explanation why there is such a big deviation
between the execution times within a thread that has a higher priority
than all other threads?

Thanks again for reading! :-)

There is overhead in creating a thread. The system must allocate stack
space, etc, etc, etc.

I have to ask, it sounds like you are trying to do manually what the
TPL in .NET 4 will do for you automatically...

It generates a 3rd pool, so threads are started up front (and unlike
the normal thread pool, you can actually have more then one
threadpool). Implements workload stealing (if one thread get's through
it's work queue, it will steal work from one of it's siblings), etc.

Anyway, if these are short lived processes - in other words, do a unit
of work and then finish, then you might actually be better off using
the system thread pool.
 
Am 15.01.2011 05:47, schrieb Jason Keats:
Is it any quicker to use a thread from the existing .NET thread pool?
For example...

ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf MyFunc))

Jason,

I've never worked with thread pools, but now that you've mentioned them,
I'll have a look at them. Thanks for the hint!
 
Am 15.01.2011 07:42, schrieb Tom Shelton:
There is overhead in creating a thread. The system must allocate stack
space, etc, etc, etc.

I have to ask, it sounds like you are trying to do manually what the
TPL in .NET 4 will do for you automatically...

It generates a 3rd pool, so threads are started up front (and unlike
the normal thread pool, you can actually have more then one
threadpool). Implements workload stealing (if one thread get's through
it's work queue, it will steal work from one of it's siblings), etc.

Anyway, if these are short lived processes - in other words, do a unit
of work and then finish, then you might actually be better off using
the system thread pool.

Tom,

see my reply to Jason (Ihaven't used thread pools yet), and thanks for the
hint, too. Then I'll hopefully understand better what you wrote.


To give some background information: The current approach is not necessarily
the final approach. No problem as it's a leisure project. However I did
think about the (planned) behavior before.

In details, it's a ray-tracer that I wrote long ago and which means much to
me as I did everything on my own (the prior-internet times). It's a challenge
for me to develop it further without looking at all the free stuff (including
source code) available nowadays. Armin, back to the point!

In the old version, the result was computed line by line. There was a LineDone
event enabling me to update the display. One day I redesigned the code to make
use of multiple cores. For this purpose, I split the picture to be rendered into
rectangles, each processed in a thread. I start with Environment.ProcessorCount
threads. If one rectangle (and one thread) is finished, the next rectangle is
computed. Right, the "LineDone" event had to disappear, so did the preview.

These days I wanted my preview back, so I decided to handle the "RectangleDone"
event in the UI thread to update the display. The handler gets a 2D array of
color values and paints them on the displayed Bitmap. But as this additional painting
job took too much power from the UI thread, I've put it also into a new Thread
(with low priority again). One thing that could not be taken away from the UI
thread was "OnPaint" where the Bitmap was drawn. Again for performance reasons,
I decided to update the display not after each rectangle. Instead it's invalidated
Timer-based (intervals now changable by the user) which is sufficient for a preview.

Below the line, the UI thread consumes only 4% CPU time. As it has a higher
priority than all other threads, I was (and I am) pretty suprised about the
result's I've posted. If I'd use only ProcessorCount - 1 threads for computations.
the problem disappears (as expected) but it would be a waste of free ressources.

BTW, the next big thing I'm going to change is speeding up shadow computations.
With shadows disabled, computation takes 2.5 s, with shadows enabled gives 60 s.
Please don't blab out how it could be done if you know it! ;-)
 
Am 15.01.2011 05:47, schrieb Jason Keats:
Is it any quicker to use a thread from the existing .NET thread pool?
For example...

ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf MyFunc))

Done that. Yep, it's quicker! Guessing that the ThreadPool class internally starts the
Thread as I do, I wonder what's the difference to my own Thread.Start? Answer: It's the
Priority of the started Thread.

I've tried it: If I start the new thread with Priority=Normal, t.thread is much quicker
in the starting thread. This is crazy because it's the opposite that I wanted to achieve:

The starting thread should get more CPU time by setting the started thread to a lower
priority. But what happens is that the starting thread is thwarted by starting a lower
priority thread. Strange.

In other words:
t.Priority = ThreadPriority.Normal
t.Start() '*** quick (0.0002 to 0.1 s)

t.Priority = ThreadPriority.Lowest
t.Start() '*** slow (0.0002 to 4.5 s)

Conclusion: I will start my threads with priority=normal (optionally using the ThreadPool)
and set Priority=BelowNormal in the started thread's main function.
 
Armin,

Because that we are long time users of Net we sometimes miss something.

You are aware of the backgroundworker which seems even to be made for the
problem of keeping the UI repsonsive?

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

I was not aware of it until I saw it in the forums, much easier (and more
effective) than threading and threadpool

Although a new real better feature is around the corner.

Async

http://msdn.microsoft.com/en-us/vstudio/gg316360.aspx

Cor



"Armin Zingler" wrote in message
Hi,

surprise, it's me - again. Yeah, I know, many questions these days....

I'm doing work in background threads in order to keep the UI thread
responsive. I know that these threads consume 100% CPU time, but if
I set their priority to BelowNormal, the UI thread should still stay
responsive. The only thing that the UI thread does is starting other
threads. On an average, it starts about 10 threads per second. This
shouldn't put too much load on the UI thread.

However, at a certain point in time, the UI thread freezes. As I
know that the only thing the UI thread does is starting threads,
I logged the execution time of "starting a thread". The result
is surprising: It takes between 0.2 ms and 4 seconds!

Does anybody have an explanation why there is such a big deviation
between the execution times within a thread that has a higher priority
than all other threads?

Thanks again for reading! :-)
 
This is not a question, Armin! My app is up and running with just about 20%
to do (mostly tidying up). Thanks to all.
 
Am 16.01.2011 11:07, schrieb Cor:
Armin,

Because that we are long time users of Net we sometimes miss something.

You are aware of the backgroundworker which seems even to be made for the
problem of keeping the UI repsonsive?

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

I was not aware of it until I saw it in the forums, much easier (and more
effective) than threading and threadpool

Although a new real better feature is around the corner.

Async

http://msdn.microsoft.com/en-us/vstudio/gg316360.aspx

Cor

Hi Cor,

doesn't the BackgroundWorker make use of Threads like I do? It can not
invent something new. Even though I know the BackgroundWorker, I've
never used it because it does not really have advantages for me
versus the Thread object. A little like the "Application Framework"
that only hides things. I think a lower level problem can not be
solved in a higher level.

As I wrote in a previous reply, "I will start my threads with priority=normal
(optionally using the ThreadPool) and set Priority=BelowNormal in the started
thread's main function." I do so now and it works.

Anyway, thanks for your hint, too! (and sorry if I chose the wrong word lately!
didn't want to gamble with our little "friendship") :-)
 
Am 16.01.2011 11:33, schrieb StrandElectric:
This is not a question, Armin! My app is up and running with just about 20%
to do (mostly tidying up). Thanks to all.

Nice to hear. Well done! What's next? :-)
 
Cor pretended :
Armin,

Because that we are long time users of Net we sometimes miss something.

You are aware of the backgroundworker which seems even to be made for the
problem of keeping the UI repsonsive?

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

I was not aware of it until I saw it in the forums, much easier (and more
effective) than threading and threadpool

Although a new real better feature is around the corner.

Async

http://msdn.microsoft.com/en-us/vstudio/gg316360.aspx

Cor

Sytem.Threading.Tasks? That already exists in .NET 4.0 - it's the TPL.
What that looks like is that they are adding new api's to some of the
framework to take advantage of it :)

I did notice that VB.NET is finally to get iterator support... 'bout
time.

Armin - seriously, the old threading model is really deperecated, well
in the sense that windows forms are deprecated. Microsoft has said
that the TPL is now the prefered threading model for .NET. I'm not
sure I would spend a whole lot of time learning the old model - unless
your stuck at the 3.5 level.
 
Am 16.01.2011 16:34, schrieb Tom Shelton:
Armin - seriously, the old threading model is really deperecated, well
in the sense that windows forms are deprecated.

Windows forms are deprecated? Now that it is fully developed?
Old threading model? I thought FW 1.1 had the old model.
Microsoft has said
that the TPL is now the prefered threading model for .NET. I'm not
sure I would spend a whole lot of time learning the old model - unless
your stuck at the 3.5 level.

I have never heared of TPL before. You know, they have to sell.
I don't believe that these brand-new super-duper things get worse over time.
VS 2008 should do it's job at least for some years, so I don't intend
to buy a new version again.

Anyways, is there something wrong? Everything works now. I have no problem
with Windows forms also. :-)
 
Armin Zingler said:
Am 16.01.2011 11:33, schrieb StrandElectric:

Nice to hear. Well done! What's next? :-)

Since you insist(!)... Please SIMPLE answers to

1 Is 'Private' the same as 'Dim'? Are the words interchangeable?

2 Is scoping of variables the same as in vb6? ie if I dimension as
variable in a subroutine is it valid only for that subroutine; in a form
valid for the whole form?

3 Do I have to erase an array after use to release memory? Destroy does
not seem to work.

4 Do I have to erase (or destroy) variables after use in a sub (say at
the end) or is it automatic in a sub based declaration?

5 What is the significance of the word 'Protected' before some subs?

That should do for now!
 
Armin Zingler was thinking very hard :
Am 16.01.2011 16:34, schrieb Tom Shelton:

Windows forms are deprecated?

Well, in that it is not longer developed. It is completely in
maintenance mode. You should be using WPF now :) This >>>>might<<<<
become important actually in the next couple of years, if MS starts
supporting ARM as they say - and if the new gui and app modles rumored
for windows 8 turn out to be true.
Now that it is fully developed?
Old threading model? I thought FW 1.1 had the old model.

1.1 - 3.5 has the old model :) Threading has changed very little in
..NET since day one. The TPL or Thread Parallel Library was introduced
in v4. It is a lot easier to work with. It's still threading whith
the same concerns but has some great functionality (Parallel.For,
Parallel.ForEach, Parallel.Invoke, etc) that can help help unlock the
latent parallelism in your app :)

I have never heared of TPL before. You know, they have to sell.
I don't believe that these brand-new super-duper things get worse over time.
VS 2008 should do it's job at least for some years, so I don't intend
to buy a new version again.

Anyways, is there something wrong? Everything works now. I have no problem
with Windows forms also. :-)

Nothing wrong. Just making you aware :)
 
Am 16.01.2011 21:13, schrieb StrandElectric:
Since you insist(!)... Please SIMPLE answers to

1 Is 'Private' the same as 'Dim'? Are the words interchangeable?

I'm afraid, but the answer is: "It depends". Though, trying as short as
possible:

For example, if you have two Forms in your project, you can not access the
'Private' variables of one Form from the other Form, i.e. the access level
is private. Access modifieres are 'Private', 'Public', 'Friend', 'Protected',
'Protected Friend'.

'Dim' is the actual declaration statement, but it can be omitted if you write
the access modifier. Thus, at Form level, the following lines are equal:

Private i As Integer
Dim i As Integer
Private Dim i As integer 'If you enter this, VB even removes the 'Dim'

If you write 'Dim' without an access modifier, the variable gets a default
access level. It depends on where the variable is declared. At Form level,
the default level is Private. In a Structure, the default level is Public.

With local variables only 'Dim' can be used.

2 Is scoping of variables the same as in vb6?

The meaning of the word "scope" is the same, but the scopes are not the same.
For example, there is no "block scope" in VB6:

do
dim i as integer
loop

Variable i is a local variable like those declared outside the loop, but i
is only accessible within the Loop.
ie if I dimension as
variable in a subroutine is it valid only for that subroutine; in a form
valid for the whole form?

Right.

Definition from the manual (maybe for later):

http://msdn.microsoft.com/en-us/library/1t0wsc67(VS.90).aspx

3 Do I have to erase an array after use to release memory?

Only if it, otherwise, would consume a tremendous amount of memory for a longer time
than necessary.
Destroy does not seem to work.

Memory is not released immediatelly. It's released whenever required
and/or there's the time to do it. (This is how the .Net Framework's
memory management works. It's called "garbage collection")

Again for later reference:
http://msdn.microsoft.com/en-us/library/f144e03t(VS.90).aspx
4 Do I have to erase (or destroy) variables after use in a sub (say at
the end) or is it automatic in a sub based declaration?

Assuming local variables: Straight before "End Sub" you don't have to
care about them because they die anyway.
I'm curious: How would you erase a variable?
5 What is the significance of the word 'Protected' before some subs?

see #1. I can't explain yet because some basics are missing. For completeness:
Only inherited classes can access protected members. (You remember
the 'Inherits' keyword explained yesterday? Your Form inherits all features
from the predefined Form class. Therefore, the code in your Form is able
to access all 'Protected' members of the predefined Form class. Other classes
that do not inherit from the Form class, can not access the Protected members
of the Form class.)
 
Armin Zingler said:
Am 16.01.2011 21:13, schrieb StrandElectric:

I'm afraid, but the answer is: "It depends". Though, trying as short as
possible:
.... (SNIP)

I'll print this out and try to work through it!
 
Am 16.01.2011 22:02, schrieb Tom Shelton:
Armin Zingler was thinking very hard :

Well, in that it is not longer developed. It is completely in
maintenance mode. You should be using WPF now :) This >>>>might<<<<
become important actually in the next couple of years, if MS starts
supporting ARM as they say - and if the new gui and app modles rumored
for windows 8 turn out to be true.


1.1 - 3.5 has the old model :) Threading has changed very little in
..NET since day one. The TPL or Thread Parallel Library was introduced
in v4. It is a lot easier to work with. It's still threading whith
the same concerns but has some great functionality (Parallel.For,
Parallel.ForEach, Parallel.Invoke, etc) that can help help unlock the
latent parallelism in your app :)


Nothing wrong. Just making you aware :)

Thanks for this bunch of information!

Well, maybe I dropped out of MSFT target group. Many things don't reach me
anymore. This was different in the past. To me it seems "the manufacturer"
has a communication problem. They may invent whatever they consider
appropriate, but, no, thanks, I'm saturated. I'll keep my eyes
and ears open, but for now I consider many things nice-to-have but not
(yet) a reason to upgrade again. (in opposite to upgrading from 1.1 to
2.0/3.5 which was a reasonable step)
 
Back
Top