- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Longjmp is loooooooooong!
Admin
Uh.... why did you even need to test which would be faster? A for loop compiles to a test and branch. A longjmp compiles to a freaking function call, one that has to inspect data structures and modify the return address on the stack.
Admin
If I had used long jump, maybe I could have been First!
Admin
Admin
People who write assembly code or setjmp like in this example in C for speed purposes are disregarding 30 years of work in field of compiler optimization. The better You can describe what You want to compiler, the better it optimizes.
Admin
I've used longjmp in a unit test harness, to bail from an entire test suite if one of the test case asserts fails. libpng also uses it, longjmping back to a location in your code if it encounters an error while reading an image. I think of longjmp as more akin to throwing an exception than a goto.
Also, to make sure your test is valid, you'll want to enable compiler optimization with -O3 or similar. I tried compiling your examples (after changing getch() to getchar()) with -O0 and -O3, and interestingly, it made no perceptible difference for the longjmp test, though it sped up the no_longjmps test greatly. So not only is the longjmp version a lot slower, it also isn't as optimizable.
Admin
Your code's no good! In no_longjmps.c, you're not even considering the amazing nuclear powers of longjmp(), while longjmp.c has gone to great lengths to make sure it finds a suitable place for it.
Admin
Oh, and TRWTF is to be still using that valuable antique from the prehistoric DOS era, getch(), in the 21st century. (Does it still overflow your application's stack by trying to read all the available console input events in one go when you've just cut and pasted a couple of hundred kB of text into the window?)
Admin
Admin
I see three major WTFs here:
longjmp - the point of the article, complete WTF; Daren - loves longjmp and can't actually spell his own name correctly; Mark Bowytz - willing Vista user.
WTF??
Admin
Admin
nexus:~> gcc -o test2 -O3 no_longjmps.c /tmp/cceJVp2k.o: In function
main': no_longjmps.c:(.text+0x154): undefined reference to
getch' collect2: ld returned 1 exit statusRemoving the getch() I get
7.472s for longjmps.c, 0.308s for no_longjmps.c
(Linux on Sparc 900MHz)
Admin
However: a linear algorithm ALWAYS outperforms a quadratic one, and compilers don't change algorithms ;)
Admin
In your 'fast' version, wouldn't it be better to eliminate the extra if-condition?
Admin
Admin
Unreadable, WTF code:
Nice, clean code, easier to read:
(sorry about multiple empty lines, I couldn't figure out how to remove them)
The for statement has a nice syntax, why don't people stick to it? It's better to say "loop i from 0 until just before sales count" than "i is zero and you should loop, break out of the loop if i is not less than sales count, add values to subtotal and if i is still less than sales count, increment it." It's a lot easier to understand what's happening when the conditions are explained just before the loop, instead of having to find them yourself after your brain suffers from a neurological fracture(just coined that) after trying to process this statement "for(;;){" You could have used a while loop, it would have made a bit more sense... but NOOOOOO, people like you have to use for(;;){ instead of while(i<sales->count){ because it's much cooler to write incomprehensible code.
And that's how you use "for" loops in C-like languages. And that's also why you should use them as the gods designed them.
Remember, each "for(;;){" statement you write will give you 10 hacker points but it will also decrease your penis size by a tenth of an inch, and if you're a girl, it will decrease your breast size to 95% of what you had just before starting to write "for(;;){".
Admin
The real WTF is of course that the original developer failed to realize setjmp is horribly broken; he should have added a #DEFINE setjmp somewhere else, preferably in a file called reinventingwheel.h
Admin
Admin
The real WTF is that people still use C. A decent compiler would optimise both examples so there would be no difference.
/flamebait
Admin
Admin
TRWTF is that Mark needed a whole IDE to compile a simple one-file program. ;=]
And getch(), obviously.
Admin
Sure, a for loop is faster, but i'm amazed how many people fail to see that longjmp is so much more enterprisey...
Admin
I can easily imagine how the coder found longjmp() to be faster : if his original version called calculate() in lieu of longjmp() (using recursion, where a sane programmer would use a loop), he'd potentially build a huge call stack, that was more cpu-intensive to handle than a setjmp/longjmp.
That said, longjmp can be the right tool for the job, but usually for low-level stuff. I remember using it in a shell for some kinds of error recovery.
Admin
the real wtf is that the author didn't consider the fact that the compiler might have optimized away all the loops in the non-longjmp version, making it not loop at all.
Admin
setjmp/lonjjmp is a library solution to exception handling, given that C doesn't have any kind of intrinsic exception handling, like try/catch.
What setjmp/longjmp DOES is, generally speaking, what the compiler does when it sees a try/catch. Except, of course, that a language construct, like try/catch, isn't subject to such abuse as a library soluction, as this WTF illustrates so well.
Admin
[quote=JW] Library code is often faster than "user-optimized code", because the compiler can apply optimizations at the level of CPU/platform-dependent calls. [/quote]
I read these comments and it makes me realize you're all a bunch of C#/Java babies. None of you get close to the real the machine. Hence the rage expressed by Alex and myself. You are all ignorant goobers and I don't know how to make you less ignorant.
At least the goober at the top, who lacked knowledge of longjmp bothered to benchmark it and LEARN something (he should've read the man page, it would've alleviated the need for a benchmark).
Admin
I can see where goto can be useful...especially if the task is OS code...but long jump? where can a thing like this be useful?
The guys who make these instructions are smart...not dumb...can anyone think of a case where it can help?
Admin
Admin
Might be a regional/country thing, but what does that even mean?
Admin
Admin
I remember in my operating systems class in university we used longjmp to simulate things like hardware interrupts and context switches and stuff for our toy os. Outside of that, and for exception handling code, I have never seen longjmp used in any way that did anything useful except cause wtfs like this.
Admin
I've been using C since the mid 80's and I thought I was pretty good at it. Mostly mixed C and assembly in micro-controllers. If I ever knew about this command, I've forgotten about it. So guess I learned something today.
Admin
I like the text saving define of RETURN_NOTHING which is so much shorter than return;
Admin
Admin
The longjmp must prevent some handy compiler optimizations. The compiler obviously writes faster code! Remember "premature optimization is the root of all evil" -Donald Knuth
Admin
goto is problematic because it is difficult for multiple people to maintain (especially when they don't talk to each other or understand each other's code or comments), and this can lead to leaked resources and incorrect logic. longjmp() has the same problem, but the damage is not limited to a single function. It's a much bigger bomb. With careful planning and execution, it can demolish a hillside to build a road, but one screw-up will make it demolish the work crew instead.
Admin
When I saw longjmp the first thing I though of was the long jump module in Half-Life. Take notice kids, video games will rot your brain...
Admin
Nobody has commented on the minor-WTF RETURN_NOTHING macro, so I thought I should fill the void.
Admin
What's a 'Man Page'? I can't find it on my Start menu.
Admin
Almost all 'C' compilers turn off optimization for the entire function, and sometimes the entire file, when it encounters a setjmp or longjmp. This is likely to be the major cause of the performance delay.
Over 20 years ago, I worked on a project that had one longjmp/setjmp pair. The application was an interpreter and there was no 'C++' and no exceptions. Lacking exceptions, this was a good way of handling errors. That was then.
Addendum (2009-01-12 12:24): For extra credit, post a working application of a longjmp that crosses threads. :-)
Admin
Aren't you confusing this with gets()? I don't see the implied buffer overflow vulnerability in a function that reads a single character.
If I remember correctly, (and I'm too lazy to check) getch is (sometimes?) an unbuffered getchar(), useful for real-time probing of user input.
Admin
I think you mean, "reinventingwhl.h", or "reinvntwhl.h".
Why programmers don't just go ahead and add that one extra vowel when talking naming, well, anything is beyond me. I've read papers and blogs on variable names and overhead, but I would rather be able to maintain code without worrying about creating another variable because I missed a vowel than "make the code faster" by leaving out a vowel or two.
Admin
[quote user="Why is DailyWTF more like DailyWTFWTF"][quote=JW] Library code is often faster than "user-optimized code", because the compiler can apply optimizations at the level of CPU/platform-dependent calls. [/quote]
I read these comments and it makes me realize you're all a bunch of C#/Java babies. None of you get close to the real the machine.[/quote]
Ok, I normally disagree when people say that, but we are talking about C here, you don't use it except when you need low level programming, so... I second that! No library will be as optimized and trimmed to your application as your own code.
Now, about the WTF, and answering to Bob (238533). No optimizer can work well with goto statements. Most of optimizing theory simply stops being useful when you start using it.
Admin
"Most C developers have not incorporated it into their everyday activities", I think.
Admin
Implementing co-operative threading / co-routines is one example (not that it'd be a smart thing to do if you expect people to understand your code) - you can achieve that by having a yield() function that keeps track of the current thread, and uses setjmp() to save its state in a struct, then schedules the next thread and longjmp()'s to it. Using signals you can even do preemptive threading that way, and there are (old) thread packages that actively worked that way.
Not something that's very useful today when anything but toy OS's or tiny embedded systems will have proper thread support.
Admin
I am long-jumping out of these comments.
Admin
Wow - what's up with the snark? Lolcats are stupid, yes. It's okay to laugh at them. That's what they're for.
But I'd never seen longjmp() before - it looks moderately useful in specific instances, but dear god, can it be abused.
Admin
Admin
setjmp/longjmp can be immensely useful in some cases where you're nested very deeply and need to back out say ten levels. Like when you're in a compiler and detect an error when reading the next character. Without an inter-function goto you'd have to pass an error code back up ten levels, checking for it and returning yet another error code up many times over.
But using it within a function is bizarre. A plain "goto" would do. And be much faster. setjmp/longjmp have to save and restore all the volatile machine registers, a slow operation on some CPUs.
Admin