www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - try-catch exception handling speed should be improved!.

reply Lord Syl <Lord_member pathlink.com> writes:
Hey, I just made a quick test, in order to see method calls' speed.
When I compared the results to Java's, I found interesting that Java (running
via JVM) had beaten D in the Try-Catch exception handling speed area, while
running slow as hell in the rest.

Here are the results:

<[D] 500 Million Calls speed test >>

TryCatched - 13750 ms
!TryCatched - 1933 ms
Directly - 1292 ms

Compiler version is 0.90, with commandline -O -release -inline

<[Java] 500 Million Calls speed test >>

TryCatched - 10926 ms
!TryCatched - 4406 ms
Directly - 4597 ms

Using Java VM v1.50 beta from Sun

Tests were done on a Duron 800(6x133) processor with  640Mb 266Mhz RAM under
Windows XP.

[D source code]

import std.date;
int main (char[][] args)
{
int i, j=-42;
printf(" ##### 500 Million Calls Speed Test #####\n");
long START_TC=getUTCtime();
for (i=0; i<500000000; i++) j=TCcall(i);
long END_TC=getUTCtime();
long START=getUTCtime();
for (i=0; i<500000000; i++) j=Ccall(i);
long END=getUTCtime();
long start=getUTCtime();
for(i=0; i<500000000; i++) j=i+4;
long end=getUTCtime();
printf("(TryCatched) Elapsed (ms) : %d\n",(END_TC-START_TC));
printf("(!TryCatched) Elapsed (ms) : %d\n",(END-START));
printf("(Directly) Elapsed (ms) : %d\n",(end-start));
return 0;
}

static final int TCcall(int I)
{
try
{
I+=4;
return I;
}
catch(Error e) { return I; }
}

static final int Ccall(int I)
{
I+=4;
return I;
}

[Java code]

public class PointlessSpeedTest
{
public static void main (String[] args)
{
int i, j=-42;
System.out.println("##### 500 Million Calls Speed Test #####");
long START_TC=System.currentTimeMillis();
for (i=0; i<500000000; i++) j=TCcall(i);
long END_TC=System.currentTimeMillis();
long START=System.currentTimeMillis();
for (i=0; i<500000000; i++) j=Ccall(i);
long END=System.currentTimeMillis();
long start=System.currentTimeMillis();
for(i=0; i<500000000; i++) j=i+4;
long end=System.currentTimeMillis();
System.out.println("(TryCatched) Elapsed: "+(END_TC-START_TC)+" ms");
System.out.println("(!TryCatched) Elapsed: "+(END-START)+" ms");
System.out.println("(Directly) Elapsed: "+(end-start)+" ms");
}

private static int TCcall(int I)
{
try
{
I+=4;
return I;
}
catch(Exception ex) { return I; }
}

private static int Ccall(int I)
{
I+=4;
return I;
}
}
May 22 2004
next sibling parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Lord Syl schrieb:

 Hey, I just made a quick test, in order to see method calls' speed.
 When I compared the results to Java's, I found interesting that Java (running
 via JVM) had beaten D in the Try-Catch exception handling speed area, while
 running slow as hell in the rest.

No, speed of try/catch shouldn't be improved. The main guideline for implementation of exception handling is that it should slow down the normal run of the program - i.e. without exceptions being thrown - as little as possible. And your test tells me rather that DigitalMars implementation succeeds in that well. And well, 1/3 difference is not important - exceptions can take even much longer time to process depending on circumstances and should not be used in performance sensitive code. It's a tradeoff which was made wisely. -eye
May 22 2004
next sibling parent Roel Mathys <roel.mathys yucom.be> writes:
Ilya Minkov wrote:
 Lord Syl schrieb:
 
 Hey, I just made a quick test, in order to see method calls' speed.
 When I compared the results to Java's, I found interesting that Java 
 (running
 via JVM) had beaten D in the Try-Catch exception handling speed area, 
 while
 running slow as hell in the rest.

No, speed of try/catch shouldn't be improved. The main guideline for implementation of exception handling is that it should slow down the normal run of the program - i.e. without exceptions being thrown - as little as possible. And your test tells me rather that DigitalMars implementation succeeds in that well. And well, 1/3 difference is not important - exceptions can take even much longer time to process depending on circumstances and should not be used in performance sensitive code. It's a tradeoff which was made wisely. -eye

I would phrase it like this: performance isn't the prime objective of exception handling, but I don't see an issue in it being optimized performance wise rm
May 22 2004
prev sibling next sibling parent Lord Syl <Lord_member pathlink.com> writes:
In article <c8ne2r$i2l$1 digitaldaemon.com>, Ilya Minkov says...

No, speed of try/catch shouldn't be improved. The main guideline for 
implementation of exception handling is that it should slow down the 
normal run of the program - i.e. without exceptions being thrown - as 
little as possible. And your test tells me rather that DigitalMars 
implementation succeeds in that well. And well, 1/3 difference is not 
important - exceptions can take even much longer time to process 
depending on circumstances and should not be used in performance 
sensitive code. It's a tradeoff which was made wisely.

