Exception check optimization
Hi, I wonder why is __pyx_filename (in exception check blocks) tracked dynamically? AFAIK it's impossible to split function body between multiple files (include only works at the top level), which makes filename a compile time constant for any given function. If the above is correct, __pyx_filename variable can be eliminated, saving at least 5 bytes per exception check (more on x64). On a related note, why is c_lineno enabled by default? So far I have only found one pretty rare case when it is useful - debugging autogenerated code in module init. I suspect that most people don't bother turning it off and get suboptimal code. Best regards, Nikita Nemkin
On Sun, May 26, 2013 at 10:04 AM, Nikita Nemkin <nikita@nemkin.ru> wrote:
Hi,
I wonder why is __pyx_filename (in exception check blocks) tracked dynamically? AFAIK it's impossible to split function body between multiple files (include only works at the top level), which makes filename a compile time constant for any given function.
If the above is correct, __pyx_filename variable can be eliminated, saving at least 5 bytes per exception check (more on x64).
Probably because exception checks are heavy-weight enough that we haven't bothered optimizing them at this level yet.
On a related note, why is c_lineno enabled by default? So far I have only found one pretty rare case when it is useful - debugging autogenerated code in module init.
Well, it used to be much more useful back when Cython was less mature.
I suspect that most people don't bother turning it off and get suboptimal code.
Again, raising exceptions is heavy-weight enough that I don't think this is a significant performance issue. These days we certainly could consider turning it off, because it is often irrelevant and a deviation from how exceptions look in Python. - Robert
On Thu, 30 May 2013 08:25:55 +0600, Robert Bradshaw <robertwb@gmail.com> wrote:
On Sun, May 26, 2013 at 10:04 AM, Nikita Nemkin <nikita@nemkin.ru> wrote:
Hi,
I wonder why is __pyx_filename (in exception check blocks) tracked dynamically? AFAIK it's impossible to split function body between multiple files (include only works at the top level), which makes filename a compile time constant for any given function.
If the above is correct, __pyx_filename variable can be eliminated, saving at least 5 bytes per exception check (more on x64).
Probably because exception checks are heavy-weight enough that we haven't bothered optimizing them at this level yet.
By "exception checks" I mean these things: if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;} They are fast, but the problem is the extra code: neither __pyx_filename nor __pyx_clineno assignments are necessary. Removing them reduces binary size by 2-3%. If you're OK with it, I'll make a patch that removes __pyx_filename and disables __pyx_clineno by default. Best regards, Nikita Nemkin
Am 30.05.2013 14:38, schrieb Nikita Nemkin:
On Thu, 30 May 2013 08:25:55 +0600, Robert Bradshaw wrote:
On Sun, May 26, 2013 at 10:04 AM, Nikita Nemkin wrote:
I wonder why is __pyx_filename (in exception check blocks) tracked dynamically? AFAIK it's impossible to split function body between multiple files (include only works at the top level), which makes filename a compile time constant for any given function.
What about includes? Are they allowed inside of functions? If not, then this sounds like a safe assumption. If they are allowed, then it should still be possible to special case the file name setting, i.e. set it to the default at function entry and only set it to a different value if it happens to change inside of a function. The C compiler should often (normally?) be smart enough to eliminate the constant assignment.
If the above is correct, __pyx_filename variable can be eliminated, saving at least 5 bytes per exception check (more on x64).
Probably because exception checks are heavy-weight enough that we haven't bothered optimizing them at this level yet.
By "exception checks" I mean these things:
if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
They are fast, but the problem is the extra code: neither __pyx_filename nor __pyx_clineno assignments are necessary. Removing them reduces binary size by 2-3%.
If you're OK with it, I'll make a patch that removes __pyx_filename and disables __pyx_clineno by default.
I'm fine with both. I consider seeing the C line a debug feature that people shouldn't need normally. Stefan
participants (3)
-
Nikita Nemkin -
Robert Bradshaw -
Stefan Behnel