views:

2940

answers:

17

If something is making a single-thread program take, say, 10 times as long as it should, you could run a profiler on it. You could also just halt it with a "pause" button, and you'll see exactly what it's doing. Even if it's only 10% slower than it should be, if you halt it more times, before long you'll see it repeatedly doing the unnecessary thing. Usually the problem is a function call somewhere in the middle of the stack that isn't really needed. This doesn't measure the problem, but it sure does find it.

Edit: The objections mostly assume that you only take 1 sample. If you're serious, take 10. Any line of code causing some percentage of wastage, like 40%, will appear on the stack on that fraction of samples, on average. Bottlenecks (in single-thread code) can't hide from it.

+16  A: 

Doing this manually can't really be called "quick" or "effective", but there are several profiling tools which do this automatically; also known as statistical profiling.

JesperE
The devil's in the details. It's not just taking samples that matters, it's what get recorded and how it is summarized. You need to record the entire call stack on each sample. Then you need for each statement (not function, statement) in the samples, what fraction of samples does it appear on.
Mike Dunlavey
and you need to take the samples when it matters, not when hanging for user input.
Mike Dunlavey
I'm sure you're right.
JesperE
> You need to record the entire call stack on each sampleThere are sampling profilers which do this, and they are very useful. One recent addition into the Windows family: Xperf (Vista required)http://blogs.msdn.com/pigscanfly/archive/2008/02/09/xperf-a-new-tool-in-the-windows-sdk.aspx
Suma
I'm glad they are finally coming around to doing that. I hope they are also raising the visibility of the statistic that I think matters most - fraction of samples containing each statement (in the interval of interest). Too bad you need Vista.
Mike Dunlavey
Use OS X. The Activity Viewer has this facility built right in. Very handy.
Thorbjørn Ravn Andersen
+17  A: 

Because sometimes it works, and sometimes it gives you completely wrong answers. A profiler has a far better record of finding the right answer, and it usually gets there faster.

Paul Tomblin
Beg to differ. If a statement shows up on X% of N samples, then if you can get rid of it you'll save X% of time. Of course, if N is big, you'll know X with more precision, but who cares?
Mike Dunlavey
@mike you'd be surprised by how many people care. people have full time jobs working on or using profiling software. in many firms and applications it is critical and when the landscape gets big @Paul is on the money.
dove
Timing it before and after gives plenty accuracy.
Mike Dunlavey
In the sort of programs I'm working on, I'd have to hit pause about a thousand times before I got any meaningful results.
Paul Tomblin
Paul, we should get specific about what the type of program is. I've had a few bake-offs and never disappointed. If you take lots of samples while it's running (not waiting) and you can't find anything to optimize, your code is very unusual.
Mike Dunlavey
@Mike, I'm not saying I don't find anything to optimize, I say I find the WRONG thing to optimize. First rule of Optimization Club is "Never Optimize unnecessarily."
Paul Tomblin
Have you actually tried this? It works for a very simple reason. If an instruction is on the call stack for X% of the time, then removing it would save exactly that much. Guaranteed. The expectation of the number of samples that shows the instruction is X%, plain and simple.
Mike Dunlavey
... now is it clear why it CAN'T give you a wrong answer?
Mike Dunlavey
As I implied in my comment to your original post, most of my programming is highly threaded. This method doesn't work for that, but a profiler does.
Paul Tomblin
Yeah, threads are harder to handle. If profilers would gen the same statistic that the halting method does, then I wouldn't have a gripe. They could, but I think only some do, and it needs to be understood that that's the important statistic.
Mike Dunlavey
Regarding threads, this programmer http://stackoverflow.com/questions/266373/one-could-use-a-profiler-but-why-not-just-halt-the-program#317160uses it, no problem.
Mike Dunlavey
+3  A: 

What if the program is in production and being used at the same time by paying clients or colleagues. Profiler allows you to observe without interferring (as much, because of course it will have a little hit too as per the Heisenberg principle)

Profiling can also give you much richer and more detailed accurate reports. This will be quicker in the long run.

