Comment On Longjmp - FOR SPEED!!!

For those who don't know, there is a standard C header called setjmp.h that defines two methods: longjmp() and setjmp(). The longjmp works just like a goto statement in C in that, when executed, the program jumps to another pre-defined point in the code, defined by a setjmp. However, where goto is limited to the current, local scope, longjmp can span outside of the current scope and across functions. [expand full text]
« PrevPage 1 | Page 2 | Page 3 | Page 4Next »

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:11 • by DaveK
Longjmp is loooooooooong!

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:11 • by Alex (unregistered)
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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:18 • by monkeyPushButton (unregistered)
If I had used long jump, maybe I could have been First!

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:23 • by Jimbo (unregistered)
238518 in reply to 238515
DaveK:
Longjmp is loooooooooong!
Grow up already you sad little boy.

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:24 • by Konrads (unregistered)
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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:25 • by adiener (unregistered)
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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:25 • by rohypnol
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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:25 • by DaveK
238522 in reply to 238516
Alex:
Uh.... why did you even need to test which would be faster?
I think Mark was showing how a professional approaches these sorts of implementation decisions.
Alex:
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.
Yes, it may be obvious, but apparently it wasn't obvious enough for the guy who wrote the WTF in the first place; and the point of doing the demonstration is to illustrate that, regardless of what is or isn't obvious, assumptions can be tested and measured, and if he had done so he wouldn't have written such a dumb bit of code.

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?)

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:26 • by DaveK
238523 in reply to 238518
Jimbo:
DaveK:
Longjmp is loooooooooong!
Grow up already you sad little boy.
Lighten up, you boring old fogey!

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:29 • by Anonymous (unregistered)
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??

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:31 • by DaveK
238525 in reply to 238520
adiener:
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.
That's possibly even more appropriate than you think; on some platforms it's the basic mechanism used to implement exceptions.
adiener:

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.
Makes sense. The major part of the overhead in longjmp/setjmp is saving and restoring the entire execution context (setting up empty stack frames and calling the function takes very little in comparison), and regardless of optimisation there's an absolute minimum time it takes just to dump that many bytes from CPU to memory. (All those SSE registers make for hundreds of bytes of loads and stores...)

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:32 • by magi (unregistered)
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 status

Removing the getch() I get

7.472s for longjmps.c,
0.308s for no_longjmps.c

(Linux on Sparc 900MHz)

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:33 • by JW (unregistered)
238527 in reply to 238519
Konrads:
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.

I totally agree. Library code is often faster than "user-optimized code", because the compiler can apply optimizations at the level of CPU/platform-dependent calls.

However: a linear algorithm ALWAYS outperforms a quadratic one, and compilers don't change algorithms ;)

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:35 • by CodeReviewer (unregistered)
In your 'fast' version, wouldn't it be better to eliminate the extra if-condition?

void
calculate(struct salesinfo*sales){
int i = 0;

for(;;) {
if (!(i<sales->count))
RETURN_NOTHING;
else
{
addvaluetosubtotal(sales->values[i]);
i++;
}
}
}

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:37 • by dkf
238529 in reply to 238516
Alex:
A for loop compiles to a test and branch.
No. A 'goto' becomes just a branch, and is very fast on modern computers. The test would be part of an 'if'...

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:37 • by rohypnol
Unreadable, WTF code:
    int i = 0;

for(;;) {
if (!(i<sales->count))
RETURN_NOTHING;
addvaluetosubtotal(sales->values[i]);
if (i<sales->count){
i++;
}
}

Nice, clean code, easier to read:
int i;

for (i = 0; i < sales->count; ++i)
{
addvaluetosubtotal(sales->values[i]);
}
RETURN_NOTHING;

