public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* exceptions and threads---a survival tactic!
@ 1998-03-11  9:31 Kaz Kylheku
  1998-03-12  0:31 ` Branko Cibej
  0 siblings, 1 reply; 9+ messages in thread
From: Kaz Kylheku @ 1998-03-11  9:31 UTC (permalink / raw)
  To: egcs

Hi everyone;

I joined the lists in order to get updates about the status of the
thread-safety of exception handling in EGCS. I was pleasantly surprised
to see this discussed in some of the archives of the mailing lists,
and that it is being addressed already in some cutting edge code.

For those of you who are waiting for a release version, or just 
can't get the cutting edge stuff to work for whatever reason, here is
a simple trick that can help you get started on using exceptions in
threaded code even though exception handling is not thread safe.

Basically, the idea is that you should create one global mutex to
ensure that only one thread is performing exception handling at
a time. 

Prior to every throw, lock this mutex. And unlock this mutex 
in every catch clause (unless you are immediately going to
throw again).

example:

	if (bad_condition) {
		eh_mutex.lock();
		throw error();
	}

and in the catch somewhere else:

	catch (error) {
		eh_mutex.unlock();
		// ... whatever ...
	}

or

	catch (error) {
		// don't bother unlocking since
		// we throw again.
		// .. whatever ...
		throw;
	}

For this to be meaningful, you must do it absolutely
everywhere in your project. I grepped the sources for
throw and catch, and painstakingly inserted the
locking and unlocking statements. Lo and behold,
the program compiled and ran like a charm.

Obviously, you have bad luck as far things like bad alloc
exceptions, which will obviously not cooperate with this
scheme unless you mess with the compiler's run-time
support libraries.

But I've had fairly good success with it so far, and it looks
like it will carry me until I take the plunge and try the new
thread-safe exception handling support (and find out how
well it works with LinuxThreads :).

The potential bottleneck should not be a worry since
in well designed programs (IMHO), exception handling is
an infrequent occurence for, well, ``exceptional'' events.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: exceptions and threads---a survival tactic!
  1998-03-11  9:31 exceptions and threads---a survival tactic! Kaz Kylheku
@ 1998-03-12  0:31 ` Branko Cibej
  1998-03-12  8:22   ` Joe Buck
  0 siblings, 1 reply; 9+ messages in thread
From: Branko Cibej @ 1998-03-12  0:31 UTC (permalink / raw)
  To: Kaz Kylheku, egcs

Kaz Kylheku wrote:

> The potential bottleneck should not be a worry since
> in well designed programs (IMHO), exception handling is
> an infrequent occurence for, well, ``exceptional'' events.

You should look at some of the discussions in the comp.lang.c++.moderated
archive :-) You'll find that opinions about that vary widely.

The fact is, with properly implemented exception-handling code that *does*
care about runtime overhead, you can write much faster code by using EH for
flow control than by the traditional "if (foo) bar(); else baz();" method.
Typical applications that come to mind are complicated recursive-descent
parsers (one of the examples in c.l.c++.m was a MIDI interpreter).

Besides, you can use lean-and-mean EH for "exceptional events only" designs
quite easily...

--
Branko Cibej   <branko.cibej@hermes.si>
HERMES SoftLab, Litijska 51, 1000 Ljubljana, Slovenia
phone: (++386 61) 186 53 49  fax: (++386 61) 186 52 70



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: exceptions and threads---a survival tactic!
  1998-03-12  0:31 ` Branko Cibej
@ 1998-03-12  8:22   ` Joe Buck
  1998-03-12  9:25     ` Branko Cibej
  1998-03-12 16:29     ` Toon Moene
  0 siblings, 2 replies; 9+ messages in thread
From: Joe Buck @ 1998-03-12  8:22 UTC (permalink / raw)
  To: Branko Cibej; +Cc: kaz, egcs

Kaz Kylheku wrote:
> > The potential bottleneck should not be a worry since
> > in well designed programs (IMHO), exception handling is
> > an infrequent occurence for, well, ``exceptional'' events.

Branko Cibej writes:
> You should look at some of the discussions in the comp.lang.c++.moderated
> archive :-) You'll find that opinions about that vary widely.
> 
> The fact is, with properly implemented exception-handling code that *does*
> care about runtime overhead, you can write much faster code by using EH for
> flow control than by the traditional "if (foo) bar(); else baz();" method.

Yes, and this can be even more true in Java.  The March '98 issue of Byte
has a piece by David Orchard entitled "Better Performance With Exceptions
in Java".  He finds that, for very large arrays, 

try {
	for (int i = 0; ; i++) {
		anInt[i] = i;
	}
}
catch (ArrayIndexOutOfBoundsException e) {}

is 30-40% faster on JDK 1.1.3 (Sun's Windows version) than the traditional

	for (int i = 0; i < ARRAY_SIZE; i++) {
		anInt[i] = i;
	}

(I suspect, though, that this is because there is a range check on each
array access in Java, so the traditional code does the same test twice).





^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: exceptions and threads---a survival tactic!
  1998-03-12  8:22   ` Joe Buck