dove
You're confusing the Heisenberg principle with the Observer effect: http://en.wikipedia.org/wiki/Conflated
JesperE
ITYM "Heisenbug".
Paul Tomblin
huh? check http://en.wikipedia.org/wiki/Performance_analysis#Simple_manual_techniquehttp://www.wikihow.com/Optimize-Your-Program%27s-Performance
Mike Dunlavey
@paul ;) like it @JesperE no confusion; if you try to measure the effect, your act of measurinng/profiling, will also distort what is happening (to varying degrees of course) and so would be different than that if you were not profiling. granted Werner was talking about ratherr small particles
dove
Only if it's hooked into the outside world. Otherwise, stopping it doesn't change its behavior.
Mike Dunlavey
Paul is right. The heisenberg principle has to do with measuring location versus momentum. The Observer effect has to do with the act of watching something affecting it.
Kevin
I like quantum physics too, and you could be right for issues like cache misses. What I nearly always find is just dumb code, usually caused by too many layers of abstraction, and speedups of 40x are common.
Mike Dunlavey
http://www.jargon.net/jargonfile/h/heisenbug.html
Paul Tomblin
That's a cute concept, but it's a diversion. It simply doesn't apply here.
Mike Dunlavey
On the physics front, in the 30s Hitler tried to denigrate Einstein by saying thousands of scientists disagreed with him. Einstein said if he were wrong, it would only take one.
Mike Dunlavey
A: 

EDIT 2008/11/25: OK, Vineet's response has finally made me see what the issue is here. Better late than never.

Somehow the idea got loose in the land that performance problems are found by measuring performance. That is confusing means with ends. Somehow I avoided this by single-stepping entire programs long ago. I did not berate myself for slowing it down to human speed. I was trying to see if it was doing wrong or unnecessary things. That's how to make software fast - find and remove unnecessary operations.

Nobody has the patience for single-stepping these days, but the next best thing is to pick a number of cycles at random and ask what their reasons are. (That's what the call stack can often tell you.) If a good percentage of them don't have good reasons, you can do something about it.

It's harder these days, what with threading and asynchrony, but that's how I tune software - by finding unnecessary cycles. Not by seeing how fast it is - I do that at the end.


Here's why sampling the call stack cannot give a wrong answer, and why not many samples are needed.

During the interval of interest, when the program is taking more time than you would like, the call stack exists continuously, even when you're not sampling it.

  • If an instruction I is on the call stack for fraction P(I) of that time, removing it from the program, if you could, would save exactly that much. If this isn't obvious, give it a bit of thought.

If the instruction shows up on M = 2 or more samples, out of N, its P(I) is approximately M/N, and is definitely significant.

The only way you can fail to see the instruction is to magically time all your samples for when the instruction is not on the call stack. The simple fact that it is present for a fraction of the time is what exposes it to your probes.

So the process of performance tuning is a simple matter of picking off instructions (mostly function call instructions) that raise their heads by turning up on multiple samples of the call stack. Those are the tall trees in the forest.

Notice that we don't have to care about the call graph, or how long functions take, or how many times they are called, or recursion.

I'm against obfuscation, not against profilers. They give you lots of statistics, but most don't give P(I), and most users don't realize that that's what matters.

You can talk about forests and trees, but for any performance problem that you can fix by modifying code, you need to modify instructions, specifically instructions with high P(I). So you need to know where those are, preferably without playing Sherlock Holmes. Stack sampling tells you exactly where they are.

This technique is harder to employ in multi-thread, event-driven, or systems in production. That's where profilers, if they would report P(I), could really help.

Mike Dunlavey
"never"??? Man, your experience is nothing like mine. Methinks you're generalizing from a very small data set.
Paul Tomblin
Hardly. Been doing it 30 years. If you've had bad luck with sampling maybe you're not doing it quite right. I've done my level best to explain it: http://en.wikipedia.org/wiki/Performance_analysis#Simple_manual_technique
Mike Dunlavey
Hah! I love your little link to wikipedia - that is something that you obviously wrote... So to defend your position and to lend some credence you point to another url - the contents of which you also wrote. That is amazing.
Tim
Tim, like most people on this website, I'm just trying to be helpful. Stack sampling is a really useful idea and I'm trying to tell people about it. Ideas are tested by proof, by reason or example, not by "lending credence".
Mike Dunlavey
Sampling works if you do it right. I've seen people take 1 sample, of a 30-level stack. It appears meaningless, so they give up, considering their skepticism justified. You gotta follow the procedure.
Mike Dunlavey
If "takes too long" is still too short for me to be able to break into the problem, then this method fails. I am a game developer. When my game is running at 20 fps instead of 25, halting and reading callstack once will not tell me much. I need to do this many times - i.e. sampling profiler.
Suma
Hi Suma. What I do in a case like that is take the code that has to run on each frame and write a loop that runs it flat out, not on a timer. That's what I take samples of in order to make it faster.
Mike Dunlavey
+6  A: 

There's a difference between things that programmers actually do, and things that they recommend others do.

I know of lots of programmers (myself included) that actually use this method. It only really helps to find the most obvious of performance problems, but it's quick and dirty and it works.

But I wouldn't really tell other programmers to do it, because it would take me too long to explain all the caveats. It's far too easy to make an inaccurate conclusion based on this method, and there are many areas where it just doesn't work at all. (for example, that method doesn't reveal any code that is triggered by user input).

