Hello cln-developers and cln-listmoderator, I want to know how it is the correct form to cite cln. 1. first in a paper? 2. in a GNU-software for Linux that uses the library? best regards -- Ms. C. Wilson Castro Rojas Foundations of Informatics Group, Department of Informatics, University of Kaiserslautern, Germany, PO Box: 3049, Building: 34/423, Phone: ++49 631 205 2155, Fax: ++49 631 205 2156,
Hello,
I want to know how it is the correct form to cite cln.
1. first in a paper?
Like in cln/doc/ratseries/paper/binsplit.bib, with updated URL: @UNPUBLISHED{96a, author = "Bruno Haible", title = "{CLN}, a class library for numbers", note = "Available from {\tt http://www.ginac.de/CLN/}", year = "1996"}
2. in a GNU-software for Linux that uses the library?
Bruno Haible, Richard Kreckel: CLN, a class library for numbers. http://www.ginac.de/CLN/ Please don't abbreviate the first names; my name is "Bruno Haible", not "Haible, B.". You can convince TeX to not abbreviate by using braces around the name: "{Haible, Bruno}". Thanks for asking this and giving proper credit! Bruno
A few years back I wrote a little app that uses cln on Linux. I had to override the behavior of read_number_bad_syntax and read_number_junk so that the app wouldn't quit whenever there was a syntax error. I accomplished that with the following code: namespace cln { void read_number_bad_syntax(const char * string, const char * string_limit) { throw 0; } void read_number_junk (const char * string_rest, const char * string, const char* string_limit) { throw 0; } } This worked on Linux. I am trying to port the code now to OS X 10.4 and it doesn't work. The code compiles just fine, but when I run it any syntax error invokes the built-in behavior, i.e. the application quits. Since this worked on Linux I am at a loss to figure out how to fix it on OS X. Any hints would be much appreciated. BTW, is there a reason that the default behavior is to quit rather than throw an exception? Thanks, Ron Garret
Hello, Ron Garret [ex-Erann Gat] wrote:
A few years back I wrote a little app that uses cln on Linux. I had to override the behavior of read_number_bad_syntax and read_number_junk so that the app wouldn't quit whenever there was a syntax error. I accomplished that with the following code:
namespace cln { void read_number_bad_syntax(const char * string, const char * string_limit) { throw 0; } void read_number_junk (const char * string_rest, const char * string, const char* string_limit) { throw 0; } }
This worked on Linux. I am trying to port the code now to OS X 10.4 and it doesn't work. The code compiles just fine, but when I run it any syntax error invokes the built-in behavior
Shared libraries in ELF (like on Linux) and shared libraries on MacOS X work differently. Static libraries work the same. Therefore one solution to your problem is to build CLN as a static library. The resulting executable will then have to be relinked when you upgrade to a new CLN version. But since the executable will only contain _your_ version of read_number_junk, not CLN's original function of the same name, the problem will not occur in this case. Shared libraries on MacOS X work as described in http://developer.apple.com/documentation/DeveloperTools/Conceptual/DynamicLi... http://developer.apple.com/documentation/DeveloperTools/Conceptual/DynamicLi... In section "Symbol exporting strategies" they mention a compiler option: "gcc -weak_library". I would try this option when building CLN as a shared library.
BTW, is there a reason that the default behavior is to quit rather than throw an exception?
When CLN was written, exceptions were not a mature specification nor technology: rethrowing an exception was undefined behaviour, and g++ created huge code when used without "-fno-exceptions". This has probably changed meanwhile... Bruno
On May 12, 2007, at 5:48 AM, Bruno Haible wrote:
Shared libraries in ELF (like on Linux) and shared libraries on MacOS X work differently.
[snip] Thanks!
BTW, is there a reason that the default behavior is to quit rather than throw an exception?
When CLN was written, exceptions were not a mature specification nor technology: rethrowing an exception was undefined behaviour, and g++ created huge code when used without "-fno-exceptions". This has probably changed meanwhile...
OK, but why hard-code a call to exit instead of (say) a user- specifiable callback or something like that? Is cln still being actively maintained? Can I submit a patch? rg
Hi! Ron Garret wrote:
When CLN was written, exceptions were not a mature specification nor technology: rethrowing an exception was undefined behaviour, and g++ created huge code when used without "-fno-exceptions". This has probably changed meanwhile...
OK, but why hard-code a call to exit instead of (say) a user- specifiable callback or something like that?
Is cln still being actively maintained? Can I submit a patch?
Sure you can! Frankly, I would much prefer throwing an exception than the present form of "user specifialble callback". However, I am very curious about the overhead incurred by compiling CLN without -fno-exceptions. If that really turns out to be negligible, I am all for throwing exceptions as that is so much more convenient. I suggest to start looking for the destructor overhead. Best wishes -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
On May 12, 2007, at 12:11 PM, Richard B. Kreckel wrote:
Hi!
Ron Garret wrote:
When CLN was written, exceptions were not a mature specification nor technology: rethrowing an exception was undefined behaviour, and g++ created huge code when used without "-fno-exceptions". This has probably changed meanwhile... OK, but why hard-code a call to exit instead of (say) a user- specifiable callback or something like that? Is cln still being actively maintained? Can I submit a patch?
Sure you can!
Where do I send them?
Frankly, I would much prefer throwing an exception than the present form of "user specifialble callback".
Actually, the present form is not even a user-specifiable callback, it's a hard-coded call to exit.
However, I am very curious about the overhead incurred by compiling CLN without -fno-exceptions. If that really turns out to be negligible, I am all for throwing exceptions as that is so much more convenient. I suggest to start looking for the destructor overhead.
You don't need to compile the whole thing with exceptions enabled, only the parser. (And in fact, I think you don't even have to compile the parser with exceptions enabled, just the error functions. That's basically what I did on Linux by "overriding" their definitions and it seemed to work OK. Of course, I never stress-tested it for memory leaks. Let me do some experiments and I'll report back. rg
Hi! Ron Garret wrote:
Where do I send them?
Feel free to send them to this list.
Actually, the present form is not even a user-specifiable callback, it's a hard-coded call to exit.
Well, it depends on your point of view. I was referring to the entire read_number_bad_syntax function as a form of "user-specifiable callback". :-) Regards -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
On May 12, 2007, at 1:11 PM, Richard B. Kreckel wrote:
Well, it depends on your point of view. I was referring to the entire read_number_bad_syntax function as a form of "user- specifiable callback". :-)
Except that it isn't user-specifiable and it isn't a callback. Other than that there's no problem. rg
On May 12, 2007, at 1:11 PM, Richard B. Kreckel wrote:
Hi!
Ron Garret wrote:
Where do I send them?
Feel free to send them to this list.
OK, here's a minimalist version. It only changes cl_abort.cc: namespace cln { void (*cl_abort_hook)(int) = exit; void cl_abort (void) { cl_abort_hook(1); } } // namespace cln I have tested this on OS X with the following client code: namespace cln { extern void (*cl_abort_hook)(int); void cl_reader_error(int status) { throw status; } } and it works. I have not tested in on Linux, but I have no reason to believe it would behave any differently there. An improved version would replace cl_read_number_XXX with functions that assembled the error message as a string instead of outputting it to cerr, and calling cl_abort_hook with that string, with a default cl_abort_hook that printed the string to cerr and then called exit, but I thought I'd start with the smaller version just to test the waters. This patch is small enough that it probably doesn't matter, but for future reference, what is the preferred format for submitting patches? diff? diff -e? diff -n? Can I send a darcs patch? rg
Hi! On 2007-05-12 22:33 CEST, Ron Garret wrote:
On May 12, 2007, at 1:11 PM, Richard B. Kreckel wrote:
Well, it depends on your point of view. I was referring to the entire read_number_bad_syntax function as a form of "user- specifiable callback". :-)
Except that it isn't user-specifiable and it isn't a callback. Other than that there's no problem.
Ron, what happened to your sense of humor? Overriding the function is certainly user-specifiable and the entire thing is kind of a "callback" if you are willing to accept that the function to call is specified at link time rather than at run time. That's why I was putting double quotes and a smile there. But never mind. :-/ On 2007-05-13 22:01 CEST Ron Garret wrote:
OK, here's a minimalist version. It only changes cl_abort.cc:
namespace cln {
void (*cl_abort_hook)(int) = exit;
void cl_abort (void) { cl_abort_hook(1); }
} // namespace cln
I have tested this on OS X with the following client code:
namespace cln { extern void (*cl_abort_hook)(int); void cl_reader_error(int status) { throw status; } }
and it works. I have not tested in on Linux, but I have no reason to believe it would behave any differently there.
An improved version would replace cl_read_number_XXX with functions that assembled the error message as a string instead of outputting it to cerr, and calling cl_abort_hook with that string, with a default cl_abort_hook that printed the string to cerr and then called exit, but I thought I'd start with the smaller version just to test the waters.
This may solve your problem but, in practice, how useful is it? I am imagining some Linux distribution where CLN is compiled with -fno-exceptions and a naive user is specifiying cl_reader_error to be called instead of exit. I haven't checked but I'm sure this will incur undefined behavior: a crash, a memory leak, you name it. So, to be safe, the library will have to be compiled with exceptions enabled. But what is the advantage of providing such a callback then? I don't think anyone will do anything but throw exceptions from it! But then it will be better to throw well-specified exceptions directly. The real question that I would like to see answered is how much overhead is incurred by exceptions. If it is negligible, I propose to define a couple of exception classes and throw these instead of calling cl_abort. The exception classes could be subtypes of std::runtime_error, because catching these is frequently used as a last resort. Let's have a look at the overhead before deciding on an interface.
This patch is small enough that it probably doesn't matter, but for future reference, what is the preferred format for submitting patches? diff? diff -e? diff -n? Can I send a darcs patch?
Any diff with context such that I can apply it using patch is fine. Best -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
On May 13, 2007, at 3:42 PM, Richard B. Kreckel wrote:
Hi!
On 2007-05-12 22:33 CEST, Ron Garret wrote:
On May 12, 2007, at 1:11 PM, Richard B. Kreckel wrote:
Well, it depends on your point of view. I was referring to the entire read_number_bad_syntax function as a form of "user- specifiable callback". :-) Except that it isn't user-specifiable and it isn't a callback. Other than that there's no problem.
Ron, what happened to your sense of humor?
I had a sense of humor? ;-)
Overriding the function is certainly user-specifiable
It is? How?
and the entire thing is kind of a "callback" if you are willing to accept that the function to call is specified at link time rather than at run time. That's why I was putting double quotes and a smile there. But never mind. :-/
Sorry to be a killjoy, but I think I'm genuinely missing something here. Overriding the behavior of these functions at link time would be perfectly fine with me, but the whole point of my original posting is that on OS X it doesn't seem to work (unless you recompile the library, but I think it would be worthwhile to get this to work with a standard installation).
On 2007-05-13 22:01 CEST Ron Garret wrote:
OK, here's a minimalist version. It only changes cl_abort.cc: namespace cln { void (*cl_abort_hook)(int) = exit; void cl_abort (void) { cl_abort_hook(1); } } // namespace cln I have tested this on OS X with the following client code: namespace cln { extern void (*cl_abort_hook)(int); void cl_reader_error(int status) { throw status; } } and it works. I have not tested in on Linux, but I have no reason to believe it would behave any differently there.
An improved version would replace cl_read_number_XXX with functions that assembled the error message as a string instead of outputting it to cerr, and calling cl_abort_hook with that string, with a default cl_abort_hook that printed the string to cerr and then called exit, but I thought I'd start with the smaller version just to test the waters.
This may solve your problem but, in practice, how useful is it? I am imagining some Linux distribution where CLN is compiled with - fno-exceptions and a naive user is specifiying cl_reader_error to be called instead of exit. I haven't checked but I'm sure this will incur undefined behavior: a crash, a memory leak, you name it.
So, to be safe, the library will have to be compiled with exceptions enabled. But what is the advantage of providing such a callback then? I don't think anyone will do anything but throw exceptions from it!
But then it will be better to throw well-specified exceptions directly.
The real question that I would like to see answered is how much overhead is incurred by exceptions. If it is negligible, I propose to define a couple of exception classes and throw these instead of calling cl_abort. The exception classes could be subtypes of std::runtime_error, because catching these is frequently used as a last resort.
Let's have a look at the overhead before deciding on an interface.
Sounds reasonable to me. Empirically I can tell you that it doesn't crash. It might, however, result in a memory leak. I haven't tested that. (To be clear, my libcln is built using the default settings, which I presume means it was built with -fno-exceptions.) rg
Ron Garret wrote:
An improved version would replace cl_read_number_XXX ...
Indeed, this is what is most in the spirit of how CLN was designed. The doc says: CLN aims at being easily integrated into larger software packages: * The library provides hooks for memory allocation and exceptions. The hooks for memory allocation are documented in <cln/malloc.h>, but those for the exceptions are not realized in the same way. I agree with you; the following functions should be realized through hooks in the same way: cl_abort cl_error_division_by_0 cl_as_error cl_notreached_abort read_number_bad_syntax read_number_eof read_number_junk uninitialized_ring uninitialized_error cl_error_floating_point_nan cl_error_floating_point_overflow cl_error_floating_point_underflow cl_ash_error cl_error_exquo possibly even _all_ occurrences of cl_abort. Richard B. Kreckel wrote:
I am imagining some Linux distribution where CLN is compiled with -fno-exceptions and a naive user is specifiying cl_reader_error to be called instead of exit. I haven't checked but I'm sure this will incur undefined behavior: a crash, a memory leak, you name it.
It will be a memory leak. Like when you use longjmp to abort a computation.
I propose to define a couple of exception classes and throw these instead of calling cl_abort.
So, to be safe, the library will have to be compiled with exceptions enabled. But what is the advantage of providing such a callback then? I don't think anyone will do anything but throw exceptions from it!
Good point. Just to think a bit further: Assume someone creates a C binding of CLN - this is a requirement brought up by RMS (such a thing existed a long time ago, but was unfortunately made with a proprietary ILOG tool) - how would the exception handling look like? Will it be a longjmp? Will it be a C++ exception handler? Bruno
On May 13, 2007, at 4:55 PM, Bruno Haible wrote:
Ron Garret wrote:
An improved version would replace cl_read_number_XXX ...
Indeed, this is what is most in the spirit of how CLN was designed. The doc says:
CLN aims at being easily integrated into larger software packages: * The library provides hooks for memory allocation and exceptions.
The hooks for memory allocation are documented in <cln/malloc.h>, but those for the exceptions are not realized in the same way.
I agree with you; the following functions should be realized through hooks in the same way: cl_abort cl_error_division_by_0 cl_as_error cl_notreached_abort read_number_bad_syntax read_number_eof read_number_junk uninitialized_ring uninitialized_error cl_error_floating_point_nan cl_error_floating_point_overflow cl_error_floating_point_underflow cl_ash_error cl_error_exquo possibly even _all_ occurrences of cl_abort.
It surprises me to learn that numerical errors abort as well. I conjecture that munging the source code is a common mode of deploying CLN in real applications.
Richard B. Kreckel wrote:
I am imagining some Linux distribution where CLN is compiled with -fno-exceptions and a naive user is specifiying cl_reader_error to be called instead of exit. I haven't checked but I'm sure this will incur undefined behavior: a crash, a memory leak, you name it.
It will be a memory leak. Like when you use longjmp to abort a computation.
Even for parser errors? It is not a foregone conclusion that anything will have been allocated on the heap, and the parser routines are standalone, are they not? i.e. none of the other CLN code will ever invoke the parsing code, right?
I propose to define a couple of exception classes and throw these instead of calling cl_abort.
That would work for me, however...
So, to be safe, the library will have to be compiled with exceptions enabled. But what is the advantage of providing such a callback then? I don't think anyone will do anything but throw exceptions from it!
Good point.
Just to think a bit further: Assume someone creates a C binding of CLN - this is a requirement brought up by RMS (such a thing existed a long time ago, but was unfortunately made with a proprietary ILOG tool) - how would the exception handling look like? Will it be a longjmp? Will it be a C++ exception handler?
If it were me, I'd write the wrapper in C++ with functions declared extern "C" that catch all exceptions and do something else with them. But that's just me. I can think of at least two other approaches. Neither of these would be my first choice, but they wouldn't require exceptions: 1. Return some kind of NaN-like thing when there's an error. 2. Return an undefined value on error, and have a global (or per- thread) flag that gets set when an error occurs. The second one is inferior from an architectural point of view, but is almost certainly easier to implement. Personally, I strongly prefer exceptions, but that's just because they work well for my particular application. rg
Bruno Haible wrote:
Richard B. Kreckel wrote:
I am imagining some Linux distribution where CLN is compiled with -fno-exceptions and a naive user is specifiying cl_reader_error to be called instead of exit. I haven't checked but I'm sure this will incur undefined behavior: a crash, a memory leak, you name it.
It will be a memory leak. Like when you use longjmp to abort a computation.
I thought so, too. But over here it crashes. It seems like Ron is making the same experience.
So, to be safe, the library will have to be compiled with exceptions enabled. But what is the advantage of providing such a callback then? I don't think anyone will do anything but throw exceptions from it!
Good point.
Just to think a bit further: Assume someone creates a C binding of CLN - this is a requirement brought up by RMS (such a thing existed a long time ago, but was unfortunately made with a proprietary ILOG tool) - how would the exception handling look like? Will it be a longjmp? Will it be a C++ exception handler?
I would suggest to whoever is going to write those that exceptions are caught in the C binding layer and transformed to return codes, messages, errno, or whatever inside that layer. -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Richard B. Kreckel wrote:
I would suggest to whoever is going to write those that exceptions are caught in the C binding layer and transformed to return codes, messages, errno, or whatever inside that layer.
Agreed. It's the only way to provide a binding layer that does not lose memory each time an exceptional situation occurs. Bruno
Bruno Haible wrote:
I agree with you; the following functions should be realized through hooks in the same way: cl_abort cl_error_division_by_0 cl_as_error cl_notreached_abort read_number_bad_syntax read_number_eof read_number_junk uninitialized_ring uninitialized_error cl_error_floating_point_nan cl_error_floating_point_overflow cl_error_floating_point_underflow cl_ash_error cl_error_exquo possibly even _all_ occurrences of cl_abort.
I'm proceeding with the convertion to throwing exceptions. However, I'm feeling unconfident with some of them. Many of the cl_abort calls should really be assertions IMO. Is there a point throwing at a code section that cannot possibly be reached, except when someone seriously screws up CLN? One of the most striking examples is the definition of CL_DEFINE_CONVERTER in include/cln/object.h. The conditional there could even be written as a compile-time assertion! When I'm finished, I would really welcome a short review of the patch. Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Hello Richy, Richard B. Kreckel wrote:
I'm proceeding with the convertion to throwing exceptions. However, I'm feeling unconfident with some of them. Many of the cl_abort calls should really be assertions IMO. Is there a point throwing at a code section that cannot possibly be reached, except when someone seriously screws up CLN?
You're right, "not reached"/"internal error"/"assertion" are a different type of situation: here the culprit is inside CLN. How to signal this situation? - through abort()? - through throw internal_error(...)? I don't like abort() in the context of CLN, since it would create huge coredumps (1 GB is not rare), and eating that much of a user's disk is simply not nice. Therefore I'm in favour of an exception class that can be used for "not reached"/"internal error"/"assertion".
One of the most striking examples is the definition of CL_DEFINE_CONVERTER in include/cln/object.h. The conditional there could even be written as a compile-time assertion!
Yes, please make it a compile-time assertion! if (sizeof(*this) != sizeof(target_class)) cl_abort(); becomes typedef int verify_size_in_CL_DEFINE_CONVERTER[2*(sizeof(*this)==sizeof(target_class))-1]; Also, there is the documented use of cl_abort in the manual, section "Debugging support". How can we keep this functionality, i.e. have a way to put a breakpoint in a single place, so that the program execution stops there after any CLN exception is constructed but before it is thrown? Does "break __cxa_throw" work? If not, it can be done by defining an empty function cl_exception_breakpoint(){} and calling this function at the end of the constructor of every concrete CLN exception class. Bruno
Hi Bruno, Bruno Haible wrote:
You're right, "not reached"/"internal error"/"assertion" are a different type of situation: here the culprit is inside CLN.
How to signal this situation? - through abort()? - through throw internal_error(...)? I don't like abort() in the context of CLN, since it would create huge coredumps (1 GB is not rare), and eating that much of a user's disk is simply not nice. Therefore I'm in favour of an exception class that can be used for "not reached"/"internal error"/"assertion".
The Linux distributions I work with set the soft limit for maximum size of core files created to zero, i.e. no core files are created unless the user explicitly specifies another ulimit. So, if a user produces cores it is because he wanted so. So why bother?
Also, there is the documented use of cl_abort in the manual, section "Debugging support". How can we keep this functionality, i.e. have a way to put a breakpoint in a single place, so that the program execution stops there after any CLN exception is constructed but before it is thrown? Does "break __cxa_throw" work? If not, it can be done by defining an empty function cl_exception_breakpoint(){} and calling this function at the end of the constructor of every concrete CLN exception class.
Right, the backtrace is very important in order to track down problems and putting a breakpoint in the catch clause is too late, because by then the stack has been rewound. I'm no gdb expert, but this appears to be working: rbk@wallace:~$ g++ -v Using built-in specs. Target: i486-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++,ada,treelang --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --program-suffix=-4.1 --enable-__cxa_atexit --enable-clocale=gnu --enable-libstdcxx-debug --enable-mpfr --with-tune=i686 --enable-checking=release i486-linux-gnu Thread model: posix gcc version 4.1.2 20060715 (prerelease) (Debian 4.1.1-9) rbk@wallace:~$ gdb -v GNU gdb 6.4.90-debian Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i486-linux-gnu". rbk@wallace:~$ cat foo.cc #include <iostream> using namespace std; void f() { throw 42; } int main() { try { f(); } catch(const int& n) { cerr << n << endl; } return 0; } rbk@wallace:~$ g++ -g foo.cc rbk@wallace:~$ gdb ./a.out GNU gdb 6.4.90-debian Copyright (C) 2006 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1". (gdb) l 3 4 void f() 5 { 6 throw 42; 7 } 8 9 int main() 10 { 11 try { 12 f(); (gdb) b 12 Breakpoint 1 at 0x804887c: file foo.cc, line 12. (gdb) run Starting program: /home/rbk/a.out Failed to read a valid object file image from memory. Breakpoint 1, main () at foo.cc:12 12 f(); (gdb) catch throw Catchpoint 2 (throw) (gdb) cont Continuing. Catchpoint 2 (exception thrown) 0xb7f7e4d5 in __cxa_throw () from /usr/lib/libstdc++.so.6 (gdb) bt #0 0xb7f7e4d5 in __cxa_throw () from /usr/lib/libstdc++.so.6 #1 0x0804886a in f () at foo.cc:6 #2 0x08048881 in main () at foo.cc:12 (gdb) Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Richard B. Kreckel wrote:
Let's have a look at the overhead before deciding on an interface.
Well, this is benchmarks/timebench2b with 100 decimal digits and oodles of repetitions on i386 Linux, GCC 4.1: static 29m12s static, -fno-exceptions 29m21s shared 30m12s shared, -fno-exceptions 31m57s Dunno if this is so sensitive, but it appears like turning on -fno-exceptions makes the shared library slightly slower. Interesting. -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Richard B. Kreckel wrote:
I am very curious about the overhead incurred by compiling CLN without -fno-exceptions.
Here is some data. Compiled cln-1.1.13 on Linux/i386 once with CXX="g++ -fno-exceptions" and once with CXX="g++" (both with GCC 4.1.2), and performed two deterministic programs, measuring user time: g++ -fno-exceptions g++ ./exam 1.24 sec 1.35 sec ./pi 100000 > /dev/null 2.64 sec 2.64 sec As was to be expected, the program which spends most of its time in large bignum multiplications is not slowed down. But the program which constructs many numbers and performs many (quick) computations is slowed down. Is a slowdown of 9% significant? Bruno
I ran these benchmarks on a MacBook pro (but compiling in 32-bit mode). First, I would like to correct an earlier claim: I thought that -fno- exceptions was the default configuration, but it's not. When I specify -fno-exceptions and try to use a callback that throws an exception I get a bus error. The benchmark results: pi 100000 takes 1.23 seconds with or without -fno-exceptions exam takes 0.337 seconds without -fno-exceptions, 0.331 seconds with. It appears to me that with gcc4, -fno-exceptions has reached the point of diminishing returns. rg On May 13, 2007, at 4:32 PM, Bruno Haible wrote:
Richard B. Kreckel wrote:
I am very curious about the overhead incurred by compiling CLN without -fno-exceptions.
Here is some data. Compiled cln-1.1.13 on Linux/i386 once with CXX="g++ -fno-exceptions" and once with CXX="g++" (both with GCC 4.1.2), and performed two deterministic programs, measuring user time:
g++ -fno-exceptions g++
./exam 1.24 sec 1.35 sec ./pi 100000 > /dev/null 2.64 sec 2.64 sec
As was to be expected, the program which spends most of its time in large bignum multiplications is not slowed down. But the program which constructs many numbers and performs many (quick) computations is slowed down.
Is a slowdown of 9% significant?
Bruno
_______________________________________________ CLN-list mailing list CLN-list@ginac.de https://www.cebix.net/mailman/listinfo/cln-list
On May 14, 2007, at 12:39 PM, Ron Garret wrote:
First, I would like to correct an earlier claim: I thought that - fno-exceptions was the default configuration, but it's not. When I specify -fno-exceptions and try to use a callback that throws an exception I get a bus error.
Meta-correction: it's an "abort trap", not a bus error. rg
Ron Garret wrote:
On May 14, 2007, at 12:39 PM, Ron Garret wrote:
First, I would like to correct an earlier claim: I thought that - fno-exceptions was the default configuration, but it's not. When I specify -fno-exceptions and try to use a callback that throws an exception I get a bus error.
Meta-correction: it's an "abort trap", not a bus error.
What's that? Sounds like an unhandled exception to me. -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Ron Garret wrote:
On May 14, 2007, at 12:39 PM, Ron Garret wrote:
First, I would like to correct an earlier claim: I thought that - fno-exceptions was the default configuration, but it's not. When I specify -fno-exceptions and try to use a callback that throws an exception I get a bus error.
Meta-correction: it's an "abort trap", not a bus error.
What's that? Sounds like an unhandled exception to me.
That's exactly what happens with uncaught exceptions (the throw `escaped' all the way out of the run-time). Not sure if every system reports it as an abort trap, but at least OS X does. Fang
On May 14, 2007, at 1:48 PM, Richard B. Kreckel wrote:
Ron Garret wrote:
On May 14, 2007, at 12:39 PM, Ron Garret wrote:
First, I would like to correct an earlier claim: I thought that - fno-exceptions was the default configuration, but it's not. When I specify -fno-exceptions and try to use a callback that throws an exception I get a bus error. Meta-correction: it's an "abort trap", not a bus error.
What's that? Sounds like an unhandled exception to me.
Nope. It's the same client code in both cases, and it handles the exceptions. But when cln is compiled with -fno-exceptions it does this: Ciel: c Illegal number syntax: "c" terminate called after throwing an instance of 'int' Abort trap [ron@mickey:~/devel/ciel]$ I have no idea what is actually going on under the hood here. I don't write much C++ code and this is the first time I've ever seen this. rg
Hi! I did an experiment with CLN 1.1.13. I configured it without GMP and set CXXFLAGS to -O2 at one time and to "-O2 -fno-exceptions" another time. The library was built on two diffent hosts, one 32 bit and one 64 bit. Both shared and static libraries were built. I then ran the three benchmarks on each of the libraries: 100*exam: time for i in $(seq 0 100); do ./tests/exam >/dev/null; done 100k*tb2b: time ./benchmarks/timebench2b -r 100000 &>/dev/null pi 1M: time ./examples/pi 1000000 >/dev/null I've disabled cron and did not touch anything while the benchmarks were running. The results are listed below. An asterisk indicates that the library was built with -fno-exceptions added to CXXFLAGS. AMD Opteron 870 2GHz, x86_64 Linux, GCC 4.1 (intDsize=64): size 100*exam 100k*tb2b pi 1M static, 4.1M 21.81s 47.52s 9.68s static, *) 3.6M 19.87s 46.84s 9.68s shared, 1.7M 21.86s 47.76s 9.68s shared, *) 1.5M 21.91s 47.66s 9.69s AMD Athon 64, 1.8GHz, i386 Linux, GCC 4.1 (intDsize=32): size 100*exam 100k*tb2b pi 1M static, 3.1M 31.24s 81.15s 9.25s static, *) 2.6M 31.01s 81.21s 9.18s shared, 1.6M 39.79s 91.44s 9.29s shared, *) 1.3M 37.64s 87.79s 9.28s It appears that it depends on the architecture whether a shared or a static library takes a small performance plunge when exceptions are turned on. The highest performance hit is 9% for the exam test on x86_64 with the static library. That benchmark is the most sensitive one because, as Bruno has already noticed, it constructs and destructs many not-so-big numbers. The fact that pi appears slow on x86_64 is due to missing assembler. This changes dramatically when CLN is configured with GMP. Bruno Haible wrote:
Is a slowdown of 9% significant?
Well, it depends on whom we ask and when. As you know, the GCC folks are willing to risk security holes for 9% performance gain on some benchmarks but then have no qualms releasing a compiler which is 40% slower on other benchmarks solely because some patches did not make it for the release. Strange world. Ron Garret wrote:
It appears to me that with gcc4, -fno-exceptions has reached the point of diminishing returns.
I am inclined to agree. -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
Richard B. Kreckel wrote:
AMD Opteron 870 2GHz, x86_64 Linux, GCC 4.1 (intDsize=64): size 100*exam 100k*tb2b pi 1M static, 4.1M 21.81s 47.52s 9.68s static, *) 3.6M 19.87s 46.84s 9.68s shared, 1.7M 21.86s 47.76s 9.68s shared, *) 1.5M 21.91s 47.66s 9.69s
AMD Athon 64, 1.8GHz, i386 Linux, GCC 4.1 (intDsize=32): size 100*exam 100k*tb2b pi 1M static, 3.1M 31.24s 81.15s 9.25s static, *) 2.6M 31.01s 81.21s 9.18s shared, 1.6M 39.79s 91.44s 9.29s shared, *) 1.3M 37.64s 87.79s 9.28s
Thanks for these timings. I'm now convinced that it's worth throwing exceptions and dropping support for -fno-exceptions. These worst-case 10% are acceptable. Bruno
On May 14, 2007, at 3:00 PM, Bruno Haible wrote:
Thanks for these timings. I'm now convinced that it's worth throwing exceptions and dropping support for -fno-exceptions. These worst- case 10% are acceptable.
We're in violent agreement. I am probably not the right person to do this unless someone wants to hold my hand. I don't do much C++ coding, and I'm almost certain to screw it up at least a few times. rg
Ron Garret wrote:
Thanks for these timings. I'm now convinced that it's worth throwing exceptions and dropping support for -fno-exceptions. These worst- case 10% are acceptable.
We're in violent agreement.
Unfortunately, my time is very limited. But I'm planning to transform the aborting functions one-to-one to throw statement. Much like the (untested) patch attached does for read_number_bad_syntax, read_number_eof, and read_number_junk. Unless someone raises objections, I'll proceed in the same way with cl_abort, cl_error_division_by_0, cl_as_error, cl_notreached_abort, uninitialized_ring, uninitialized_error, cl_error_floating_point_nan, cl_error_floating_point_overflow, cl_error_floating_point_underflow, cl_ash_error, cl_error_exquo, and maybe others. I don't think there will be an impressive exception class hierarchy. Deriving all input exceptions from one common base makes sense, though. Maybe it would also be useful to derive all CLN exceptions from one common base, which is in turn derived from std::runtime_error. But that should be enough, I think. Ron, the patch should work for your input routines. How does it work for you? It will take me at least two weeks till I can check in a complete patch to CVS HEAD (a.k.a. CLN 1.2-pre.) -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
On May 17, 2007, at 3:52 PM, Richard B. Kreckel wrote:
Ron, the patch should work for your input routines. How does it work for you?
Like a charm, except for one thing. This code snippet: class out_of_range {}; extern out_of_range range_exception; now results in this error (referring to the second line): error: 'out_of_range' does not name a type This used to work, and if I rename out_of_range to Out_of_range then it works again. So it appears that you made some change to the include file that makes this break, but I can't for the life of me figure out what it might be since nothing even remotely resembling the string "out_of_range" appears anywhere in cln/*.h. C++ can be quite the infuriating programming language. rg
Ron Garret wrote:
Like a charm, except for one thing. This code snippet:
class out_of_range {}; extern out_of_range range_exception;
now results in this error (referring to the second line):
error: 'out_of_range' does not name a type
This used to work, and if I rename out_of_range to Out_of_range then it works again. So it appears that you made some change to the include file that makes this break, but I can't for the life of me figure out what it might be since nothing even remotely resembling the string "out_of_range" appears anywhere in cln/*.h.
Well, std::out_of_range is an exception type pulled in from the <stdexcept> header via include/cln/number_io.h.
C++ can be quite the infuriating programming language.
Such things happen. Grep for eksplicit in the CLN sources. :-) -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
On May 17, 2007, at 10:57 PM, Richard B. Kreckel wrote:
Ron Garret wrote:
Like a charm, except for one thing. This code snippet: class out_of_range {}; extern out_of_range range_exception; now results in this error (referring to the second line): error: 'out_of_range' does not name a type This used to work, and if I rename out_of_range to Out_of_range then it works again. So it appears that you made some change to the include file that makes this break, but I can't for the life of me figure out what it might be since nothing even remotely resembling the string "out_of_range" appears anywhere in cln/*.h.
Well, std::out_of_range is an exception type pulled in from the <stdexcept> header via include/cln/number_io.h.
Ah, that would explain it. But why would it say that out_of_range is not a type rather than complain that it is being redefined? (Feel free to treat that as a rhetorical question.) rg
Richard B. Kreckel wrote:
Ron Garret wrote:
Thanks for these timings. I'm now convinced that it's worth throwing exceptions and dropping support for -fno-exceptions. These worst- case 10% are acceptable.
We're in violent agreement.
Unfortunately, my time is very limited. But I'm planning to transform the aborting functions one-to-one to throw statement. Much like the (untested) patch attached does for read_number_bad_syntax, read_number_eof, and read_number_junk.
Unless someone raises objections, I'll proceed in the same way with cl_abort, cl_error_division_by_0, cl_as_error, cl_notreached_abort, uninitialized_ring, uninitialized_error, cl_error_floating_point_nan, cl_error_floating_point_overflow, cl_error_floating_point_underflow, cl_ash_error, cl_error_exquo, and maybe others.
I don't think there will be an impressive exception class hierarchy. Deriving all input exceptions from one common base makes sense, though. Maybe it would also be useful to derive all CLN exceptions from one common base, which is in turn derived from std::runtime_error. But that should be enough, I think.
A few minutes ago, I've committed a patch to the main branch that gets rid of all those nonreturning functions and instead throws exceptions of type cln::runtime_exception or derived. runtime_exception is in turn derived from std::runtime_error and inherits the .what() member function which can be used to query the cause of the exception. Here is the current hierarchy of exception types (with corresponding previous nonreturning functions in parenthesis): runtime_exception (was roughly: cl_abort) +- division_by_0_exception (was: cl_error_division_by_0) +- as_exception (was: cl_as_error) +- notreached_exception (was: cl_notreached_abort) +- uninitialized_exception (was: uninitialized_error) +- uninitialized_ring_exception (was: uninitialized_ring) +- exquo_exception (was: cl_error_exquo) +- ash_exception (was: cl_ash_error) +- floating_point_exception | +- floating_point_nan_exception (was: cl_error_floating_point_nan) | +- floating_point_overflow_excption (was: cl_error_floating_point_overflow) | `- floating_point_underflow_exception (was: cl_error_floating_point_underflow) `- read_numger_exception +- read_number_bad_syntax_exception (was: read_number_bad_syntax) +- read_number_junk_exception (was: read_number_junk) `- read_number_eof_exception (was: read_number_eof) Cheers -richy. -- Richard B. Kreckel <http://www.ginac.de/~kreckel/>
participants (5)
-
Bruno Haible
-
David Fang
-
Richard B. Kreckel
-
Ron Garret
-
Wilson Castro