@ 1998-03-12  9:25     ` Branko Cibej
  1998-03-12 14:50       ` Joe Buck
  1998-03-12 16:29     ` Toon Moene
  1 sibling, 1 reply; 9+ messages in thread
From: Branko Cibej @ 1998-03-12  9:25 UTC (permalink / raw)
  To: Joe Buck; +Cc: kaz, egcs

Joe Buck wrote:

> > The fact is, with properly implemented exception-handling code that *does*
> > care about runtime overhead, you can write much faster code by using EH for
> > flow control than by the traditional "if (foo) bar(); else baz();" method.
>
> Yes, and this can be even more true in Java.  The March '98 issue of Byte
> has a piece by David Orchard entitled "Better Performance With Exceptions
> in Java".  He finds that, for very large arrays,
>
> try {
>         for (int i = 0; ; i++) {
>                 anInt[i] = i;
>         }
> }
> catch (ArrayIndexOutOfBoundsException e) {}
>
> is 30-40% faster on JDK 1.1.3 (Sun's Windows version) than the traditional
>
>         for (int i = 0; i < ARRAY_SIZE; i++) {
>                 anInt[i] = i;
>         }
>
> (I suspect, though, that this is because there is a range check on each
> array access in Java, so the traditional code does the same test twice).

Aha! And someday, when (e)gcs gets a Java front-end, it could be taught to
recognize the second form and optimize it to the first form, and at once become
the best Java optimizing compiler available.

(Would this be called "range check elimination"? :-)

--
Branko Cibej   <branko.cibej@hermes.si>
HERMES SoftLab, Litijska 51, 1000 Ljubljana, Slovenia
phone: (++386 61) 186 53 49  fax: (++386 61) 186 52 70



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: exceptions and threads---a survival tactic!
  1998-03-12  9:25     ` Branko Cibej
@ 1998-03-12 14:50       ` Joe Buck
  1998-03-15 15:15         ` Craig Burley
  0 siblings, 1 reply; 9+ messages in thread
From: Joe Buck @ 1998-03-12 14:50 UTC (permalink / raw)
  To: Branko Cibej; +Cc: jbuck, kaz, egcs