So just like using lie detectors in court, or the "goto" statement, we just don't recommend that you do it, even though they all have their uses.

andy
I'm glad you use it. I suppose it takes some practice. It certainly takes explaining. I've never had it give me wrong information, and hardly ever obvious. On fast code, like user input, you gotta puff it up with a temporary outer loop.
Mike Dunlavey
+1  A: 

Stepping through code is great for seeing the nitty-gritty details and troubleshooting algorithms. It's sortof like looking at a tree really up close and following each vein of bark and branch individually.

Profiling lets you see the big picture, and quickly identify trouble points -- sortof like taking a step backwards and looking at the whole forest and noticing the tallest trees. By sorting your function calls by length of execution time, you can quickly identify the areas that are the trouble points.

HanClinto
If you sort function calls by (length_of_execution_time TIMES number_of_invocations), then I agree you're getting there. Even so, you may need more context to really understand if a function call could be avoided, and halting gives you that.
Mike Dunlavey
Actually, that's tricky because of recursion. The call-stack-sampling technique does not suffer from confusion about recursion.
Mike Dunlavey
+5  A: 

If we take the question "Why isn't it better known?" than the answer is going to be subjective. Presumably the reason why it is not better known is because profiling provides a long term solution rather than a current problem solution. It isn't effective for multi-threaded applications and isn't effective for applications like games which spend a significant portion of its time rendering.

Furthermore, in single threaded applications if you have a method that you expect to the consume the most run time and you want to reduce the run-time of all other methods then it is going to be harder to determine which secondary methods to focus your efforts upon first.

Your process for profiling is an acceptable method that can and does work but profiling provides you with more information and has the benefit of showing you more detailed performance improvements and regressions.

If you have well instrumented code than you can examine more than just the how long a particular method; you can see all the methods.

With profiling:

  • You can then rerun your scenario after each change to determine the degree of performance improvement/regression.

  • You can profile the code on different hardware configurations to determine if your production hardware is going to be sufficient.

  • You can profile the code under load and stress testing scenarios to determine how the volume of information impacts performance

  • You can make it easier for junior developers to visualise the impacts of their changes to your code because they can re-profile the code in six months time while your off at the beach or the pub, or both. Beach-pub, ftw.

Profiling is given more weight because enterprise code should always have some degree of profiling because of the benefits it gives to the organisation of an extended period of time. The more important the code the more profiling and testing you do.

Your approach is valid and is another item is the toolbox of the developer. It just gets outweighed by profiling.

Ryan Boucher
I agree with what you say about profilers as general health-monitoring tools. For finding bottlenecks precisely they only give clues. They don't pinpoint the problem (most of them). They find the haystack, but this method finds the needles.
Mike Dunlavey
Profiling can give you as much info as you want from per component to per statement. It gives it under a variety of scenarios and provides more long term benefits. With AOP or a VM you don't even need to instrument you're code to gain the benefits.The skill of the tool is in the hands of the owner
Ryan Boucher
Thanks, Ryan. I confess I'm not a profiler expert. All I know about them is what I see from their specs. I'm in a big team, and people talk about them but don't use them. Often I just halt the code a few times and say "Did you know you're spending a lot of time doing this ...?" Oops-didn't mean to.
Mike Dunlavey
+2  A: 

These must be some trivial examples that you are working with to get useful results with your method. I can't think of a project where profiling was useful (by whatever method) that would have gotten decent results with your "quick and effective" method. The time it takes to start and stop some applications already puts your assertion of "quick" to shame.

Why anyone would advocate making this sampling manual rather than automated is mind boggling. It is also mind-boggling that you continue to defend this idea.

Again, with non-trivial programs the method you advocate is useless.

EDIT: Regarding "why isn't it better known"?

In my experience code reviews avoid poor quality code and algorithms, and profiling would find these as well. If you wish to continue with your method that is great - but I think for most of the professional community this is so far down on the list of things to try that it will never get positive reinforcement as a good use of time.

It appears to be quite inaccurate with small sample sets and to get large sample sets would take lots of time that would have been better spent with other useful activities.

Tim
Actually it works better on bigger software because, since the stack is generally deeper, there are more instructions on it, so more candidates for optimizing. As far as applications taking long time to start and stop, that's exactly when halting it will find out why.
Mike Dunlavey
So here's the scenario: there's a big system, and it's all been done with code reviews, etc., but there's still a problem. The profiler tells you what state and county contains the problem, but stack sampling tells you the exact doorstep.
Mike Dunlavey
Profilers could tell you this, but for some reason they don't, as I explained in my "answer" below.
Mike Dunlavey
Um, I have used profilers that give this information.
Tim
Are you sure? Fraction of time on call stack, per statement (not function), in time interval of interest, sorted in decreasing order? I think some can do this. Most do not, from what I read.
Mike Dunlavey
BTW Tim, I see you're a pilot. Me too (student). I love aviation because there's no religion in it. There are differences of opinion, but you can usually get down to brass tacks.
Mike Dunlavey
+2  A: 