-eye

You didn't take into account that, although the "absolute" difference is a 30%, the other results were there for something. According to those results, the (exception handled)/(non-exception handled) proportion in Java is around 250%, while D shows there a 700%, so some improvement is possible there. At all, one of the points of exception handling is to avoid the need to use "defensive code" to improve readability and increase performance.
May 22 2004
prev sibling parent reply Norbert Nemec <Norbert.Nemec gmx.de> writes:
Ilya Minkov wrote:

 Lord Syl schrieb:
 
 Hey, I just made a quick test, in order to see method calls' speed.
 When I compared the results to Java's, I found interesting that Java
 (running via JVM) had beaten D in the Try-Catch exception handling speed
 area, while running slow as hell in the rest.

No, speed of try/catch shouldn't be improved. The main guideline for implementation of exception handling is that it should slow down the normal run of the program - i.e. without exceptions being thrown - as little as possible. And your test tells me rather that DigitalMars implementation succeeds in that well.

Sure? If I understand the code correctly, it measures the time of the try/catch block *without throwing exceptions*, which would mean, that the DM compiler really does not follow your "main guideline". Of course "throw" need not be optimized for speed, but try/catch should not cost that much!
May 22 2004
parent Lord Syl <Lord_member pathlink.com> writes:
In article <c8nnp6$uil$3 digitaldaemon.com>, Norbert Nemec says...

Sure? If I understand the code correctly, it measures the time of the
try/catch block *without throwing exceptions*, which would mean, that the
DM compiler really does not follow your "main guideline". Of course "throw"
need not be optimized for speed, but try/catch should not cost that much!

You got it :) . The code measures the setup time, as it's important, specially for system apps, that if a set of methods which are called continuously are written using exception handling, if there is no error on the data they receive (no exception is caused) then it isn't slowed down too much.
May 22 2004
prev sibling next sibling parent "Matthew" <matthew.hat stlsoft.dot.org> writes:
AFAIK, D's exceptions are layered on top of the Win32 SEH, whereas Java does
not.

Check out http://www.windevnet.com/wdn/webextra/2003/0313/


"Lord Syl" <Lord_member pathlink.com> wrote in message
news:c8ncf8$g3r$1 digitaldaemon.com...
 Hey, I just made a quick test, in order to see method calls' speed.
 When I compared the results to Java's, I found interesting that Java (running
 via JVM) had beaten D in the Try-Catch exception handling speed area, while
 running slow as hell in the rest.

 Here are the results:

 <[D] 500 Million Calls speed test >>

 TryCatched - 13750 ms
 !TryCatched - 1933 ms
 Directly - 1292 ms

 Compiler version is 0.90, with commandline -O -release -inline

 <[Java] 500 Million Calls speed test >>

 TryCatched - 10926 ms
 !TryCatched - 4406 ms
 Directly - 4597 ms

 Using Java VM v1.50 beta from Sun

 Tests were done on a Duron 800(6x133) processor with  640Mb 266Mhz RAM under
 Windows XP.

 [D source code]

 import std.date;
 int main (char[][] args)
 {
 int i, j=-42;
 printf(" ##### 500 Million Calls Speed Test #####\n");
 long START_TC=getUTCtime();
 for (i=0; i<500000000; i++) j=TCcall(i);
 long END_TC=getUTCtime();
 long START=getUTCtime();
 for (i=0; i<500000000; i++) j=Ccall(i);
 long END=getUTCtime();
 long start=getUTCtime();
 for(i=0; i<500000000; i++) j=i+4;
 long end=getUTCtime();
 printf("(TryCatched) Elapsed (ms) : %d\n",(END_TC-START_TC));
 printf("(!TryCatched) Elapsed (ms) : %d\n",(END-START));
 printf("(Directly) Elapsed (ms) : %d\n",(end-start));
 return 0;
 }

 static final int TCcall(int I)
 {
 try
 {
 I+=4;
 return I;
 }
 catch(Error e) { return I; }
 }

 static final int Ccall(int I)
 {
 I+=4;
 return I;
 }

 [Java code]

 public class PointlessSpeedTest
 {
 public static void main (String[] args)
 {
 int i, j=-42;
 System.out.println("##### 500 Million Calls Speed Test #####");
 long START_TC=System.currentTimeMillis();
 for (i=0; i<500000000; i++) j=TCcall(i);
 long END_TC=System.currentTimeMillis();
 long START=System.currentTimeMillis();
 for (i=0; i<500000000; i++) j=Ccall(i);
 long END=System.currentTimeMillis();
 long start=System.currentTimeMillis();
 for(i=0; i<500000000; i++) j=i+4;
 long end=System.currentTimeMillis();
 System.out.println("(TryCatched) Elapsed: "+(END_TC-START_TC)+" ms");
 System.out.println("(!TryCatched) Elapsed: "+(END-START)+" ms");
 System.out.println("(Directly) Elapsed: "+(end-start)+" ms");
 }

 private static int TCcall(int I)
 {
 try
 {
 I+=4;
 return I;
 }
 catch(Exception ex) { return I; }
 }

 private static int Ccall(int I)
 {
 I+=4;
 return I;
 }
 }

