This is about another problem we are having with threads...
Here is test app (_lot_ of simpler than previous one) which
GPF's with 5333 or just throws out randomly.
If you change _COLLECT_ATTHREADBEGIN to FALSE it will run longer, but
isn't this the case allways with GC... <g>
Interesting thing is that if WipeDynSpace is set to 0 it seems
to be failing faster, if it is 1 it seems to be running much
longer time... Usually with 5333's this is just opposite.
It will take something like 3-4 minutes to crash with WipeDynSpace
0 on my machine, but I strongly believe it will do that at some
point on all machines.
Please let me know what happens and be patient and watch it
doing it's stuff via DebugView. Or go take cup of coffee and
see what happens...
I would be happy also if somebody could point me if there is
problem with my code.
Download test: http://www.codeblock.fi/test/_app.ThreadMemTest.aef 7 kb
- Jari -
When I speak of a limit you are correct in that it seems tied to GC. IOWs
(and to answer Derik's question in another thread) if you stay away from
dynamic memory allocations you should be able create and work with as many
thread's as you like.
Also I can confirm that the limit was raised in VO 2.5 as Young mentions.
For me things go wonky around the 52 or 53 thread under VO 2.6
You can see for yourself. The following program is a VO implementation of
the famous dinning philosphers program. Basically you have N philosophers
sitting done to dinner at a round table. Each has a plate with food on it.
There is a single fork between each plate going around the table. To eat a
philospher must pick up the fork on either side of the plate for a period of
time. The problem is to code this without having the simulation deadlock!
This can happen if each philsopher picks up his right fork at the same time
for example. If every philopsher has a fork in his right hand then they are
all waiting on the person to his left to put down his fork and you get
deadlock.. Your task as a 2nd year CS student is to write the code such
that this deadlock cannot happen. Of course each philosopher is simulated
with its own thread.
Anyway here is a "proper" solution to this problem written in VO. The
program should run for every (i.e.; never deadlock). However, (on my
machine anyway) set the max treads to 52 or higher and it will blow up. On
VO 2.5b3 it would blow on a value of 31 or higher. Anything less then these
limits seems to run fine. [Hint: To really test that the solution is
working well you should slow the eating process down and reduce the number
of threads to a very small number (i.e.; 2 or 3) both of which will increase
the odds of a deadlock situation happending in a badly programmed solution]
Hopefully Brian can have a look at this problem and see what can be done
about fixing it. Also, while he is in there, it would be great if he could
remove any TLS (Thread Local Storage) being used to implement the GC. The
problem with TLS is that it makes the GC assume that the same thread that
allocate dynamic memory will deallocate/manipulaate it, etc.. This isn't
true in free threaded, thread pooling environments such as ASP under IIS,
where any thread can call into the VO component and do dynamic memory
allocations at any time. This is really making it hard to do mission
critical stuff with VO-based software under the likes of IIS (you basically
have to forego the GC to make it work....)
Rod
GLOBAL goCon AS Console
GLOBAL DIM ghForks[ MAX_NUM_PHILOSOPHERS ] AS PTR
FUNCTION Philosopher( dwPhilospherID AS DWORD ) AS DWORD PASCAL
LOCAL dwLeftFork, dwRightFork AS DWORD
LOCAL lHaveLeftFork, lHaveRightFork AS LOGIC
dwLeftFork := dwPhilospherID
dwRightFork := ((dwLeftFork + 1) % MAX_NUM_PHILOSOPHERS )
DO WHILE TRUE
Sleep(500 ) // Slow things down...
// Pick Up Left Fork
lHaveLeftFork := ( WaitForSingleObject( ghForks[ dwLeftFork + 1 ], 0 ) ==
0 )
IF lHaveLeftFork
goCon:WriteLine( "Philosopher " + NTRIM(dwPhilospherID ) + " picks up
Left fork" )
// Pick up Right Fork
lHaveRightFork := ( WaitForSingleObject( ghForks[ dwRightFork + 1], 0 )
== 0 )
IF lHaveRightFork
goCon:WriteLine( "Philosopher " + NTRIM(dwPhilospherID ) + " picks up
Right fork" )
// Eat for some random amount of time
goCon:WRiteLine( "Philopshper " + NTRIM( dwPhilospherID ) +" is eating
... .Mmmmmm (Burp!)" )
Sleep( INTEGER( RAND() * 1000 ) )
// Put Forks down
ReleaseMutex( ghForks[ dwLeftFork + 1 ] )
ReleaseMutex( ghForks[ dwRightFork + 1 ] )
goCon:WriteLine( "Philosopher " + NTRIM( dwPhilospherID ) + " put down
forks and is thinking ... Hmmmmmm" )
ELSE
ReleaseMutex( ghForks[ dwLeftFork + 1 ] )
goCon:WriteLine( "*** Philosopher " + NTRIM( dwPhilospherID ) + " could
not get both forks... try again later" )
ENDIF
ENDIF
ENDDO
RETURN 0
FUNCTION Start
LOCAL dwThreadID AS DWORD
LOCAL DIM ahThread[MAX_NUM_PHILOSOPHERS] AS PTR
LOCAL i AS DWORD
goCon := Console{}
goCon:Clear()
goCon:Title := "Dinning Philospher's Problem (Good)"
FOR i := 1 UPTO MAX_NUM_PHILOSOPHERS
ghForks[i] := CreateMutex( NULL_PTR, FALSE, NULL_PSZ )
NEXT i
FOR i := 1 UPTO MAX_NUM_PHILOSOPHERS
ahThread[ i ] := CreateThread(;
NULL_PTR, 0, ;
@Philosopher(),;
PTR(_CAST, i-1 ),;
0,;
@dwThreadID )
NEXT i
// Wait for all threads to finish
WaitForMultipleObjects(;
MAX_NUM_PHILOSOPHERS,; // nCount AS DWORD
@ahThread,; // lpHandles AS PTR
TRUE,; // bWaitAll AS LOGIC
INFINITE; // dwMilliseconds AS DWORD
)
// Clearn Up
FOR i := 1 UPTO MAX_NUM_PHILOSOPHERS
CloseHandle(ahThread[i])
CloseHandle( ghForks[i] )
NEXT i
RETURN
DEFINE MAX_NUM_PHILOSOPHERS := 51
snip[ Basically you have N philosophers sitting done to dinner at a round
table. ]
You have way to much time on your hands...
====
snip[ ... .Mmmmmm (Burp!)" ) ]
Nice comments.. <g>
Phil
---
"Rod da Silva" <RodDa...@NOSPAM.com> wrote in message
news:b2fbv6$rc8$1...@ngspool-d02.news.aol.com...
> When I speak of a limit you are correct in that it seems tied to GC. IOWs
> (and to answer Derik's question in another thread) if you stay away from
> dynamic memory allocations you should be able create and work with as many
> thread's as you like.
OK, I have also now noticed this 32 thread limit, allthought
I didn't had time to look at this sample.
Are you saying your sample should explain
this totally different problem we have, what sample in
this thread is all about.
In it we only have 3 threads running and evrything is cleaned up
before they are initiated again. And it blows up too...
Please take look at it, if you haven't?
>(you basically have to forego the GC to make it work....)<
This is exactly what we are doing...<g>
- Jari -
I crash almost imediately at 59 Ps on my 512MB Machine (W2k SP3).
When running (from the IDE ) with _58_, you can see in the taskman
that the app eats roughly 30-40k /sec of memory.
UNTIL the Memory reaches rather exactly the 95% Watermark of the
virtual Memory value.
Then the swallowing slows down and stops for me at 11260kb of 11852
kb. Then the app continues to run ad inifinitam.
Changing back to 59 the app crashes at some 30% used Memory of the
virtual Memory pool.
Karl
Ideal pure example! They (58) eat and eat... And not wanted one out (59).
Thank you.
And (m.b. mad) idea:
Number of concurrent threads (VO+GC) limited by MAXIMUM_WAIT_OBJECTS(=64).
minus 1 as always;
minus 1 for GC itself;
minus 1 for avoiding GC recursion (run&exit when called recursively);
minus 2-3 for output from within GC or something else.
If this is true, no chances to break limit with current GC realization.
Igor
Do you suggest that GC is running in separated thread ?
I have always hear the opposite !
Dirk
On Thu, 13 Feb 2003 15:40:34 +0200, "Igor Kaliniak" <rem_i...@gal.ukrpack.net>
wrote:
I think that VO is creating an array of threads, which are created with
CreateVOThreads. If this array is bigger then 64, then -->Crash !!
But if you create threads by CreateThread, then the threadid is not in this array,
so the thread is not stopped during GC. If this thread is using dyn-memory,
on that moment it is possible that the GC and the thread is using on the same
time the same dyn-memory ---> crash !!!
So, use CreateVOThread when using dyn-memory (max 56 in 2.6)
Otherwise, use CreateThread.
Dirk
On Thu, 13 Feb 2003 15:40:34 +0200, "Igor Kaliniak" <rem_i...@gal.ukrpack.net>
wrote:
> Rod,
We have only one multi-threaded app /*MSVC60+own VO-dll+cavort20 (VO20)*/.
Only 5-6 threads and our customer quite pleased with one crash/week. Of
course, we used CreateThread(). So, I have only theoretical interest at
least for now (we have some plans after we'll purchase VO27). I simply
suppose that GC should run in another thread (with new extra-threads-array)
when number of threads exceed (64-X). And, certainly, you're right.
Thanks,
Igor
"Dirk Herijgers" <di...@fujitron.be> wrote in message
news:tu9n4vcjp8496cnh3...@4ax.com...
FWIW, i sent the example to a friend with a DualProcessormachine and
1GB Memory - for him it works upto 59 and crashes with 60...
Karl
Interesting. And, yes, I also used ProcessViewer, and MemTurbo for "scrub
RAM" sometimes (simply as stress, and "Theatre Of Tragedy" in background :).
So, I think limit is 64-(1+1+1) and m.b. yet another 1 (for output?).
Igor
"Karl Faller" <10072...@compuserve.com> wrote in message
news:ijen4v02sjq62aq36...@4ax.com...
OK, we propably now had fact that VO 2.5 works with 31 and 2.6 with little bit more, but......
Can you confirm crash with both of them with the test app:
http://www.codeblock.fi/test/_app.ThreadMemTest.aef
This is important, since this has nothing to do with thread limits...
- Jari -
The app crash on my PC almost always.
Sometimes 400 threads, sometimes 100 threads.
I have changed program a little "psz2string" changed in "string2psz" in function
_DebOut32
Also, threads are running all together.
If thread are running 1 by 1 : it works without crash, but it is "sensitive" for
5333.
Dirk
On Fri, 14 Feb 2003 14:50:36 +0200, "- Jari -" <Jari.Sevon@codeblock_SPAMREMOVE_.fi>
wrote:
Karl
Yes, crash. But after I
- comment all debouts (never used and even don't know how, m.b. you tell
me...);
- comment AAdd( aObjects, oObject ) in threadProc_1() (i think needless and
dangerous);
- and add critical section,
this app worked:
1 pass - only w. player (Joe Cocker:);
2 pass - + stress;
3 pass - player + hard stress (every 10 secs).
Enough for me. And no errors.
Igor
P.S.
Someone would say: don't blame VO<g>
> Yes, crash. But after I
> - comment all debouts (never used and even don't know how, m.b. you tell
> me...);
Well you should...as they are the only way to monitor this app.
Go to www.sysinternals.com and download debugview. It is free
and great tool for it.
> - comment AAdd( aObjects, oObject ) in threadProc_1() (i think needless and
> dangerous);
No there is nothing wrong it. And it is needed in several places. It is
also fully supported in VO's runtime, if you don't use multithreading.
I have used it since days 1.0....
>- and add critical section,
Well, what can I say...if you do this you totally loose whole
purpose of this app.....
It for _simulating real world_ situation where two or more threads
are executing stuff and GC get's lot of things to do...
>Enough for me. And no errors.
Not for me...<g>
>Someone would say: don't blame VO<g>
I think this app clearly shows that in VO there is critical errors
in way GC handles multithreading environments.
I will send it to Brian!
- Jari -
Thanks for confiriming the problem.
Can you also give VO version where you tested it...?
TIA,
- Jari -
Thanks for explanation of debugview. I'll try it.
> > - comment AAdd( aObjects, oObject ) in threadProc_1() (i think needless
and
> > dangerous);
>
> No there is nothing wrong it. And it is needed in several places. It is
> also fully supported in VO's runtime, if you don't use multithreading.
> I have used it since days 1.0....
Well, but in this concrete case it really needless. And dangerous because of
memory (re-)allocating. Anyway explicit declaring or arraycreate() better
(see 'Avoid AADD()' topic in VO2.0-Help).
> >- and add critical section,
>
> Well, what can I say...if you do this you totally loose whole
> purpose of this app.....
No. I'll send you modified aef just now.
Igor
> Well, but in this concrete case it really needless.
No it is not. As purpose of this is show that there is problem
with VO's dynamic datatypes with multithreading.
> > >- and add critical section,
> >
> > Well, what can I say...if you do this you totally loose whole
> > purpose of this app.....
> No. I'll send you modified aef just now.
So you think that your modification doesn't change the purpose...????
We very well know that app works like this!
By defining those critical sections you are changing logic to synchronous
calls. Not in thread level. Of course all this stuff works if you don't mix
up GC, which was purpose. How you think you can write efficient threads if
you are writing them like this??? You loose whole purpose of threads...
Also you have taken out the call to Aadd, don't care if it is dangerous
it should work as it works outside of threads fine. Your versions memory
load is lot of less....BTW It might also fail, but because you have taken
the real "loader" it might take days...<g>
Also these ONLYEARLY pragmas don't have anything to do with real problem...?
So I think our question was not to try to find ways to around thew problem.
It simply was to confirm a bug?
There always is a way around....
- Jari -
Did you send your code to bugsh...@cavo.com? It looks like a good repro of the
problem to me.
--
Ginny
"- Jari -" <jari....@codeblock.fi> wrote in message
news:4e3abece.03021...@posting.google.com...
> > Well, but in this concrete case it really needless.
>
> No it is not. As purpose of this is show that there is problem
> with VO's dynamic datatypes with multithreading.
Okay, we have different purposes. My first goal is a stable application. And
yours one to find and prove a bug. A big area is waiting for you.<g>
> > > >- and add critical section,
> > >
> > > Well, what can I say...if you do this you totally loose whole
> > > purpose of this app.....
> > No. I'll send you modified aef just now.
>
> So you think that your modification doesn't change the purpose...????
Maybe not for this simplest app, but... yes, of course. In our case we have
3 protected (by critical section) parts in thread function == ~15% CPU time
for each trade. And other 85% unprotected...
> By defining those critical sections you are changing logic to synchronous
> calls. Not in thread level. Of course all this stuff works if you don't
mix
> up GC, which was purpose. How you think you can write efficient threads if
> you are writing them like this??? You loose whole purpose of threads...
... and what I loose? Only errors.
> Also you have taken out the call to Aadd, don't care if it is dangerous
> it should work as it works outside of threads fine. Your versions memory
> load is lot of less....BTW It might also fail, but because you have taken
> the real "loader" it might take days...<g>
This function (AAdd) may cause GPF w/o multithreading even.
So, you can find&prove yet another bug.<g>
> Also these ONLYEARLY pragmas don't have anything to do with real
problem...?
Indeed, you can comment it. W/o visual changes.
> So I think our question was not to try to find ways to around thew
problem.
> It simply was to confirm a bug?
And again, we have different goals.
> There always is a way around....
I hope... <g>
Igor
I am a pragmatist, just as you are. I try to go around problems whenever
possible. But I now think I have been too reluctant to complain about bugs -
even if I can work around them, and perhaps the VO product has suffered through
the years as a result. Just a thought...
--
Ginny
"Igor Kaliniak" <rem_i...@gal.ukrpack.net> wrote in message
news:b2tph9$1g9qs9$1...@ID-179710.news.dfncis.de...
I agree with you, as always. As to "complain about bugs", may be they at
least heard you. My own experience with CA ideally depicted by Franz
Kafka.<g> Just a reminiscence...
Igor
"Ginny Caughey" <ginny....@wasteworks.com> wrote in message
news:b2tt1i$1fn4d1$1...@ID-144704.news.dfncis.de...
I think they always heard me (at least I hope so <g>), but I'm afraid that
fixing bugs wasn't always the top priority at CA, so I got slack about reporting
them. Fortunately things are different now, and I'm very much looking forward to
2.7. Until then, I think it's very important for all of us to try to reproduce
bugs and report them so they can finally get fixed.
--
Ginny
"Igor Kaliniak" <rem_i...@gal.ukrpack.net> wrote in message
news:b2u3e4$1fpmpa$1...@ID-179710.news.dfncis.de...
Now my hopes live too. But I'm afraid most GC-problems will be adjourned
until VO27+. And you convince me, probably I review my buglists&workarounds.
Thank you,
Igor
/*sorry for 2 hours - champions league*/
"Ginny Caughey" <ginny....@wasteworks.com> wrote in message
news:b2u3o1$1ga0bp$1...@ID-144704.news.dfncis.de...
I think this went little bit chit-chat way...<g>
IMHO I think most important in tracing bugs is to produce
small reproducable sample. This is actually needed before
we can confirm a bug....
So yes... I will send it to "bugshunter".
I think Brian and rest are interested to see these kind of
samples....
- Jari -