I've typically used it on real-time programs that were overrunning their timeslice. You can't manually stop and restart code that has to run 60 times every second.

I've also used it to track down the bottleneck in a compiler I had written. You wouldn't want to try to break such a program manually, because you really have no way of knowing if you are breaking at the spot where the bottlenck is, or just at the spot after the bottleneck when the OS is allowed back in to stop it. Also, what if the major bottleneck is something you can't do anything about, but you'd like to get rid of all the other largeish bottlenecks in the system? How to you prioritize which bottlenecks to attack first, when you don't have good data on where they all are, and what their relative impact each is?

T.E.D.
First question: run the code separately in a long loop, and take your time about squeezing it.
Mike Dunlavey
Second question: That's why you take several samples. The bigger each bottleneck is, the more it will stand out. And it doesn't matter what order you tackle them, because each one will make it faster.
Mike Dunlavey
The point is, you don't have to wonder where they are. It pinpoints each one. All you have to do is figure out which ones you can do something about.
Mike Dunlavey
Actually, the term "bottleneck" bothers me, because it gives a misleading image of typical problems. They are more like government waste. The more layers there are, the more likely it's in there somewhere.
Mike Dunlavey
I think you are missing my point. The issue is that a debugger can't always stop a program just anywhere. For instance, it typically can't stop you inside a system call. Instead it will break you an instruction or two later, and you will think the problem is there.
T.E.D.
Good point. Fortunately it's not a serious problem, because it's no different from a lengthy instruction. If you halt right after "call FileOpen", you're looking at a gold nugget of information. Is the file being opened/closed unnecessarily? Look higher up.
Mike Dunlavey
Where I used to run into difficulty was some 90's version of VC, where if you hit the pause button, it wouldn't bother stopping until the next windows message. Man, that was annoying.
Mike Dunlavey
+2  A: 

I used this method for C64 Basic many years ago. Surprising how well it works.

WW
+1  A: 

The larger your program gets, the more useful a profiler will be. If you need to optimize a program which contains thousands of conditional branches, a profiler can be indispensible. Feed in your largest sample of test data, and when it's done import the profiling data into Excel. Then you check your assumptions about likely hot spots against the actual data. There are always surprises.

mseery
Thanks for your comment. Few people have actually tried this, instead relying on intuition. Profilers are fine for what they do. But if you actually take some samples and study them, you'll be surprised, *especially* in big programs. I know it's hard to believe.
Mike Dunlavey
+3  A: 

Hitting the pause button during the execution of a program in "debug" mode might not provide the right data to perform any performance optimizations. To put it bluntly, it is a crude form of profiling.

If you must avoid using a profiler, a better bet is to use a logger, and then apply a slowdown factor to "guesstimate" where the real problem is. Profilers however, are better tools for guesstimating.

The reason why hitting the pause button in debug mode, may not give a real picture of application behavior is because debuggers introduce additional executable code that can slowdown certain parts of the application. One can refer to Mike Stall's blog post on possible reasons for application slowdown in a debugging environment. The post sheds light on certain reasons like too many breakpoints,creation of exception objects, unoptimized code etc. The part about unoptimized code is important - the "debug" mode will result in a lot of optimizations (usually code in-lining and re-ordering) being thrown out of the window, to enable the debug host (the process running your code) and the IDE to synchronize code execution. Therefore, hitting pause repeatedly in "debug" mode might be a bad idea.

Vineet Reynolds
The things you say are true but don't matter, because a single-thread program spends a sequence of cycles, and you need to find out if any of them are being spent for poor reasons. After you fix those, it takes less cycles, and then runs faster.
Mike Dunlavey
In debug mode, sure there's overhead, but it goes away in release mode. The thing about inlining is it matters in code where the program counter lives. Higher up the call stack it makes no difference, and thats where many problems are.
Mike Dunlavey
I think the problem is confusion between measuring performance and finding performance problems. I suggest separating these goals.
Mike Dunlavey
I've said that profilers help if they sample the entire call stack (some do) and if they tell you, for each instruction (call or non-call) what percentage of stacks it was on. The only remaining point is, for big issues, not many samples are needed.
Mike Dunlavey
Yes, fixing issues will cause the program to run faster. But you might solve the wrong problem. Besides, you have already pointed you the real issue which is unknown behavior of the program in runtime. The only way to optimize such an application, would involve studying the codeflow.
Vineet Reynolds
Thanks. The keywords are "might" and "would". If you do it, you see that any problem you find and fix is not a wrong problem because it reduces time, and it makes other problems more obvious. Studying codeflow is fine, but it will miss subtle stuff, like compiler-inserted calls.
Mike Dunlavey
This isn't something you do just once. If there, say, 3 performance problems, you fix 1, and that makes the other 2 take larger percentages. Then you do the 2nd, and so forth. If one of them is "right", dont' worry, you'll get it, guaranteed.
Mike Dunlavey
+12  A: 

