-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sjlj vs dwarf. Why should be sjlj preferred over dwarf (especially for C code) #20
Comments
See also an earlier discussion in issue #4 . For Windows 64-bit SEH was chosen over SJLJ because it is the native Windows exception handling and winlibs aims to be as native as possible. It also has less overhead. Considering the reality of what people actually want by looking at the downloads from old builds at: I don't like the idea of offering both SJLJ and Dwarf or SEH downloads because then a lot of users have no idea what they should be downloading. One reason is that winlibs.com has further plans to make a build ecosystem with thousands of packages, and offering the choise would imply all (C++) packages would need to be built in all the variations of GCC (32-bit/64-bit, Dwarf/SEH/SJLJ) Can you tell me if there are examples of any open source packages that don't build with non-SJLJ exception handling GCC? |
I understand your position, and what you are saying it is true, but consider the following case. It is up to you how do you produce your releases I just wrote down my opinion, and some facts about dwarf. |
Thank you for your insights. To check this I took the C program Mbrowse which - together with all of its dependancies - I built with my 32-bit compiler (which used Dwarf exception handling). |
Sorry to interfere, but I felt like joining the party.
gendef fbclient.dll
dlltool --dllname fbclient.dll --input-def fbclient.def --output-lib libfbclient.dll.a --kill-at And if you try to link to that generated
Thanks for your understanding. |
for tomay3000 thanks for your intervention. You hit the nail on the head when you mentioned the possible crash issues with DWARF on Windows. I know about this aspect (I read about that), but forgot to tell. My opinion is that for 32-bit C code SJLJ should be used. Why? SEH is not available for 32-bit. C can't use DWARF exception handling plus (maybe useless to say when the previous statement is true) DWARF bloats C code. |
You guys give compelling arguments. You convinced me. I was never really a fan of Dwarf, but chose it because talking to the end-users seemed to point in its direction. In an ideal world there would be SEH support for Windows 32-bit in GCC. Unfortunately I believe this was initially not started due to patent issues. These issues no longer exist, but attempts to start GCC support for SEH for the MinGW i386 platform didn't really take off (see: https://gcc.gnu.org/legacy-ml/gcc-help/2008-02/msg00117.html). For my next build I will look into switching GCC for 32-bit Windows to SJLJ exception handling, but as I also try to build a matching LLVM/CLang I will also need to look into how it's supported over there. I will keep this issue open to inform you how things are going. |
Dear brechtsanders, please dont abandon DWARF version for 32b. Limitation of DWARF is well-know, however it better than SJLJ by lot of reasons. I have C++ soft which running data acquisition for 365x24x7, linked for 3+ hardware drivers of various vendors, including monstrous NI VISA, and never observed any "crash issues with DWARF" (with SJLJ also, but I dropper it as soon as first versions of MinGW with DWARF support appeared). Dear ZsoltKantor, size of the empty main exe is ~13K (gcc-8.1.0). You can check it using "-O2 -static -s" options, which are more or less usual for "Release". |
I also read (including here: https://stackoverflow.com/questions/15670169/what-is-difference-between-sjlj-vs-dwarf-vs-seh) that SJLJ makes execution a lot slower. It's advantage is mainly interoperation with other libraries that have nocall-stack unwinding information, which is not a goal of winlibs.com, see the winlibs philosophy statement for more information. Does anybody know more about the future of SEH support in GCC for Windows 32-bit? |
I`m afraid that there are no future. It requires sufficient intervention in gcc code: "Note that 32-bit SEH is stack-based and requires code-generation" . So someone with proper skills has to do it, but x86 32b mainly considered as deprecated, and to find such person is not easy business. |
I suppose keeping the 3 of em ( TIA. |
For the winlibs.com project the idea for the future is to have a whole ecosystem of packages all build with the same compiler. |
Could somebody provide an example code of dwarf exception handling to see how it works in practice? |
Surprising results when timing try-catch exception handling in 32-bit code. Used gcc 7.3.0 32-bit dwarf and sjlj compiler The test code is: int main(void) I've used python time function to measure elapsed time of the do-while loop. I made the configuration in the gdbinit file, so the time measurement starts when GDB is started. python from time import time As I read everywhere sjlj should be slower, but what I measured is the opposite Average execution time for dwarf: 4.461 seconds Somebody else should also try this with different gcc versions for 32-bit P.S. Avg time dwarf: 3.885 sec. |
Dear ZsoltKantor, low efficiency of the sjlj is well-defined issue, see for example https://sourceforge.net/p/mingw-w64/mailman/message/30532139/
produce output like
|
nenin-sc, shouldn't you compare SJLJ vs DWARF code ? Or it can be that my tests are wrong . . . |
Made further tests comparing sjlj with dwarf (using gcc 7.3.0 though), The code used for testing is below. Compile command used: g++ except.cpp -s -Wall |
Your code produced: 6.192514s on gcc version 8.1.0 (i686-win32-dwarf-rev0, Built by MinGW-W64 project) Thread model: win32 , win7 64b i7-4700S |
Test code updated. Test parameters can be controlled via macros.
it is better to compare the two gcc variants - I will do a test with Brecht's gcc 9.3.0 compiler |
Test results Compiler: gcc 9.3.0 32-bit 1000000 loops, average calculated from 6 runs, compiled to throw exceptions 900000000 loops, average calculated from 6 runs, compiled to don't throw exceptions |
It must not be slower i7-4700S by 4 times. Or it can? When you are using c++ you can enjoy expressions like this: Likely you need to try throw exception out of function, which was called from different compilation module. |
it makes no relevance the CPU speed if you provide both results (
from the tests point of view the code change is useless.
That can be done. But you must to remember that
I'm not interested in nenin-sc : Thank you for the provided ideas! P. S. |
|
I have to emphasize: the goal of winlibs is not have the best option for interoperability with modules compiled with other C/C++ compilers, but rather to have the best performance and stability. |
I understand. The best performance between Updated test code Compiler: MingW-W64 gcc 7.3.0 32-bit posix 1000000 loops, average calculated from 6 runs, compiled to throw exceptions 900000000 loops, average calculated from 6 runs, compiled to not throw exceptions |
Dear tomay3000
You can look at GoldenDict, for example. Dear ZsoltKantor
in C++ this is a piece of language: http://www.cplusplus.com/doc/tutorial/exceptions/ and there are no other options. |
Hello nenin-sc, thanks for the reply! |
Dear ZsoltKantor, |
nenin-sc: 2004-2006? That was a long time ago. I think from 2006 until now software and hardware evolved a lot, so those . . . old tests are not really relevant now. To install a MingW gcc compiler it takes at most 5 minutes. You download, extract the archive and eventually add the bin directory to the PATH variable - if you have only one compiler. If you have more - as in my case, create a cmd file for every compiler and you configure the PATH there (I have 4 gcc versions installed). |
I think this battle is lost from the beginning because we live in a world where people do just follow and don't study, and there is nothing we can do about it :(
-Finally, If I decide to to build a recent Thanks. |
@tomay3000 I have ported over 1800 sources to Windows using my winlibs.com personal build, so please stay tuned for those packages in the future. I'm working on the package manager, after that I should be ready to release. I'm not trying to replace MSYS2 - in fact I use it myself as a shell to build everything - but my goal is to build an environment that follows certain principles. |
Dear tomay3000 ,
|
That's why I try to provide the winlibs.com personal build as a simple folder to be extracted.
I use MinGW-w64 mostly from Code::Blocks for developing and from the MSYS2 shell for porting or compiling sources that come with makefiles or configuration scripts (autotools, cmake, meson, ...) About testing, it may be best to compare apples with apples, so I'm have built both Dwarf/SEH and SJLJ versions of gcc-10.1.1-snapshot20200627 for MinGW-w64. You can find them at: |
@nenin-sc
With this statement I quite disagree. For Cygwin I consider that to be true, but MinGW-w64 really does build native Windows libraries. Of course they call functions in the operating system's libraries, but the binaries really can be run on another Windows without shipping any additional dependancies (apart from C/C++ shared runtimes, but this can be solved by statically linking). |
nenin-sc is a little bit impertinent. Please block it if it continues with offensive comments. Otherwise I will close the issue. One more comment from nenin-sc, and I close the issue, it is up to you brechtsanders if you open it again. I'm not here to hear somebody's disgracing words. |
I will test the new snapshots. |
@brechtsanders P.S. |
Hi, I'm still working on the gdb backspace issue, and I believe I found a solution. I will look into i686-posix-dwarf-gcc-10.1.1-snapshot20200627 to see what went wrong... |
Juist built the latest snapshot in all EH variants: https://github.com/brechtsanders/winlibs_mingw/releases/tag/10.1.1-snapshot20200704-7.0.0 . |
Thank you, backspace in GDB is working now. It displays on one line the previous commands used, appending the text one after the other. Related to the exceptions, do you think it makes any sense to write a simple dll that throws exceptions and use that dll in one exe to check exception time? I think it is useless, I think C++ library exceptions do exactly the same thing. P.S. |
I can't reproduce the command history issue with https://github.com/brechtsanders/winlibs_mingw/releases/tag/10.2.0-11.0.0-9.0.0-r5 . Is it ok for you now too? Your exception question is beyond the scope of what winlibs.com is trying to do. Maybe you should pose that question on https://stackoverflow.com/ ? |
Oh man, I read the whole thread, even the arrogant comments from the other dude and @ZsoltKantor didn't conclude with his findings :O !!! You can't leave us hanging like that after building so much suspens :P. @ZsoltKantor Did you try at least your original bench just to see ? I would love to have an answer just to see if things changed compare to all these reports that I am sure were right but with their own context. I will try too when I will have some time to burn in the upcoming months (yeah, I am super hyper busy lately) and do a whole comprehensive test with your tailored builds @brechtsanders. |
If it was up to me I would go SEH all the way because it is native to Windows, which improves compatibility and interoperability. Building SJLJ releases separately would be a lot of extra work for me, and looking at the number of downloads from |
Do you have more info why it is available for 64bit but not for 32bit? |
As explained in #4 SEH isn't in GCC yet due to some non-tech reasons such as patents. To check the real reason and current status you would need to check with the GCC development team. |
Sadly I've missed the explanation part and only have seen a guess "seems like" and a "likely not, patent expired". |
I have no information about this, even though I would also very much like to see 32-bit SEH support. |
32 bit SEH will most likely newer get added to gcc. Reason is that sjlj uses allmost the same mechanism (both rely on code injection) so it would not really net us any benefits. I known of some person http://blog.davidegrayson.com/2016/02/windows-32-bit-structured-exception.html who made a test case library providing SEH to 32 bit gcc but the code was newer accepted upstream. |
@ZsoltKantor your benchmark measures an irrelevant quantity With sjlj every |
wont say it is that bad in most cases sjlj is actually faster than dwarf when an exception is thrown and just a tiny bit slower when not :) not sure how big an impact a 32 bit SEH exception model would impose but i reckon it might be about the same. |
How slow "just a bit slower" exactly is? Let's measure it!
Notice that this program actually does not throw any exceptions (the condition is always false). First I'll compile and run it with distro (cross-) compiler, which uses dwarf: i686-w64-mingw32-gcc -O2 -o except_bench_dwarf.exe except_bench.cc
cp -a /usr/lib/gcc/i686-w64-mingw32-gcc/lib*.dll .
perf stat wine except_bench_dwarf.exe The result is
Next I'll use a home-brew (cross) compiler with sjlj exceptions (which is the default) /opt/mingw-sjlj/bin/i686-w64-mingw32-gcc -O2 -o except_bench_sjlj.exe except_bench.cc
cp /opt/mingw-sjlj/lib/gcc/i686-w64-mingw32/lib*.dll .
perf stat wine except_bench_sjlj.exe This gives
which is more than 30x slower ( What gives? Let's look at the asm: /opt/mingw-sjlj/bin/i686-w64-mingw32-gcc -O2 -save-temps -o except_bench_sjlj.exe except_bench.cc
cp except_bench.s except_bench_sjlj.s
Roughly speaking every function with And this is what
Here the data necessary to handle an exception (in particular to unwind the stack) is collected at the compile time (and stored into |
That's a good check. Which GCC version was used exactly? While most programs should not expect a lot of exceptions... as you already have that setup: ... and, as this was the main part of the original point: what time differences does it show with "plain c"? |
i was wondering myself ? since i anticipated a C example. But can you even use try catch in C ?. |
no seems try catch wont work with C :S only setjmp / longjmp or goto's (evil thingies xD) you can emulate them though its not very nice to look at. |
There are no exceptions in standard C (C89/C99/C11). Hence dwarf/sjlj choice is irrelevant for a pure C code. |
indeed so the only thing we need be aware of are the extra sections added by dwarf in the libraries. |
Hello to everybody!
I will provide some info about sjlj and I can also give some arguments supporting the idea that gcc sjlj variants should be released.
The sjlj functionality is specified in the C standard from C90 upwards.
sjlj is described by the standard as a functionality to make jumps in the code from one function to the other (goto can do jumps only in the current function).
Also if somebody works only with C code dwarf exception handling is probably useless, because as I know only C++ code can use dwarf exceptions. In fact the C programming language does not even has the idea of exception handling. SJLJ is implemented in the C standard as a method to jump in the code, to do "long jumps", but not as an exception handling mechanism. It is true that using the sjlj functionality, an exception handling mechanism can be implemented, so an exception handling emulation can be done with C code.
Also if you work with pure C code dwarf is a waste of space and code execution.
Compiled C code with a dwarf enabled compiler inserts extra sections in the code + does extra function calls.
So the code size will increase and there is no gcc option to completely exclude dwarf sections and code from the final binary.
The gcc dwarf compiler inserts 4 functions in you code from which one it is even called despite you don't use exception handling in your program. This extra function call is GetModuleHandleA() which is called every time in a dwarf enabled program before the main function is called.
So my opinion and conclusion is that gcc variants with sjlj should be released for newer gcc compilers also (e.g. 10.1.0) because if somebody writes code only in the C language the sjlj variant is preferred over dwarf which, remember adds no benefits to C code.
The text was updated successfully, but these errors were encountered: