Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

REAL8 bug?

31 views
Skip to first unread message

Olli Kekäläinen

unread,
Jan 30, 2003, 11:48:55 AM1/30/03
to
Hi all

Have anybody else noticed this kind of inaccuracy with REAL8s?
How can I overcome this?

Olli


FUNCTION test()

LOCAL r8DecPortion AS REAL8
LOCAL r8Value AS REAL8
LOCAL dwDecimals AS DWORD


r8Value := 0.1234
r8DecPortion := (r8Value * 10000) % 10000 // -> 1234.00
r8DecPortion %= 1 // -> 0.00 - AS EXPECTED

? r8DecPortion


r8Value := 123456.1234
r8Value %= 1 // -> 0.1234 - % seems to mess REAL8 up

r8DecPortion := (r8Value * 10000) % 10000 // -> 1234.00
r8DecPortion %= 1 // -> 1.00 - SHOULD IT STILL BE 0.00

? r8DecPortion

sleep(4000)

Malcolm Gray

unread,
Jan 30, 2003, 12:43:46 PM1/30/03
to
Olli Kekäläinen wrote:
> Hi all
>
> Have anybody else noticed this kind of inaccuracy with REAL8s?
> How can I overcome this?
Don't use real8 or float

using Str(r8DecPortion,20,15) I get
0.0000000000
r8value=123456.1234000000000
r8Value * 10000=1233.999999967636500
0.999999967636541

Which is pretty much expected as floating point numbers
are an approximation.

Although it might have expected a few more digits of accuracy.


OK

unread,
Jan 31, 2003, 1:12:25 AM1/31/03
to
Hi

Thanks for your answer.I am aware of the inaccurary of REAL8 and I can
nearly live with it. There is some times needs to handle creater digits than
DWORDs.

But if the result of r8value % 1 is sometimes 1 - that's unbearable! It's is
not admissible inaccuracy - it is a bug!


Olli

BTW. I'm still using 2.5b3. Could someone test my original source with 2.6.
Just making sure that the bug is still there.

Arne Ortlinghaus

unread,
Jan 31, 2003, 2:25:18 AM1/31/03
to
Hello Olli,

these are not really bugs.
You have similar problems in nearly every programming language.

You should not use the operators Mod and Div together with float numbers
(float as a generic name for Real4, Real8...). Mod and Div are defined for
Integer operations. When leaving the necessary transformations to the
compiler you are are never shure which results you will have.

You should always use a rounding operation before doing any truncating like
Mod and Div. Just an example:
Maybe you have a float f which contains a value nearly to 1 and you want to
have the part before the decimal point:
f = 1.0000000000000001 -> f %1 will give probably 1
f = 0.9999999999999999 -> f % 1 will give probably 0.
Although for your application f would be seen as 1.000 or 1.00 or 1.0000,
the runtime can not know what your wanted precision really is.

In the SDT 2/2002 I wrote an article about these problems with some code for
safe rounding.

Arne


Geoff Schaller

unread,
Jan 31, 2003, 3:11:47 AM1/31/03
to
No, this is not a bug - please stop insisting it is.
It is simply your misunderstanding of the nature of floating point numbers
represented by a binary system. For example, 0.5 just cannot be represented
exactly in binary. There must always be some error. Malcolm gives you one
way around and there are others.

In any event you should NOT be using REAL8. It is there as a compatibility
data type only. Use floats. There is also less overhead with a float because
internally, VO must convert REALs to floats to do any math.

Geoff

"OK" <O...@NOSrhoy.pp.fi> wrote in message
news:Xns931453EFA8...@192.89.123.233...

Olli Kekäläinen

unread,
Jan 31, 2003, 3:56:55 AM1/31/03
to
Hi Geoff

> No, this is not a bug - please stop insisting it is.
> It is simply your misunderstanding of the nature of floating point
> numbers represented by a binary system. For example, 0.5 just cannot be
> represented exactly in binary. There must always be some error. Malcolm
> gives you one way around and there are others.

I do know that 0.5 cannot be represented exactly in binary. But If r8Value %
1 (or fValue % 1) can be in some cases 1, so be it. I will stop
insisting....

>
> In any event you should NOT be using REAL8. It is there as a
> compatibility data type only. Use floats. There is also less overhead
> with a float because internally, VO must convert REALs to floats to do
> any math.

However the use of FLOATs instead of REALs does not solve the problem.
I was using REALs in that belief that FLOAT is dynamic datatype and REAL is
not (am I correct). I was intending to get rid of GC (at least as much as
possible). But if, as you said, VO internally converts REALs to FLOATs, can
it be possible at all?


Olli

Malcolm Gray

unread,
Jan 31, 2003, 7:30:07 AM1/31/03
to
Olli Kekäläinen wrote:
> Hi Geoff
>
>> No, this is not a bug - please stop insisting it is.
>> It is simply your misunderstanding of the nature of floating point
>> numbers represented by a binary system. For example, 0.5 just cannot
>> be represented exactly in binary. There must always be some error.
>> Malcolm gives you one way around and there are others.
>
> I do know that 0.5 cannot be represented exactly in binary. But If
> r8Value % 1 (or fValue % 1) can be in some cases 1, so be it. I will
> stop insisting....

But it isn't 1.0 exactly it is a number smaller than 1 that when rounded
for display displays as 1.0
e.g. 0.999999999999 % 1.0 should be 0.999999999999
but is likely to render as 1.0000 (say)