On java servers it's always been a neat trick to do 2-3 quick ctrl-breaks in a row and get 2-3 threaddumps of all running threads. Simply looking at where all the threads "are" may give you extremely quick pinpoint to where your performance problems are.

This technique can reveal more performance problems in 2 minutes than any other technique I know of.

krosenvold
There's still the issue of tracking down asynchronous problems, but for that other methods are needed.
Mike Dunlavey
Have you experimented by doing this programmatically with the Java 6 additions allowing for stack trace introspection?
Thorbjørn Ravn Andersen
I'm not sure we're thinking about the same thing; a thread dump gives you a view of where *all* your threads are at any given point in time. If you're going to do this inside your code, you'll need to know where to put it, right ?
krosenvold
Note that this is *exactly* how the "cpu=samples" feature of `hprof`works. It will wake up regularly (default 10ms) and record the current stack trace of every thread. Handy if you find it difficult to press ctrl-break 100 times a second ;-).
sleske
+5  A: 

Sampling profilers are only useful when

  1. You are monitoring a runtime with a small number of threads. Preferably one.
  2. The call stack depth of each thread is relatively small (to reduce the incredible overhead in collection a sample).
  3. You are only concerned about wall clock time and not other meters or resource bottlenecks.
  4. You have not instrumented the code for management & monitoring purposes (hence the stack dump requests)
  5. You mistakenly believe removing a stack frame is an effective performance improvement strategy whether the inherent costs (excluding callees) are practically zero or not
  6. You can't be bothered to learn how to apply software performance engineering day-to-day in your job
  7. ....

http://williamlouth.wordpress.com/2009/01/16/profiling-sampling-versus-execution-part-2/

William

@William: What you really need to do is decide what you care about. If the system is empirically "too slow" then wall clock time slices are the thing to sample. For each sample you need to find out _why_ it is being spent. In a single-thread program, the stack can often tell you that, but not always, like if it's an interpreter or message-driven. If it's multi-thread, it may be even harder to determine the _why_, but that's what you need to determine, because to spend fewer units of the desired resource, you need to find those that have a nonessential reason.
Mike Dunlavey
... ignoring unhelpful remarks, like 6, I just scanned your blog entry and absorbed as much as I could in 10 minutes. It seems we are solving different problems. I am less concerned with ongoing health-monitoring, and more with discovery and removal of performance problems. To that end, I don't care about the overhead of sampling, only that it is unbiased. I am not trying to remove stack frames, but unnecessary time-taking operations, which are very often method calls, and the more levels there are, the better the hunting is.
Mike Dunlavey
... but I'll give you an up-vote for taking the trouble to answer, and as a welcome to SO :-)
Mike Dunlavey
... and BTW your weblog has comments disabled. Is that to avoid being questioned?
Mike Dunlavey
+1  A: 

Mike thanks for pointing out the disablement of comments on my blog. Somehow the automatic comment closure setting on the wordpress discussion page is set 1 day.