> > ...  He finds that, for very large arrays,
> >
> > try {
> >         for (int i = 0; ; i++) {
> >                 anInt[i] = i;
> >         }
> > }
> > catch (ArrayIndexOutOfBoundsException e) {}
> >
> > is 30-40% faster on JDK 1.1.3 (Sun's Windows version) than the traditional
> >
> >         for (int i = 0; i < ARRAY_SIZE; i++) {
> >                 anInt[i] = i;
> >         }
> >
> > (I suspect, though, that this is because there is a range check on each
> > array access in Java, so the traditional code does the same test twice).

> Aha! And someday, when (e)gcs gets a Java front-end, it could be taught
> to recognize the second form and optimize it to the first form, and at
> once become the best Java optimizing compiler available.

Actually, I suspect that for JIT compilers the second form is better,
since it would be fairly trivial to eliminate the range check.  In fact,
one point made by the Byte article is that in Microsoft's implementation
the *second* form is faster (in Sun's implementation try blocks add zero
cost but in Microsoft's try blocks slow things down, indicating a
completely different way of implementing exceptions), meaning that if you
care about performance, Java isn't really portable: you have to know which
implementation your users will be running.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: exceptions and threads---a survival tactic!
  1998-03-12  8:22   ` Joe Buck
  1998-03-12  9:25     ` Branko Cibej
@ 1998-03-12 16:29     ` Toon Moene
  1998-03-13 15:04       ` Kaz Kylheku
  1 sibling, 1 reply; 9+ messages in thread
From: Toon Moene @ 1998-03-12 16:29 UTC (permalink / raw)
  To: Joe Buck; +Cc: egcs

>  Yes, and this can be even more true in Java.  The March
>  '98 issue of Byte has a piece by David Orchard entitled
>  "Better Performance With Exceptions in Java".  He finds
>  that, for very large arrays,

[ Run loop until end of array by catching index-out-of-bound
  exception ]

>  is 30-40% faster on JDK 1.1.3 (Sun's Windows version)
>  than the traditional

[ Run a loop bounded by the upper array bound ]

OK, even though this has every chance to escalate into a language  
war, I can't let this pass:

This must be specific to Java.

About a year and a half ago I installed the latest operational  
version of our numerical weather forecasting system (see  
http://www.knmi.nl/hirlam ) on a DEC Alpha, using Digital Fortran.  I  
tried compiling both with and without (compiler generated) array  
bound checking.  The difference in run time was *undetectable* (i.e.  
below 1 %, the variance between two successive runs), even though  
_every_ array access would have 2 x 2 comparison operations (upper  
and lower bound in two dimensions).  Oh, and you can be assured that  
numerical weather forecasting is nothing else but using data in  
arrays.

The reason the overhead is so low is that conditional branches on  
Alpha's (and probably on other architectures too) are predicted "not  
taken".  So as long as the checking code branches _out_ of the main  
line of computing on error, it's almost free.  Hence, there  
wouldn't be any gain in handling this via exceptions (not that any  
current Fortran standard _has_ any).

HTH,
Toon.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: exceptions and threads---a survival tactic!
  1998-03-12 16:29     ` Toon Moene
@ 1998-03-13 15:04       ` Kaz Kylheku
  1998-03-14  4:14         ` Toon Moene
  0 siblings, 1 reply; 9+ messages in thread
From: Kaz Kylheku @ 1998-03-13 15:04 UTC (permalink / raw)
  To: Toon Moene; +Cc: Joe Buck, egcs

On Thu, 12 Mar 1998, Toon Moene wrote:

> About a year and a half ago I installed the latest operational  
> version of our numerical weather forecasting system (see  
> http://www.knmi.nl/hirlam ) on a DEC Alpha, using Digital Fortran.  I  
> tried compiling both with and without (compiler generated) array  
> bound checking.

> The difference in run time was *undetectable* (i.e.  
> below 1 %, the variance between two successive runs), even though  

It could be that the compiler is able to optimize the bound checking.
I mean, if you have a loop of the form

	for (i = 0; i < 100; i++) { /*...*/ }

and the array runds from 0 to 99, and i is not messed with in the
loop, the compiler can figure out that no range check is actually
needed.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: exceptions and threads---a survival tactic!
  1998-03-13 15:04       ` Kaz Kylheku
@ 1998-03-14  4:14         ` Toon Moene
  0 siblings, 0 replies; 9+ messages in thread
From: Toon Moene @ 1998-03-14  4:14 UTC (permalink / raw)
  To: Kaz Kylheku; +Cc: egcs

>  It could be that the compiler is able to optimize the
>  bound checking.  I mean, if you have a loop of the form
>
>  	for (i = 0; i < 100; i++) { /*...*/ }
>
>  and the array runds from 0 to 99, and i is not messed
>  with in the loop, the compiler can figure out that no
>  range check is actually needed.

Yep, however, peeking into the assembler output produced by DEC's  
Fortran compiler, it doesn't do that for loops like this:

      subroutine aap(x, y, n)
      integer n
      real x(n,n), y(n,n)
      integer i
      do i = 2, n
         do j = 2, n
            x(j, i) = (y(j-1,i) + y(j,i) + y(j,i-1))/3.
         enddo
      enddo
      end

which are somewhat more representative of the programs I was  
thinking of.  Apparently, the analysis necessary to move the  
index-to-bounds comparison out of the loop is too much for this  
compiler.

Cheers,
Toon.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: exceptions and threads---a survival tactic!
  1998-03-12 14:50       ` Joe Buck
@ 1998-03-15 15:15         ` Craig Burley
  0 siblings, 0 replies; 9+ messages in thread
From: Craig Burley @ 1998-03-15 15:15 UTC (permalink / raw)
  To: jbuck; +Cc: branko.cibej, kaz, egcs

>[...] meaning that if you
>care about performance, Java isn't really portable: you have to know which
>implementation your users will be running.

The example in question seems like a great one to illustrate
the verity of the above statement for Java, but I believe
it's fair to say that the above statement is still true
when one replaces "Java" with "*".  ;-)

        tq vm, (burley)

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~1998-03-15 15:15 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-03-11  9:31 exceptions and threads---a survival tactic! Kaz Kylheku
1998-03-12  0:31 ` Branko Cibej
1998-03-12  8:22   ` Joe Buck
1998-03-12  9:25     ` Branko Cibej
1998-03-12 14:50       ` Joe Buck
1998-03-15 15:15         ` Craig Burley
1998-03-12 16:29     ` Toon Moene
1998-03-13 15:04       ` Kaz Kylheku
1998-03-14  4:14         ` Toon Moene

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).