As it happens 0.5 can be represented exactly, (0.1 in binary or 1x2^-1)
but 0.1 cannot.


Ginny Caughey

unread,
Jan 31, 2003, 7:56:30 AM1/31/03
to
Olli,

I think that if you want to avoid the GC, you should use a langauge like C that
doesn't have one. Seriously. It's possible to avoid using the VO GC in very
small sections of code, but the VO language is designed to be used with a GC.
--
Ginny


"Olli Kekäläinen" <O...@NOSrhoy.pp.fi> wrote in message
news:Xns93146FD468...@192.89.123.233...

Olli Kekäläinen

unread,
Jan 31, 2003, 8:22:36 AM1/31/03
to
Malcolm,

Blind me! Thanks for your patience. In my original example the inaccuracy
took place on second line. Confusion happened because did not notice it.

r8Value := 123456.1234
r8Value %= 1 // -> 0.1234 - !!! This is actually 0.1233999999999
and will lead further difficulties later

r8DecPortion := (r8Value * 10000) % 10000 // -> 1234.00 //ACTUALLY
1233.9999999999
r8DecPortion %= 1 // -> 1.00 - ACTUALLY 0.999999999999


Fortunately I solved my problem with another approach. That is, I was
constructing a substitute function for the str() which, instead of returning
a VO string, writes the result to the memory buffer allocated in advance. It
is now working properly.


Olli

Olli Kekäläinen

unread,
Jan 31, 2003, 9:00:00 AM1/31/03
to
Ginny

Yeah. I have couple of times seriously considered moving to C++. But (this
but is big one!) I am extremely fond of VO's language, especially it's
syntax. And C++ syntax looks like "crap of fly" (as we in Finland might put
it) <g>.

But seriously. Question about avoiding the GC is very interesting. Is it
really so that you cannot write such code with VO which would keep GC
inactive. If you don't use any dynamic data types (incuding strings,
objects, arrays etc.), why should GC activate at all? As you may noticed in
coreLite libary, I have done lot of work with solutions which tend to avoid
the use of VO's dynamic data types. Are you saying that this work is waste
of time on a way to the GC free world <g>.

It would be interesting to know the situations where the GC kics in. Which
are they if we managed to produce a code which does not include VO's dynamic
data types?


Olli


"Ginny Caughey" <ginny....@wasteworks.com> wrote in
news:b1drn6$11plt3$1...@ID-144704.news.dfncis.de:

FDW

unread,
Jan 31, 2003, 9:06:10 AM1/31/03
to
Olli,

You can register some functions to monitor the GC activation and

de-activation.

_RegCollNotifyStart(@MyGCStartMonitor(),TRUE)

_RegCollNotifyEnd(@MyGCEndMonitor(),TRUE)

Frans

"Olli Kekäläinen" <O...@NOSrhoy.pp.fi> wrote in message

news:Xns9314A338A2...@192.89.123.233...

Olli Kekäläinen

unread,
Jan 31, 2003, 9:26:15 AM1/31/03
to
Frans,

Thanks! I will try the monitoring right a way.

Olli


Ginny Caughey

unread,
Jan 31, 2003, 10:05:52 AM1/31/03
to
Hi Olli,

> Yeah. I have couple of times seriously considered moving to C++. But (this
> but is big one!) I am extremely fond of VO's language, especially it's
> syntax. And C++ syntax looks like "crap of fly" (as we in Finland might put
> it) <g>.

I definitely agree!

> But seriously. Question about avoiding the GC is very interesting. Is it
> really so that you cannot write such code with VO which would keep GC
> inactive. If you don't use any dynamic data types (incuding strings,
> objects, arrays etc.), why should GC activate at all? As you may noticed in
> coreLite libary, I have done lot of work with solutions which tend to avoid
> the use of VO's dynamic data types. Are you saying that this work is waste
> of time on a way to the GC free world <g>.

Not at all! I think it's great. I just know from trying to write multithreaded
code prior to VO 2.5 how hard it is to completely avoid the GC. That was the
time I started to think seriously about C++ myself. <g>

> It would be interesting to know the situations where the GC kics in. Which
> are they if we managed to produce a code which does not include VO's dynamic
> data types?

The GC *shouldn't* kick in at all if we completely avoid anything that uses
dynamic data types. The problem is knowing sometimes when we're doing it - which
functions might use dynamically allocated memory under the covers, etc. The
whole runtime (or anyway most of it) was written with the assumption that the GC
would be available. I would love to see all the functions documented in this
fashion - warning us which ones might trigger GC action - but I suspect it would
be a lot of work for somebody to do.

Ginny


Ginny Caughey

unread,
Jan 31, 2003, 10:08:11 AM1/31/03
to
Frans,

Do these functions tell you when memory is actually moved around or also just
when dynamic memory is allocated but there was enough room so no GC action was
needed *this* time? My concern was always that I would miss something that
wouldn't trigger GC action for me on my machine in my office but that might at a
customer site.

--
Ginny


"FDW" <fdewit_...@planet.nl> wrote in message
news:b1e0m9$6qr$1...@reader08.wxs.nl...

Greg Garza

unread,
Jan 31, 2003, 10:22:48 AM1/31/03
to
Geoff,

> For example, 0.5 just cannot be represented exactly in binary.

In Standard Binary Exponential Notation, a 16 Bit representation of 0.5
would be:

0000000100000000

This is an exact representation.

Greg

Igor Kaliniak

unread,
Jan 31, 2003, 10:48:59 AM1/31/03
to
Olli

