Am Sat, 08 Feb 2014 14:01:12 -0800
schrieb Walter Bright <[email protected]>:

> On 2/7/2014 8:40 AM, Dmitry Olshansky wrote:
> > Meh. If exceptions are such a liability we'd better make them (much) faster.
> 
> They can be made faster by slowing down non-exception code.
> 
> This has been debated at length in the C++ community, and the generally 
> accepted 
> answer is that non-exception code performance is preferred and exception 
> performance is thrown under the bus in order to achieve it.
> 
> I think it's quite a reasonable conclusion.

Am Sat, 08 Feb 2014 21:31:53 -0800
schrieb Walter Bright <[email protected]>:

> On 2/8/2014 9:00 PM, Marco Leise wrote:
> > The reasons for slow exceptions in D could be the generation
> > of stack trace strings or the garbage collector instead of
> > inherent trade offs to keep the successful code path fast.
> 
> Sigh, once again,
> 
> 1. It is not the collector
>
> 2. I've implemented it both ways, I know what I'm talking about. You can see 
> the 
> fast exception way in the Win32 code generation, and the slow way in the 
> Linux 
> code generation.

Ok, I'm on Linux which should be inherently slower at
throwing exceptions as you say. So I've written a little test
and it shows two things:
1. You are right, about the collector. It is not the
bottleneck.
2. It doesn't have anything to do with trading speed for the
   successful code path either.

I called two functions recursively until a nesting depth of
1000. The first version allocates a new exception, the second
one reuses an existing exception. At the call site I caught
the exception. I did this 10_000 times in a loop.
[The code is attached.]

Even at this nesting depth the second version still
outperformed the first one by a factor of ~200(!) and all
the CPU time (>98%) was is spent somewhere in libc.

Using static exceptions (or similarly in C++: throwing
literal strings) is VERY fast in D already and I see no reason
to improve that at the moment.

So I repeat my point:

The reasons for slow exceptions in D could be the generation
of stack trace strings or anything else other than some
inherent trade offs to keep the successful code path fast.

-- 
Marco
import core.time;
import std.stdio;

enum iter = 10_000;
enum maxDepth = 1000;

int main(string[] args)
{
	int sum;
	string text = args.length >= 2 ? args[1] : "Hello World";
	{
		auto t1 = TickDuration.currSystemTick;
		foreach (i; 0 .. iter)
		{
			try
			{
				newException(text);
			}
			catch (Exception e)
			{
				sum += e.line;
			}
		}
		auto t2 = TickDuration.currSystemTick;
		writefln("New exception needs %s µs per iteration", (t2-t1).nsecs / 1_000 / iter);
	}
	{
		auto t1 = TickDuration.currSystemTick;
		foreach (i; 0 .. iter)
		{
			try
			{
				staticException(text);
			}
			catch (Exception e)
			{
				sum += e.line;
			}
		}
		auto t2 = TickDuration.currSystemTick;
		writefln("Static exception needs %s µs per iteration", (t2-t1).nsecs / 1_000 / iter);
	}
	return sum;
}

void newException(string text, size_t depth = 1)
{
	if (depth < maxDepth)
		newException(text, depth + 1);
	else
		throw new Exception(text);
}

Exception se;

void staticException(string text, size_t depth = 1)
{
	if (depth < maxDepth)
		staticException(text, depth + 1);
	else
		throw se ? se : (se = new Exception(text));
}

Reply via email to