May 22 2004
prev sibling next sibling parent "Walter" <newshound digitalmars.com> writes:
There is some overhead in a function added if exception 'catcher' code
exists. This is necessary in order to be compatible with Win32 structured
exception handling. The linux version, however, does not have such overhead
since it is based on static tables (though there is extra overhead based on
the need to use EBP as a frame pointer). I think your sample code overstates
the overhead, as it compares with a trivial function that can be optimized
into two instructions, which is not at all typical of functions which need
to generate exception frames.
May 22 2004
prev sibling parent "Phill" <phill pacific.net.au> writes:
I used the same code and I got a different result than you, which follows:

C:\Documents and Settings\me.ME\Desktop>javac PointlessSpeedTest.java

C:\Documents and Settings\me.ME\Desktop>java PointlessSpeedTest
##### 500 Million Calls Speed Test #####
(TryCatched) Elapsed: 5227 ms
(!TryCatched) Elapsed: 1913 ms
(Directly) Elapsed: 1973 ms

C:\Documents and Settings\me.ME\Desktop>dmd -O -release -inline test.d
c:\dmd\bin\..\..\dm\bin\link.exe test,,,user32+kernel32/noi;

C:\Documents and Settings\me.ME\Desktop>test
 ##### 500 Million Calls Speed Test #####
(TryCatched) Elapsed (ms) : 6410
(!TryCatched) Elapsed (ms) : 911
(Directly) Elapsed (ms) : 611

I have WinXP pro with 256 megs ram and an Athlon 2100.

I will add that when I used to use Java, I used try catch to my advantage,
It saves hassles trying to get the length of an array for example, and you
dont need
to check the bounds at all, so its a bit faster in loops.

But with D's speed and the fantastic foreach it has, none of this is
necessary.

Phill.






"Lord Syl" <Lord_member pathlink.com> wrote in message
news:c8ncf8$g3r$1 digitaldaemon.com...
 Hey, I just made a quick test, in order to see method calls' speed.
 When I compared the results to Java's, I found interesting that Java

 via JVM) had beaten D in the Try-Catch exception handling speed area,

 running slow as hell in the rest.

 Here are the results:

 <[D] 500 Million Calls speed test >>

 TryCatched - 13750 ms
 !TryCatched - 1933 ms
 Directly - 1292 ms

 Compiler version is 0.90, with commandline -O -release -inline

 <[Java] 500 Million Calls speed test >>

 TryCatched - 10926 ms
 !TryCatched - 4406 ms
 Directly - 4597 ms

 Using Java VM v1.50 beta from Sun

 Tests were done on a Duron 800(6x133) processor with  640Mb 266Mhz RAM

 Windows XP.

 [D source code]

 import std.date;
 int main (char[][] args)
 {
 int i, j=-42;
 printf(" ##### 500 Million Calls Speed Test #####\n");
 long START_TC=getUTCtime();
 for (i=0; i<500000000; i++) j=TCcall(i);
 long END_TC=getUTCtime();
 long START=getUTCtime();
 for (i=0; i<500000000; i++) j=Ccall(i);
 long END=getUTCtime();
 long start=getUTCtime();
 for(i=0; i<500000000; i++) j=i+4;
 long end=getUTCtime();
 printf("(TryCatched) Elapsed (ms) : %d\n",(END_TC-START_TC));
 printf("(!TryCatched) Elapsed (ms) : %d\n",(END-START));
 printf("(Directly) Elapsed (ms) : %d\n",(end-start));
 return 0;
 }

 static final int TCcall(int I)
 {
 try
 {
 I+=4;
 return I;
 }
 catch(Error e) { return I; }
 }

 static final int Ccall(int I)
 {
 I+=4;
 return I;
 }

 [Java code]

 public class PointlessSpeedTest
 {
 public static void main (String[] args)
 {
 int i, j=-42;
 System.out.println("##### 500 Million Calls Speed Test #####");
 long START_TC=System.currentTimeMillis();
 for (i=0; i<500000000; i++) j=TCcall(i);
 long END_TC=System.currentTimeMillis();
 long START=System.currentTimeMillis();
 for (i=0; i<500000000; i++) j=Ccall(i);
 long END=System.currentTimeMillis();
 long start=System.currentTimeMillis();
 for(i=0; i<500000000; i++) j=i+4;
 long end=System.currentTimeMillis();
 System.out.println("(TryCatched) Elapsed: "+(END_TC-START_TC)+" ms");
 System.out.println("(!TryCatched) Elapsed: "+(END-START)+" ms");
 System.out.println("(Directly) Elapsed: "+(end-start)+" ms");
 }

 private static int TCcall(int I)
 {
 try
 {
 I+=4;
 return I;
 }
 catch(Exception ex) { return I; }
 }

 private static int Ccall(int I)
 {
 I+=4;
 return I;
 }
 }

May 23 2004