> I was using REALs in that belief that FLOAT is dynamic datatype and REAL
is
> not (am I correct). I was intending to get rid of GC (at least as much as
> possible). But if, as you said, VO internally converts REALs to FLOATs,
can
> it be possible at all?

As Ginny said, in pure VO, GC is 'pre-supposed' (not sure, is this right
word, m.b. 'inevitable':). Even
func test(k as dword) as dword pascal
return k + 1
is realized using kid stack etc.

But (Geoff!) REAL8+REAL8 calulated w/o converting to FLOATs (asm fadd for
real8 and faddp for float values).


Olli Kekäläinen

unread,
Jan 31, 2003, 11:04:21 AM1/31/03
to
Hi Ginny


> The GC *shouldn't* kick in at all if we completely avoid anything that
> uses dynamic data types. The problem is knowing sometimes when we're
> doing it - which functions might use dynamically allocated memory under
> the covers, etc. The whole runtime (or anyway most of it) was written
> with the assumption that the GC would be available. I would love to see
> all the functions documented in this fashion - warning us which ones
> might trigger GC action - but I suspect it would be a lot of work for
> somebody to do.

I think that in order to succesfully avoid the GC, you just have to abandon
almost whole run-time. And have to write your own <g>!. Actually I am just
working on it. I am writing some substituting functions for the string
manipulation and string-numeric -conversions. At the least I have prepared
to spend couple of days to do it.

Another important question concerning GC free code: does the VO's basic
language (numeric operators, function calls etc) cause the GS kick in. For
instance, I just noticed that following code caused some garbage collecting

FUNCTION start()

LOCAL i,j AS DWORD

_RegCollNotifyStart(@MyGCStartMonitor(),TRUE)
_RegCollNotifyEnd(@MyGCEndMonitor(),TRUE)

FOR i := 1 UPTO 10000
FOR j := 1 UPTO 10
j^j
NEXT
NEXT

_Debout32( psz( _CAST, "done" ))

FUNCTION MyGCEndMonitor() AS VOID PASCAL
_Debout32( psz( _CAST, "GC ends" ))

FUNCTION MyGCStartMonitor() AS VOID PASCAL
_Debout32( psz( _CAST, "GC starts" ))


It seems that ^-operator caused the GC activation.

Olli

FDW

unread,
Jan 31, 2003, 11:27:09 AM1/31/03
to
Ginny,

The registered functions will tell you when GC invocation is started and
ended, not if memory is actual moved.

You can create a 'monitor' method that monitors actual data movements.

GLOBAL glGCDataMoveDetect:=FALSE AS LOGIC

CLASS GCDataMoveDetect

METHOD Init() CLASS GCDataMoveDetect
RegisterAxit(SELF)
RETURN SELF

METHOD Axit() CLASS GCDataMoveDetect
? "Data is movig ;-)"
IF glGCDataMoveDetect
GCDataMoveDetect{}
END
RETURN NIL

FUNCTION Start()
glGCDataMoveDetect:=TRUE
GCDataMoveDetect{}
...
glGCDataMoveDetect:=FALSE
RETURN

Frans

"Ginny Caughey" <ginny....@wasteworks.com> wrote in message
news:b1e3gt$12h7bk$1...@ID-144704.news.dfncis.de...

Robert van der Hulst

unread,
Jan 31, 2003, 11:41:52 AM1/31/03
to
Hi Olli,

On Fri, 31 Jan 2003, at 16:04:21 [GMT GMT] (which was 5:04 PM where I live)
you wrote about: 'REAL8 bug?'

> It seems that ^-operator caused the GC activation.

Of course. x^y is equivalent to Pow(x,y) and pow returns a float.


--
Robert van der Hulst
AKA Mr. Data
Vo2Jet & Vo2Ado Support
www.sas-software.nl
mrd...@sas-software.com

OK

unread,
Jan 31, 2003, 12:46:57 PM1/31/03
to
Thanks Robert

It seems that there is a need for the substitute function which will return
a real <g>.


Olli

Ginny Caughey

unread,
Jan 31, 2003, 12:58:46 PM1/31/03
to
Thanks, Frans. I've saved your message for reference.

--
Ginny


"FDW" <fdewit_...@planet.nl> wrote in message

news:b1e8tu$8qc$1...@reader11.wxs.nl...

Geoff Schaller

unread,
Jan 31, 2003, 7:43:31 PM1/31/03
to
> As it happens 0.5 can be represented exactly, (0.1 in binary or 1x2^-1)
> but 0.1 cannot.

...yes, sorry <g>


Geoff Schaller

unread,
Jan 31, 2003, 7:46:06 PM1/31/03
to
Olli,