William Louth
++ Hate to see you floating around with a rep of 1 :-) I guess that's just because you're in SO twice, once with a ' ' between given and surname.
Mike Dunlavey
... anyway, I hope you parse out the comments I added to your previous question. You've had a lot to say on this subject, and I have too. I see most people assuming performance tuning is hard and requires profilers. Much of the time (not all) neither is true.
Mike Dunlavey
... for example: http://stackoverflow.com/questions/926266/performance-optimization-strategies-of-last-resort/927773#927773
Mike Dunlavey
... just had another thought to your point 5 above. I've seen that execution time varies (roughly) exponentially with sampled stack depth. My explanation is that at each level there is a certain probability of excess calls being done, and this effect compounds. This does not seem to be generally understood, for some reason.
Mike Dunlavey
That is a good point Mike. Yes I think it has something to do with other missed method calls per call stack frame. I would also speculate that the lower you go (deeper the stack) in a standard enterprise application the more calls (distinct count, frequency) that are made to very lightweight methods.It should also be noted that in current JVM's the cost in collecting a stack is not linear to the depth. The cost rises per call frame depth.
William Louth
@William: You know my method is to halt the program at random, grab a stackshot, and analyze it to see why it's being done. The speed of grabbing is irrelevant, because I'm not timimg. I'm asking why was the thread spending that particular wall-clock nanosecond, and was it necessary? That's what the statements on the stack can almost always answer. If there is a problem, then its removal will save some % of the time, and the probability of seeing it on each sample is no less than that.
Mike Dunlavey
... this is probably really different from the way you're used to thinking about it, and you're not alone. Notice among the answers to the question, most can't believe it (to put it charitably), but a few quiet ones (me excepted) know that it really does work. I'm just trying to get the word out, because it's too valuable to be smothered under what "everybody knows".
Mike Dunlavey
... here are the links to explanations that people seem to find more agreeable: http://stackoverflow.com/questions/375913/what-can-i-use-to-profile-c-code-in-linux/378024#378024and http://stackoverflow.com/questions/926266/performance-optimization-strategies-of-last-resort/927773#927773
Mike Dunlavey
Mike the approach you prescribe I would argue is only effective in single threaded applications with largely static execution behavior and cost patterns and even then it mainly in development rather than a production environment. Your approach is basically focused on the software execution model - remove steps. A system execution model builds on this and looks at how such execution patterns behavior (in terms of dynamic cost) under different types of workloads (units/sizes) and concurrency.
William Louth
Here removing a frame or an execution step or execution tx/flow can easily introduce a drag on the performance and scalability as it just pushes more work at a faster space to a resource already saturated and trashing. You need both models to be collected and related and this can only happen when you have a technique that works with both models. The approach I recommend and the one that I make a living from achieves this and it works across whatever environment and under whatever context.
William Louth
@William: No need to spend a lot of words on debate when demonstration suffices. For example, look at the first comment on this entry: http://stackoverflow.com/questions/890222/analyzing-code-for-efficiency/893272#893272
Mike Dunlavey
Mike Dunlavey
... What you say about systems that involve a lot of message-passing rings true, and I have also tuned those. For those, I tune the individual threads so they're not doing anything unnecessary, after which I analyze the message traffic. As always, I'm not measuring. I'm looking for specific representative instances of _unnecessary_ activity.
Mike Dunlavey
Mike I have read you postings I appreciate the effort you make and fully respect your unwavering commitment to improving the life of a developer with regard to tuning. But you wrong in thinking that I have not implemented and tested the effectiveness of call stack sampling. Even though we issue updates to our software nearly on a bi-weekly basis I am actually one of the biggest procrastinators you will have every met though I am probably the most prolific software designer and developer I know. What we deliver today was dreamt and designed at least 2 years prior to its release.
William Louth
I spend an incredible long time mulling over ideas and their many possible realization. I just queue things up. Of course you can be effective with you approach to some degree but you will not be able to tackle every problem especially those in the field of distributed computing, concurrent/parallel processing (even Java EE). There are limits to your approach. There are no limits to my approach. Will everyone hit those limits. I cannot honestly say because I am only ever called into solve the hardest of performance and scalability problems that have plagued customers for months - a bias.
William Louth
Mike call stack analysis is not going to help when the most important piece of profiling data is not the actually class/method name but one or more contexts of the operation: http url, sql, grid/cache name, message type, destination queue,...All of these will look pretty much the same and it is going to get much more like this with the growth of multi-tenant PaaS solutions in the cloud were the application code base represents a generic business process execution engine.
William Louth
With the approach I favor and value over all others I can meter (profile) from different perspectives (bundles, codebase, execution context, even multiple tagged execution periods) and I can do this in terms of whatever resource meters are related to key performance indicators for the system as a whole.http://blog.jinspired.com/?p=755http://blog.jinspired.com/?p=738
William Louth
@William: I've utmost respect for what you're doing. I just think there's >1 way to conceptualize this. Some are "big picture" thinkers. I go where the "rubber meets the road". If a user perceives a gap between hitting "enter" and seeing info, every nanosecond in that gap has a reason. Nanoseconds that could be eliminated because they're not essential represent opportunities for optimization. Many people assume, without knowing, that all those nanoseconds are actually necessary. Unless aggressive tuning has been done, experience says they are not.
Mike Dunlavey
... With many threads, it may be harder (maybe much harder) to figure out which nanoseconds of the gap are actually necessary, because the "why-chain" spans multiple threads on multiple processors, but for me at least, that is the question that has to be answered, hard or not. To condense the point, little attention has been given to "bottom-up" methods. They are not not not about measuring. They are about fishing for culprits that are causing time to be spent that is not necessary.
Mike Dunlavey
Mike I think in a few years call stack dumps (or sampling) will be irrelevant with more and more software moving to the cloud and/or becoming a cloud service. Service requests and resource interactions will have to be metered either way for cost-, performance-, capacity- management purposes via execution probes. How fast and at what cost!!! These will be your suspects/culprits for the most part. This is even going to get harder because a large part of the infrastructure will be elastic and driven by policies largely based on the performance analysis of the activities executed. Metering.
William Louth
Just in case this gets lost. Sampling and on-demand dumps can be effective if you have already a good understand of the execution model and the resource behavior and usage. You will certainly find the low hanging fruit [which should never make it in prod] and maybe that is sufficient for most people. For those [financial inst.] obsessive about costs, timing, capacity,.... its not adequate for complete coverage (risk mgmt) going or running in production.Please note that our execution probes actually support probe stack sampling and on-demand stack dumps.
William Louth
By the way the approach I recommend and use does assume the person collecting and analyzing the data has a good analytical mind and can model effective both the software and system in determining collection techniques and strategies.
William Louth
@William: Not to belabor but... When a computer executes an instruction, unless it's doing it as a random act triggered by a cosmic-ray, it's in code written by a person, who had a reason. What's more, it's in a routine called from another instruction, and that has a reason. The chain of reasons is the why-chain. It may be in response to a message from Mars, in which case the reason may be hard to tell, but it's still there. Every unit of time between start and end of a useful process has a why-chain, whether it's easy to see on a stackshot, or spread across a cloud of computing agents....
Mike Dunlavey
... If there exists a change in code in any of those computing agents that will result in fewer units of time for the round-trip, then that change is an optimization. Now, if you pick a random time slice out of that round-trip, and figure out what its why-chain is, every point on it is a program state that is _waiting_ for the work it requested to complete. If that work _can have been done without_, it need not be waiting for it. Now, you can still look at these as time-slices, or as bigger lumps of time, like function timing. I focus on slices...
Mike Dunlavey
... because in the bigger lumps the why-chains get lost, so it's harder to find the points that don't need to be done.
Mike Dunlavey
... One of the models of computation says that any computation consists of a partial order of events performed by computing agents. Each event has to wait for its predecessors. There's no way around it. To optimize the computation, what you need to do is get rid of intermediate events that aren't strictly necessary. Single processor, cloud, whatever, I don't think that logic is escapable.
Mike Dunlavey
+3  A: 

