How are exceptions actually implemented in assembly?

Bengt Richter bokr at oz.net
Thu Jan 24 18:21:48 EST 2002


On Thu, 24 Jan 2002 17:37:06 +0000, Jonathan Hogg <jonathan at onegoodidea.com> wrote:

>On 23/1/2002 22:06, in article a2nc5d$75a$1 at panix2.panix.com, "Aahz Maruch"
><aahz at panix.com> wrote:
>
>> In article <mailman.1011809616.25217.python-list at python.org>,
>> hungjunglu <hungjunglu at yahoo.com> wrote:
>>> 
>>> [...] Python exception
>>> handling is at much higher level, and it charges this cost at that
>>> level. Not too bad, in a sense, since the underlying C code does not
>>> necessarily have to propagate the exception handling all the way down
>>> to assembly. But, it also means that at Python level, exception is
>>> built into everywhere. That's OK, I guess... compared to other things
>>> (e.g: variable name look up), exception handling is probably pretty
>>> cheap in resources/performance.
>> 
>> Note carefully that the cost comes almost entirely during the handling
>> of exceptions, not in setting up exception blocks.  So if as a
>> percentage of instructions executing exceptions are rare, it's a very
>> small penalty.
>
>On the contrary, I think the original explanation is most accurate. The cost
>of exception handling in Python is pretty much O(n) in the number of Python
>"instructions" executed in total.
ISTM Aahz was pointing out that typical handling of an actual exception is
'way more expensive than deciding whether it needed to be handled -- not
saying a gazillion decisions won't cost more than typical exception handlings
may add up to, especially if they happen very seldom or not at all.

I suppose you could eliminate the checking altogether in the normal path
if you use an "int n" instruction on x86, to break out of a path of execution
like a hardware interrupt when you raise an exception, but it might not be
so easy to do portably.

>
>At each point that a C call returns in the interpreter (or extension
>modules), the return pointer is checked to see if it is NULL (indicating an
>exception) and appropriate error handling is invoked if it is - usually just
>returning from the current function with NULL, i.e., unwinding the stack.
>
>Thus a constant is added to the cost of every Python instruction. This
>constant is small (the cost of a register-equal-to-zero and a
>not-taken-conditional-branch) but still there.
>
OTOH, we are long past the time when CPUs got their instructions one by one
directly from main memory. These days, it's hard to say whether any given
hypothesized instruction execution cost will wind up invisible behind a wait
for memory access.

>Thus, Python exception handling is indeed "built into everywhere". You pay a
>penalty for Python having exceptions rather than a penalty for choosing to
>use them.
I'm sure there's a penalty, but I'm not sure how much of the time it's paid
in the shadow of a bigger wait penalty. Optimization should make a big
difference. I wonder if the interpreter has ever been built with "__fastcall"
or pascal calling conventions.

>
>[And yes, in comparison to all the other overhead of a dynamic interpreted
>language it is very cheap.]
Definitely**.

**that's almost beginning to look wrong, having seen "definately" so much ;-/

Regards,
Bengt Richter




More information about the Python-list mailing list