(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(;;){".

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:38 • by YDD (unregistered)
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

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:39 • by dkf
238532 in reply to 238527
JW:
Library code is often faster than "user-optimized code", because the compiler can apply optimizations at the level of CPU/platform-dependent calls.
Theoretically so, but in practice library code is faster because libraries are usually written by people who know what they are doing (e.g. by avoiding bubblesort...)

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:41 • by Bob (unregistered)
The real WTF is that people still use C. A decent compiler would optimise both examples so there would be no difference.

/flamebait

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:45 • by Andy Goth
#define ABS_ZERO (1-1)
???

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:46 • by Spectre
TRWTF is that Mark needed a whole IDE to compile a simple one-file program. ;=]

And getch(), obviously.

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:48 • by virgil (unregistered)
Sure, a for loop is faster, but i'm amazed how many people fail to see that longjmp is so much more enterprisey...

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:48 • by moltonel (unregistered)
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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:48 • by tulcod (unregistered)
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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:48 • by Daniel (unregistered)
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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:49 • by Why is DailyWTF more like DailyWTFWTF (unregistered)
[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).

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:56 • by vinnybad (unregistered)
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?

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:57 • by Anonymous (unregistered)
238544 in reply to 238540
Why is DailyWTF more like DailyWTFWTF:
<snipped rubbish>
No, you're a towel.

Re: Longjmp - FOR SPEED!!!

2009-01-12 09:59 • by Bobbo (unregistered)

... most C developers have not brought it in their everyday.


Might be a regional/country thing, but what does that even mean?

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:06 • by DaveK
238547 in reply to 238540
Why is DailyWTF more like DailyWTFWTF:
JW:

Library code is often faster than "user-optimized code", because the
compiler can apply optimizations at the level of CPU/platform-dependent calls.


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.
Goober yerself, goober! I've written perfectly hand-scheduled superscalar assembly when I've wanted to push a machine to the metal, but I don't bother doing it for strcmp every time I start coding on a new platform because someone's already done the actual benchmarking and profiling for me. Work smarter, not harder - NIH syndrome is the real WTF!

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:09 • by captncraig (unregistered)
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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:11 • by Dirk Diggler (unregistered)
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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:12 • by jackalope (unregistered)
I like the text saving define of RETURN_NOTHING which is so much shorter than return;


Re: Longjmp - FOR SPEED!!!

2009-01-12 10:13 • by Why is DailyWTF more like DailyWTFWTF (unregistered)
238551 in reply to 238547
DaveK:
Why is DailyWTF more like DailyWTFWTF:
JW:

Library code is often faster than "user-optimized code", because the
compiler can apply optimizations at the level of CPU/platform-dependent calls.


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.
Goober yerself, goober! I've written perfectly hand-scheduled superscalar assembly when I've wanted to push a machine to the metal, but I don't bother doing it for strcmp every time I start coding on a new platform because someone's already done the actual benchmarking and profiling for me. Work smarter, not harder - NIH syndrome is the real WTF!
Did you squeeze that in between posting pictures of cats on anonymous message boards frequented exclusively by 14 year old school kids? Yeah, right. Once you leave school you'll learn some real skills, hopefully.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:16 • by Anonymous Coward (unregistered)
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

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:18 • by Andy Goth
238553 in reply to 238543
vinnybad:
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?
It's hardly ever needed. Think about the cases where goto is helpful. One major use for goto is to abort the execution of a deeply nested loop in case of error or trivial success (e.g. search complete). What if the looping construct is so complex that it spans many functions? If the looping depth is dynamically determined, a function call is pretty much required--- either that or restructure the algorithm. In this case, longjmp() takes the place of goto for performing an early exit, when it's prohibitive to put early exit detection and support code around every function invocation. Other cases exist, but it's hard to fathom situations where it isn't necessary to perform frame-by-frame stack unwinding along the way.

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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:25 • by DOA
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...

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:25 • by Shai (unregistered)
Nobody has commented on the minor-WTF RETURN_NOTHING macro, so I thought I should fill the void.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:30 • by WinGuy (unregistered)
238558 in reply to 238540
Why is DailyWTF more like DailyWTFWTF:

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).


What's a 'Man Page'? I can't find it on my Start menu.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:30 • by Rick
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. :-)

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:33 • by fluffy777
238560 in reply to 238522

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?)


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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:36 • by Pope
238561 in reply to 238531
YDD:
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


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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:37 • by Mcoder
238562 in reply to 238540
[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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:37 • by emurphy
238563 in reply to 238545
Bobbo:

... most C developers have not brought it in their everyday.


Might be a regional/country thing, but what does that even mean?


"Most C developers have not incorporated it into their everyday activities", I think.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:40 • by Vidar (unregistered)
238564 in reply to 238553
Andy Goth:

In this case, longjmp() takes the place of goto for performing an early exit, when it's prohibitive to put early exit detection and support code around every function invocation. Other cases exist, but it's hard to fathom situations where it isn't necessary to perform frame-by-frame stack unwinding along the way.


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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:41 • by Charles400
I am long-jumping out of these comments.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:46 • by anonymous_coder() (unregistered)
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.

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:48 • by Sir Twist
238568 in reply to 238530
rohypnol:
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){

No, "for(;;)" is used for endless looks because "while (1)" makes the MSVC compiler complain "warning C4127: conditional expression is constant."

Re: Longjmp - FOR SPEED!!!

2009-01-12 10:49 • by grg (unregistered)
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.


Re: Longjmp - FOR SPEED!!!

2009-01-12 10:51 • by Anonymous Cowherd (unregistered)
238570 in reply to 238527
JW:
However: a linear algorithm ALWAYS outperforms a quadratic one, and compilers don't change algorithms ;)

Uhm. No. A linear algorithm outperforms a quadratic algorithm for sufficiently large n. Sufficiently large n is highly variable. If you're sorting less than ten items, for example, the fastest algorithm is generally one of the old, primitive quadratic versions. Many good 'qsort' implementations don't use qsort at all once they get down to dealing with small ranges of items.
« PrevPage 1 | Page 2 | Page 3 | Page 4Next »

Add Comment