Stack trace snapshots only allow you to see stroboscopic x-rays of your application. You may require more accumulated knowledge which a profiler may give you.

The trick is knowing your tools well and choose the best for the job at hand.

Thorbjørn Ravn Andersen
@Thorbjørn: Well, who can argue with your last sentence? Every tool automates a technique. My point is that the nature of this problem is that the technique of sampling (and analyzing) the stack is little-known, simple, and very effective. What's more, the ambient attitudes people have about performance need to be re-evaluated. For example, if you want to measure performance precisely, that's fine, but if you want to improve performance, measurement misses the point.
Mike Dunlavey
... If I could add, yes you are taking stroboscopic x-rays of your application. (I think that is an excellent metaphor.) Typically there are unexpected things that the app is doing that could be replaced for substantial speedup. The time that would save is the probability they will appear on each stackshot. That's why it works.
Mike Dunlavey
... So I gave you an upvote for that nice metaphor.
Mike Dunlavey
Thank you for the upvote. In return I think you should know that your choice of words in comments may convey the image that you are a "I know better than you"-person instead of considering others as equals. If that is not intentional,well, at least you know now.
Thorbjørn Ravn Andersen
And a very useful tool could be one that programatically takes a complete application stacktrace and dump it somewhere. jvisualvm can do it externally, but you may not always be able to attach with jvisualvm (or you want to do it on a schedule instead of invoked manually). This requires Java 6.
Thorbjørn Ravn Andersen
@Thorbjørn: About knowing better, maybe it comes from having been a professor, or maybe from using, questioning, explaining, and proving the technique for so long that it's hard to avoid the feeling that, well, I do know better, on this particular subject and maybe 1 or 2 others. In fact, I've never figured out why this technique is not general knowledge. Also, I googled "stackshot" and found someone who makes a tool that does exactly that.
Mike Dunlavey
... BTW I'm not alone. There are people on SO who "get it", and so does Jon Bentley, on page 33 of this PDF: http://dimacs.rutgers.edu/Workshops/EAA/slides/bentley.pdf
Mike Dunlavey
I encourage you to get a Mac, and see that the Activity Monitor allows for doing exactly this, as well as aggregate the results.
Thorbjørn Ravn Andersen
I also encourage you to write a Java 6 stack trace analyzer encompassing your vast experience with this approach.
Thorbjørn Ravn Andersen
@Thorbjørn: I did write one about 15 years ago, as a DOS program, and it worked fine, but IMO it was no match for the manual method because, even with the drudgery of writing down call stacks, being able to actually see the data at run-time was just too useful. Besides, I'm at an age where I need to be careful what challenges I take on.
Mike Dunlavey
... BTW you might be interested in the comments on this answer. A user took 4 samples and got a 7x speedup. Later he took 20 samples and got a 3x speedup. (I don't know if that meant he got an overall 21x speedup, or if those were independent, but I have seen that happen.) http://stackoverflow.com/questions/890222/analyzing-code-for-efficiency/893272#893272
Mike Dunlavey
Now I've found out what nagged me about your explanation. You say you need to halt your program - that is incorrect, as what you describe is basically repeated thread dumps which can be done WITHOUT halting the Java program. Ctrl-Break reportedly does it under WIndows, and "kill -3" under Unix, and Java 6 even allows you to do that programatically.
Thorbjørn Ravn Andersen
@Thorbjørn: Hmmm... I guess I never thought much about the distinction. The "profiler" I wrote would also take the samples on-the-fly, but IMO nothing compares to getting your fingers right in the code
Mike Dunlavey
I still encourage you to investigate the posibillities with OS X. You will like it.
Thorbjørn Ravn Andersen
and by the way... No Java programs are single threaded any more - you have multiple threads running all the time, and have thread pools to do things in parallel etc. In other words "halt the program" does not make much sense any more.
Thorbjørn Ravn Andersen
@Thorbjørn: Regarding Java threading, look at the selected answer (from krosenvold). It's not that "halting the program" doesn't make sense. They just made it harder to do because they don't understand how useful it is. If you're waiting for the program, then part of it is waiting for some other part, and so on, so there is a waiting-chain. Tracking that chain across threads is not simple, but within a thread it is easy (the call stack), and that's what needs to be done. Just because they make it difficult doesn't mean you don't need to do it.
Mike Dunlavey
+2  A: 

I'm surprised by the religous tone on both sides.

Profiling is great, and certainly is a more refined and precise when you can do it. Sometimes you can't, and it's nice to have a trusty back-up. The pause technique is like the manual screwdriver you use when your power tool is too far away or the bateries have run-down.

Here is a short true story. An app (kind of a batch proccessing task) had been running fine in production for six months, suddenly ops is calling developers because it is going "too slow". They aren't going to let us attach a sampling profiler in production! You have to work with the tools already installed. Without stopping the production process, just using Process Explorer, (which ops had already installed on the machine) we could see a snapshot of a thread's stack. You can glance at the top of the stack, dismiss it with the enter key and get another snapshot with another mouse click. You can easily get a sample every second or so.

It doesn't take long to see if the top of the stack is most often in the database client library dll (waiting on the datase), or in another system dll (waiting for a system operation), or actually in some method of the applicaiton itself. In this case, if I remember right, we quickly noticed that 8 times in 10 the app was in a system .dll call reading or writing a network file. Sure enough recent "upgrades" had changed the performacne characteristics of a file share. Without a quick and dirty and (sysadmin sanctioned) approach to see what the app was doing in production, we would have spent far more time trying to measure the issue, than correcting the issue.

On the other hand, when performance requirements move beyond "good enough" to really pushing the envelope, a profiler becomes essential so that you can try to shave cycles from all of your closely-tied top-ten or twenty hot spots. Even if you are just trying to hold to a moderate performance requirement durring a project, when you can get the right tools lined-up to help you measure and test, and even get them integrated into your automated test process it can be fantasticly helpful.

But when the power is out (so to speak) and the batteries are dead, it's nice know how to use that manual screwdriver.

So the direct answer: Know what you can learn from halting the program, but don't be afraid of precision tools either. Most importantly know which jobs call for which tools.

DanO
"Religious tone" - Ouch! Process Explorer - sounds great, now don't just look at the top of the stack. The "gold nuggets" are in the middle. I agree profilers are precision tools - precision of the wrong thing. They measure time with precision, but (if they take and retain stack samples) they actually know the problem location with high precision, but they don't show it to you, and that's what you're looking for.
Mike Dunlavey
... Sorry, can't leave well enough alone. Here's a (only slightly artificial) case study: http://stackoverflow.com/questions/926266/performance-optimization-strategies-of-last-resort/927773#927773It's tempting to think that a profiler will do a better job when you're really trying to push performance, but when you get down to an actual experiment, that doesn't seem to hold. In fact, I've never seen a story where a profiler was used to really wring out a program through a series of steps, as in that example.
Mike Dunlavey
... I don't mean to give you a hard time. Your story about the file system upgrade showing you an 8 in 10 problem is exactly what I'm talking about. Now I'm just trying to raise awareness that in big software it's really easy to get issues like that in your own code in the form of mid-stack calls, and those are not hot-spots, because the program counter is not there. (In real hot-spots, by my understanding, the memory chip actually has a spot of higher temperature.)
Mike Dunlavey