> I was using REALs in that belief that FLOAT is dynamic datatype and REAL
is
> not (am I correct). I was intending to get rid of GC (at least as much as

But why? VO is designed to work with the GC. REALs are actually slower to
use and Floats don't cause problems anyway so why avoid them! Honestly, if
you want to avoid the GC, do what Ginny says and go code in C <g>.

Geoff


Geoff Schaller

unread,
Jan 31, 2003, 7:49:53 PM1/31/03
to
Olli,

Exactly why are you so worried about the GC? As long as you obey the basic
rules about pointers to dynamic structures, everything is OK. For most
coding, its totally irrelevant. I don't think its healthy to have an
obsession about avoiding the GC. It is one of the great features of the VO
language.

Geoff


Geoff Schaller

unread,
Jan 31, 2003, 7:52:34 PM1/31/03
to
> But (Geoff!) REAL8+REAL8 calulated w/o converting to FLOATs (asm fadd for
> real8 and faddp for float values).

But you and I both know that most math is not that simple. Just use any
function that requires a Usual as a parameter with real8 and you are off to
float conversions. ...and more. Just ask Frew. He explained it quite
succinctly at Devcon in Germany 2 years ago. He was horrified that people
were actively using Reals instead of floats and he explained why.

Geoff


Igor Kaliniak

unread,
Jan 31, 2003, 9:20:17 PM1/31/03
to
Geoff,

> But you and I both know that most math is not that simple.

Yes, I know <g>. About 5 years ago lost file w. part of my own thesis. I
spent a week to re-prove one theorem, and then made the paper copy in the
institute library.

> Just use any
> function that requires a Usual as a parameter with real8 and you are off
to
> float conversions. ...and more. Just ask Frew. He explained it quite
> succinctly at Devcon in Germany 2 years ago. He was horrified that people
> were actively using Reals instead of floats and he explained why.

Yes, agree. But it is also strange seeing large GC-designed code for
strongly typed simplest arithmetic functions. I think, you also place some
simple repeating calculations in static functions (or inline in C). I would
like set _NOGC declaration for some my functions. Under my own
GC-responsibility, of course.

Igor


Olli Kekäläinen

unread,
Feb 1, 2003, 4:47:15 AM2/1/03
to
Geoff

I agree with you, For most of coding, there is no need to avoid GC. But when
coding multithreaded applications (for example net servers), GC leads to
severe problems. For example registerAxit() and _registerKid() does noet
seem to work proberly in multithreaded environment. Another problem I have
faced with GC and threads is that GC appears to gradually slow execution of
code and finally almost halts it.

Olli

Olli Kekäläinen

unread,
Feb 1, 2003, 5:02:17 AM2/1/03
to
Geoff

See my answer above...

And C(++) is still a options, but like I said earlier, I am so fond of VO's
syntax comparing to C's "crap of fly"-like code <g>. Seriously, I have coded
with VO so long, that achieving equal level of productivity with C++ would
take too long....


Olli

Dave Francis

unread,
Feb 1, 2003, 5:15:19 AM2/1/03
to
Geoff,

To put Olli's work in perspective - He is trying to allow sub-threads to be
GC free, not necessarily the whole caboodle. In our case, we have stripped
down the code in sub-threads to the bare minimum, but still hit apparent GC
triggered problems every 7 days or so. If I can use Olli's work to get all
the sub-thread code into static memory, I am hoping that will knock this
last problem on the head (serial optimist <g>). I don't believe his aim is
to make the whole application GC-free.

If I can solve my problem without going to C, then I'm going to be very
happy (well I'm a reasonably happy bunny anyway <g>). Olli's doing heroic
work at the moment, so all power to his elbow.

Dave Francis

"Geoff Schaller" <geof...@bigpond.net.au> wrote in message
news:iNE_9.727$DC6....@news-server.bigpond.net.au...

Geoff Schaller

unread,
Feb 1, 2003, 10:05:55 PM2/1/03
to
Disagree.

You should see Rod da Silva's paper on advanced multi-threading. Design your
code properly and there are no problems. This paper is being re-presented to
the Aussie Devcon in April.

Geoff


"Olli Kekäläinen" <O...@NOSrhoy.pp.fi> wrote in message

news:Xns9315785D21...@192.89.123.233...

Geoff Schaller

unread,
Feb 1, 2003, 10:11:24 PM2/1/03
to
Dave,

Well, ok, I can understand then where the sentiment is coming from but I
still think you are over-reacting to the GC as the GC being the issue.
Obviously this comes down to coding practice and just as obviously, I can't
see your code. Hence the real issue is obscure for both of us <g>.

Reading the various papers on multi-threading, its not the GC itself which
is necessarily the problem. From 2.5 the GC is labelled as thread-safe and
according to Frew and Uwe, it was and is. What might not be threadsafe is
our coding and the GUI classes. The latter is already under review but we
all now have the SDK and so can do some of our own scrutiny.

Still, its an interesting topic and one day I'd like to see the code that
causes problems.

Geoff


"Dave Francis" <Da...@suilven.com> wrote in message
news:b1g6ku$127mok$1...@ID-147388.news.dfncis.de...

OK

unread,
Feb 2, 2003, 6:07:47 AM2/2/03
to
Hi Geoff

> Disagree.

On which part of my message? Functioning of registerAxit()/_registerkid()?
Slowing fo code execution? Or "I agree with you" sentence <g>?


>
> You should see Rod da Silva's paper on advanced multi-threading. Design
> your code properly and there are no problems. This paper is being
> re-presented to the Aussie Devcon in April.

I would be very interested on reading it. It is published somewhere?

Olli

OK

unread,
Feb 2, 2003, 7:29:50 AM2/2/03
to
Geoff

> Still, its an interesting topic and one day I'd like to see the code
> that causes problems.


I hope that following code will demonstrate the slowing of threads. In my
machine (Windows 2000, 733 MHz, 512MB) execution will occasionally halt at
the end of a sub-thread. Normally one main loop lasts aprox. 700 ms, but
about every 40th loop will last over 20 seconds. You can influence the
behaviour of code with modifying values of the defines included in it (see
them below start() function).


Olli

FUNCTION start()

LOCAL ptrThread1 AS PTR
LOCAL ptrThread2 AS PTR
LOCAL ptrThread3 AS PTR
LOCAL dwThreadID AS DWORD
LOCAL struThreadInfo2 IS THREADINFO
LOCAL struThreadInfo1 IS THREADINFO
LOCAL struThreadInfo3 IS THREADINFO
LOCAL i AS DWORD
LOCAL dwCount AS DWORD
LOCAL dwBegin AS DWORD


dwCount := 1000

DynSize( __DYNSIZE )

_debout32( psz( _CAST, ltrim( str1( dynInfoFree())) ))
sleep(2000)

FOR i := 1 UPTO dwCount

dwBegin := timeGetTime()

struThreadInfo1._exit := FALSE
struThreadInfo2._exit := FALSE
struThreadInfo3._exit := FALSE

struThreadInfo1.rounds := __ROUNDS
struThreadInfo2.rounds := __ROUNDS
struThreadInfo3.rounds := __ROUNDS

#ifdef __GROWTH_MEMORYCONSUMPTION
struThreadInfo1.rounds += i
struThreadInfo2.rounds += i
struThreadInfo3.rounds += i
#endif

#ifdef __PREVENT_GC
dynLock()
#endif

ptrThread1 := CreateVOThread( NULL_PTR,;
0,;
@threadProc_1(),;
@struThreadInfo1 ,;
0,;
@dwThreadId )
ptrThread2 := CreateVOThread( NULL_PTR,;
0,;
@threadProc_2(),;
@struThreadInfo2 ,;
0,;
@dwThreadId )
ptrThread3 := CreateVOThread( NULL_PTR,;
0,;
@threadProc_3(),;
@struThreadInfo3 ,;
0,;
@dwThreadId )

WHILE !struThreadInfo1._exit
END
WHILE !struThreadInfo2._exit
END
WHILE !struThreadInfo3._exit
END


CloseHandle( ptrThread1 )
CloseHandle( ptrThread2 )
CloseHandle( ptrThread3 )


#ifdef __PREVENT_GC
dynUnLock()
dynShrink()
#endif

_debout32( psz( _CAST, "**********" + strzero( i, 7, 0 );
+ " TIME: ";
+ ltrim( str1( timeGetTime() - dwBegin ));
+ " COLLECT COUNT: ";
+ ltrim( str1( collectCount() )) ))

NEXT


sleep(4000)


DEFINE __COLLECT_ATTHREADBEGIN := TRUE

DEFINE __DYNSIZE := 8 // 54

DEFINE __GROWTH_MEMORYCONSUMPTION := FALSE//TRUE

// Setting this TRUE will speed up code execution
DEFINE __PREVENT_GC := FALSE

DEFINE __ROUNDS := 330

DEFINE __TO1_STRINGLEN := 270 // 256

DEFINE __TO2_ARRAYLEN := 77 // 120 // 340

DEFINE __TO2_STRINGLEN := 5

// Setting this TRUE will slow exetution of code even more
DEFINE __EXITVOTHREAD := FALSE

STRUCTURE THREADINFO
MEMBER pConnection AS PTR
MEMBER _exit AS LOGIC
MEMBER rounds AS DWORD

FUNCTION threadProc_1( dwParam AS DWORD ) AS LONGINT PASCAL

LOCAL struInfo AS THREADINFO
LOCAL i AS DWORD
LOCAL dwCount AS DWORD
LOCAL oObject AS testObject
LOCAL aObjects := {} AS ARRAY
LOCAL dwMax AS DWORD
LOCAL dwUsed AS DWORD

_debout32( psz( _CAST, "THREAD 1 STARTED" ))

#ifdef __COLLECT_ATTHREADBEGIN
collectForced()
#endif

struInfo := ptr( _CAST, dwParam )

dwMax := 0
dwCount := struInfo.rounds
FOR i := 1 UPTO dwCount
oObject := testObject{}
aadd( aObjects, oObject )
dwUsed := dynInfoUsed()
IF dwUsed > dwMax
dwMax := dwUsed
ENDIF
NEXT

_debout32( psz( _CAST, "THREAD 1 USED: ";
+ ltrim( str1( dwMax ))))

struInfo._exit := TRUE
#ifdef __EXITVOTHREAD
exitVoThread(0)
#endif

RETURN 0L

FUNCTION threadProc_2( dwParam AS DWORD ) AS LONGINT PASCAL

LOCAL struInfo AS THREADINFO
LOCAL i AS DWORD
LOCAL dwCount AS DWORD
LOCAL oObject AS testObject
LOCAL aObjects := {} AS ARRAY
LOCAL dwMax AS DWORD
LOCAL dwUsed AS DWORD

_debout32( psz( _CAST, "THREAD 2 STARTED" ))

#ifdef __COLLECT_ATTHREADBEGIN
collectForced()
#endif

struInfo := ptr( _CAST, dwParam )

dwMax := 0
dwCount := struInfo.rounds
FOR i := 1 UPTO dwCount
oObject := testObject{}
aadd( aObjects, oObject )
dwUsed := dynInfoUsed()
IF dwUsed > dwMax
dwMax := dwUsed
ENDIF
NEXT

_debout32( psz( _CAST, "THREAD 2 USED: ";
+ ltrim( str1( dwMax ))))

struInfo._exit := TRUE
#ifdef __EXITVOTHREAD
exitVoThread(0)
#endif

RETURN 0L

FUNCTION threadProc_3( dwParam AS DWORD ) AS LONGINT PASCAL

LOCAL struInfo AS THREADINFO
LOCAL i AS DWORD
LOCAL dwCount AS DWORD
LOCAL oObject AS testObject
LOCAL aObjects := {} AS ARRAY
LOCAL dwMax AS DWORD
LOCAL dwUsed AS DWORD

_debout32( psz( _CAST, "THREAD 3 STARTED" ))

struInfo := ptr( _CAST, dwParam )

#ifdef __COLLECT_ATTHREADBEGIN
collectForced()
#endif

dwMax := 0
dwCount := struInfo.rounds
FOR i := 1 UPTO dwCount
oObject := testObject{}
aadd( aObjects, oObject )
dwUsed := dynInfoUsed()
IF dwUsed > dwMax
dwMax := dwUsed
ENDIF
NEXT

_debout32( psz( _CAST, "THREAD 3 USED: ";
+ ltrim( str1( dwMax ))))

struInfo._exit := TRUE

#ifdef __EXITVOTHREAD
exitVoThread(0)
#endif

RETURN 0L

CLASS testObject

PROTECT oObject1 AS testObject1
PROTECT oObject2 AS testObject2

METHOD init() CLASS testObject
self:oObject1 := testObject1{}
self:oObject2 := testObject2{}

CLASS testObject1
PROTECT s AS STRING


METHOD init() CLASS testObject1
self:s := replicate("X",__TO1_STRINGLEN)

CLASS testObject2
PROTECT a := {} AS ARRAY

METHOD init() CLASS testObject2

LOCAL i AS DWORD
LOCAL dwCount AS DWORD

dwCount := __TO2_ARRAYLEN

FOR i := 1 UPTO dwCount
aadd( self:a, replicate( "Y", __TO2_STRINGLEN ))
NEXT

OK

unread,
Feb 2, 2003, 7:37:46 AM2/2/03
to
Sorry Geoff,

I forgot to mention that you need Debug View (or a corresponding tool) in
order to observe the execution of the code.

Olli

Geoff Schaller

unread,
Feb 4, 2003, 7:12:34 AM2/4/03
to
> On which part of my message? Functioning of registerAxit()/_registerkid()?
> Slowing fo code execution? Or "I agree with you" sentence <g>?

No. I disagreed with the sentence that suggested that the GC made
multi-threaded apps a nightmare. This is wrong. What is needed first is
proper knowledge of multi-threading in general. Then the GC will become your
friend.

> I would be very interested on reading it. It is published somewhere?

No its not. But come to our conference and you will be have it presented to
you. Alternately, contact Rod direct.

Geoff


Geoff Schaller

unread,
Feb 4, 2003, 7:14:34 AM2/4/03
to
That's ok, I understood that <g>.

I'll take a look on the weekend but gee you code a lot of unecessary stuff!
<g>

Geoff

"OK" <O...@NOSrhoy.pp.fi> wrote in message
news:Xns93169547F8...@192.89.123.233...

Ginny Caughey

unread,
Feb 4, 2003, 10:13:55 AM2/4/03
to
Geoff,

Rod said he also ran into GC problems after a certain number of threads - I
think it was 32 in his case. Anyway, I'm pretty sure he understands
multithreading concepts and also the VO GC. I never saw this problem since my
production apps aren't running more than 8 worker threads at any one time.

--
Ginny


"Geoff Schaller" <geof...@bigpond.net.au> wrote in message

news:S6O%9.12372$DC6....@news-server.bigpond.net.au...

- Jari -

unread,
Feb 4, 2003, 6:53:58 PM2/4/03
to
Geoff,

> This is wrong. What is needed first is
> proper knowledge of multi-threading in general.

What can I say, Geoff..

This would be something you could know before saying nothing is
wrong with CG. I strongly believe that Olli has enough knowledge
to say this.

Also your statement that Rod has said everything is fine if things
are done correctly, is wrong.

Rod has already said in this ng that there is least couple problems...

1. Thread limit
2. VO's way to handle CG stack as local to thread

And I have doubt that that even Rod has deeply debugged stuff under
COM+ environment in several threading models etc...

So there might be more of them...

So you might take Olli's sample and spend couple days wondering
what is going on and where is the problem... <g>

- Jari -


Geoff Schaller

unread,
Feb 5, 2003, 4:08:32 AM2/5/03
to
Yes I saw that reference too but then he wasn't entirely sure which part of
the "system" to blame: the OS, C++ or VO. I don't run anything that has that
many threads either so I can't say.

But none of this says that the GC itself is to blame. And nothing says that
it interferes with all multi-threaded apps.

Rod's paper makes interesting reading. Maybe we can set some tests up at the
conference?

Geoff


"Ginny Caughey" <ginny....@wasteworks.com> wrote in message

news:b1olc7$14r8aj$1...@ID-144704.news.dfncis.de...

Geoff Schaller

unread,
Feb 5, 2003, 4:11:13 AM2/5/03
to
Jari,

I am only going down the path that the statement that the GC makes
multi-threaded apps impossible is clearly wrong. There are good VO
multi-threaded apps around working just fine. I hope to have a commercial
one on display at our conference. That's not to say that there limitations
or issues around but to simply say that you cannot multi-thread with the GC
is nonsense. At least Rod's paper and the various working apps prove this.

Geoff


"- Jari -" <Jari....@SPAMREMOVE.codeblock.fi> wrote in message
news:b1pjqr$i4d$1...@phys-news1.kolumbus.fi...

- Jari -

unread,
Feb 5, 2003, 6:15:55 AM2/5/03
to
Geoff,

> I am only going down the path that the statement that the GC makes
> multi-threaded apps impossible is clearly wrong.

Well isn't this statement which is quite twisted.
If some feature has bugs it doesn't make whole feature
useless or what! It just forces to find way round to it.

> There are good VO multi-threaded apps around working just fine.

If are talking about apps that creates 10-100 simultenous threads
and uses VO's dynamic memory types inside threads and maybe are
executed under Component Manager or EXE's which run continously
on server 24/7 basis.

I haven't seen any...maybe you could point me one...

> I hope to have a commercial one on display at our conference.

> That's not to say that there limitations
> or issues around but to simply say that you cannot multi-thread with the GC
> is nonsense.

You seem to have a way to twist words. Nobody has said anything like
this.

Nonsence is to say...

"But none of this says that the GC itself is to blame"

"but then he (Rod) wasn't entirely sure which part of the "system" to blame: the OS, C++ or VO"

"Then the GC will become your friend."

"Design your code properly and there are no problems"

"As long as you obey the basic rules about pointers to dynamic structures, everything is OK"

"For most coding, its totally irrelevant"

Do you need more..?

As I have said to Ginny...

Vo (especially multithreading) is like car with one smaller wheel.
You can drive it, but not as it supposed to be done and not that fast.
This is not the way VO should be.

>At least Rod's paper and the various working apps prove this.

We'll see.. <g>

- Jari -


Ginny Caughey

unread,
Feb 5, 2003, 9:58:02 AM2/5/03
to
Jari,

> Vo (especially multithreading) is like car with one smaller wheel.
> You can drive it, but not as it supposed to be done and not that fast.

Exactly. It works fine unless you push it too hard.

> This is not the way VO should be.

I would like to agree with this too, but it's the way VO has always been - in
fact VO just keeps getting better and better. The problem for VO is that other
dev tools just keep getting better and better too. It is true that writing
multithreaded apps is tricky in any language. Some languages like C++ have
supported multithreading for decades but don't have a GC. Some languages like C#
(or more correctly the .Net runtime) have a GC that was designed from the
beginning to support multithreading. But VO was never designed for the
sophisticated apps that we write today, especially multithreaded ones. Although
the VO team(s) have worked throughout VO's history to make it more powerful and
more reliable under pressure, it's possible that we be approaching the limit of
what VO's design can realistically do at the same time that a shrinking market
may make it harder and harder to justify the expense of a redesign. I've come to
the conclusion for myself to use VO for the many things that VO does very well,
but to use other tools when VO isn't really the best choice.

Ginny


- Jari -

unread,
Feb 5, 2003, 3:51:38 PM2/5/03
to
Ginny,

> I would like to agree with this too, but it's the way VO has always been - in
> fact VO just keeps getting better and better.

I agree, but there could be couple better words more...

> Although the VO team(s) have worked throughout VO's history to make it more
powerful and more reliable under pressure, it's possible that we be approaching the limit of what
VO's design can realistically<

Here I have to disagree. I think VO has lost several years in hands
of excellent developers, but to whom was never given enough time
and resources (CA decision) to make it perfect. I really think these
guys would have loved to do it that way.

I maybe wrong....
To be honest I doubt there wasn't even single one full time developer
in VO team. They were all signed to do something else and then come
back make this VO crowd happy with one service patch.

>do at the same time that a shrinking market<

I am not going to say anything about VO market...<g>

>it's possible that we be approaching the limit of
>what VO's design can realistically

VO's design is capable I am convinced about that, but
I am not convinced about GC writers good coding practices..<g>

>do at the same
>time that a shrinking market
>may make it harder and harder to justify the
>expense of a redesign

I agree, but while there is light there is hope..<g>

And Ginny, yes we can also C# the other light...<g>

But {
I hate;
these;
}

- Jari -


Ginny Caughey

unread,
Feb 5, 2003, 7:36:56 PM2/5/03
to
Hi Jari,

> Here I have to disagree. I think VO has lost several years in hands
> of excellent developers, but to whom was never given enough time
> and resources (CA decision) to make it perfect. I really think these
> guys would have loved to do it that way.

This is certainly possible. I'm pretty sure that a lot of work VO got was pretty
much on a volunteer basis toward the end.

> VO's design is capable I am convinced about that, but
> I am not convinced about GC writers good coding practices..<g>

Careful coding is especially important with multithreading - in any language.
But the basic design of VO's GC - that it doesn't run on a separate thread that
can control all the other threads - is the root cause of some dynamic memory
problems even in single-threaded apps. I have never been told enough details
about what CA did for VO 2.5 to the GC to make it thread-safe to be able to
determine if the new design made sense one. It works for me with a maximum of 8
threads at a time, but if good programmers are running into a limit after more
threads, I'm inclined to believe that the design of VO's GC still isn't good
enough for this sort of usage.

> But {
> I hate;
> these;
> }

So
{
Do them this way;
}

<g>

Ginny


Stephen Quinn

unread,
Feb 6, 2003, 2:59:06 AM2/6/03
to
Ginny

> So
> {
> Do them this way;
> }
>
> <g>

I prefer that way as well

--
HTH
Steve Quinn


Geoff Schaller

unread,
Feb 6, 2003, 5:56:02 AM2/6/03
to
Jari,

> Well isn't this statement which is quite twisted.

Well yes it was. The statement was very clear: it said that the GC made
multi-threaded apps in VO almost impossible. I am just saying that this is
not correct and probably indicates a lack of experience on the part of the
coder.

> If some feature has bugs it doesn't make whole feature
> useless or what! It just forces to find way round to it.

In this case I don't think this is a fair statement. The GC has an important
role to play and yes, it obviously comes with some limitations for
successful implementation. Deal with them.

> If are talking about apps that creates 10-100 simultenous threads
> and uses VO's dynamic memory types inside threads and maybe are

> I haven't seen any...maybe you could point me one...

Ok, come to our conference.

> You seem to have a way to twist words. Nobody has said anything like
> this.

No, not at all. I have no idea what you want to do with your multi-threaded
app but the one thing you don't do across thread boundaries is refer to
dynamic objects. But within a thread there really isn't a problem. But large
and complex multi-threaded apps are.... large and complex. In any lanuage.
Read some of the stuff on the MSDN (mostly in C++ and C# now). Its a tough
world and they too cover the issues that need to be addressed. GC or no GC.

All I'm saying is: don't blame the GC.

> Do you need more..?

More what?

> Vo (especially multithreading) is like car with one smaller wheel.
> You can drive it, but not as it supposed to be done and not that fast.
> This is not the way VO should be.

Hmmm. But are you asking for things that VO is not optimised to do? If you
find that one particular tool can do something better than another then
don't you go and use that tool for that task? So, if you find you can
develop your multi-threaded app in another language and achieve your goal
then go right ahead. Would I write a high volume web server in VO? probably
not. Would I write a 100 line modem manager in VO? Sure. Pick the tool for
the task.

Geoff


- Jari -

unread,
Feb 7, 2003, 9:19:04 AM2/7/03
to
Geoff,

> Well yes it was. The statement was very clear: it said that the GC made
> multi-threaded apps in VO almost impossible.

It is maybe the way GC is implemented not that GC can't be implemented
in multithreaded capable language...

And VO's GC is not so far away from it, I believe...haven't seen
the code.. <g>

> I am just saying that this is
> not correct and probably indicates a lack of experience on the part of the
> coder.

This is where you are wrong!

> In this case I don't think this is a fair statement. The GC has an important
> role to play and yes, it obviously comes with some limitations for
> successful implementation. Deal with them.

No! We have found the way around it. No GC!

> > If are talking about apps that creates 10-100 simultenous threads
> > and uses VO's dynamic memory types inside threads and maybe are
> > I haven't seen any...maybe you could point me one...

So you think I have to make trip to other side of the world
to see working multithreaded VO app...get real...

Geoff,

> No, not at all. I have no idea what you want to do with your multi-threaded
> app but the one thing you don't do across thread boundaries is refer to
> dynamic objects.

Well isn't this very clear!

> But within a thread there really isn't a problem.

Yes there is, look at the sample Olli gave to you!

> But large
> and complex multi-threaded apps are.... large and complex. In any lanuage.
> Read some of the stuff on the MSDN (mostly in C++ and C# now). Its a tough
> world and they too cover the issues that need to be addressed. GC or no GC.

Absolutely, but they are no


> All I'm saying is: don't blame the GC.

Why? It is _the_ problem...

> > Do you need more..?
> More what?

More nonsense <g> Look your msg...

> Hmmm. But are you asking for things that VO is not optimised to do?

Absolutely not. Why there is CreateVOThread() if it doesn't work?
Just for fun?

> So, if you find you can
> develop your multi-threaded app in another language and achieve your goal
> then go right ahead. Would I write a high volume web server in VO? probably
> not.

We have done something similar, it is not web server it was just sample.
It is IP server which can handle client request like item:dothis()

Let me explain...

In client you would write like...

ourserver:connect()
oApp := ourserver:getApp()
oCollection := oApp:DoThis() //Remote call to server
oCollection //Use as normal VO object

oApp:DoThis() is actually remote call over IP to server (written in VO)
IOW oApp interface takes the call and converts call to Z protocol and
then sends it as "string" to server. Server parses the call executes
it against it's application model and loads the return value to object.
Which is then extracted to Z protocol and sends it as a "string" to client
whic automaticall rebuilds the object so it can be seen as object
in our app.

IOW Who needs SOAP! <g>

So you can understand that multithreading is only way to get it
work correctly and because we are using VO's nice features
I don't like the idea changing the tool. And I have to say
I think we would be facing lot of more problems with other tools...<g>

>Would I write a 100 line modem manager in VO? Sure. Pick the tool for
>the task.

VO is the tool and we have found pretty good ways to around
the GC.

Generally I am speaking about improvement here, not bashing
VO's GC. And VO's GC is not that far away from where it should be.

- Jari -


Geoff Schaller

unread,
Feb 8, 2003, 4:30:58 AM2/8/03
to
Ok, <shrug> so I don't know where you are taking this.
I don't disagree with most of what you say.

My experience with multi-threaded apps is very limited. Happy to say that.
However, Rod and others run threaded apps and environments quite happily.
All using VO objects to manage the threads and objects within. The GC is
very active - and certianly not a hinderance. But Rod, Ginny and others have
found that VO falls into a hole somewhere around the point of 32
simultaneous threads. Now, whether that's a GC issue, a C++ runtime issue or
what... who knows?

So, the only thing I draw from this is that for 32+ threads running in an
app, I should probably look to a different tool from VO.

Geoff

PS - By the way, you quip about SOAP is very interesting. There is more
behind this than many people might think....

0 new messages