5

I have asked questions whose answers often faced me in the direction of efficiency. Rather than continuing asking these type of questions I would rather look beforehand at the efficiency. However there are of course many different types of efficiency. The number of lines in code, assembly, the time it takes to write, the time it takes for a computer to execute. And I probably miss a lot more ways to look at it.

Because there are so many ways to look at efficiency, I would like to start with how do you get the assembly code of your own code and stop at the right spot within your code? (Let's say you have 500 lines of code and you're interested in line 450 to 460). I am not sure if this is already a feature found in IDEs, if so how could I find functions like these? (= What is the naming of these sort of things so that I can find it for my own IDEs if it has this feature).

(There is already a lot of information about efficiency at Stack Overflow, I looked at many of them, however I found it hard to get a feel of what people often start with when they analyse their code. Do they start with studying their code, then assembly or do they just use an IDE to find the most expensive methods and change them this way? This is a bad question because it of course depends on a lot on different factors, but I hope to get at least a little bit more feel for it and I think an answer to this question might help.)

OrangeDog
  • 36,653
  • 12
  • 122
  • 207
Joop
  • 3,706
  • 34
  • 55
  • 1
    A debugger lets you stop at specific points (breakpoints) and step or continue from these points. In general, people use debuggers. For smaller programs/problems some print statements should do the trick (along with some inspection+thinking of course). – keyser Dec 19 '14 at 10:12
  • But a debugger just let's you stop at a specific line of code right? It does not really show how expensive a method call is for example.. only shows the source code of the method. With print statements you mean that you print the starttime, and the end time and see that as a way of how long it took to get there? – Joop Dec 19 '14 at 10:14
  • 1
    Yes, it's mainly used to inspect the flow and inner workings. Getting execution times is also possible though. One thing to remember when debugging is that the actual code is often changed in order to be debuggable, which might be an issue if you want to inspect assembly or byte code. – keyser Dec 19 '14 at 10:16
  • 2
    I guess what you're looking for is a profiler. There is one bundled with the JDK called VisualVM and there are several others both free and commercial – Simon Dec 19 '14 at 10:16
  • 1
    There's another thing you can do with a debugger. [*You can pause it randomly a few times and see what's happening.*](http://stackoverflow.com/a/378024/23771) Suppose it is wasting some fraction like 30% of its time doing something silly, like calling some innocent function that, 5 layers down the call stack, happens to do some file I/O, and you realize you don't *really* need it. If you pause it 10 times, 3 of those times, on average, it will pin the tail on the problem for you. No profiler can do that. Fix it, save 30%, and do it again, to get the next problem, and so on. – Mike Dunlavey Dec 19 '14 at 22:11

2 Answers2

4

You are unlikely to get anything useful from analyzing assembly code generated by JVM. If you are worrying about performance, this is the wrong approach. You cannot reason about high-level performance by measuring low level details. This probably worked well for first programs where you could count cycles by hand. Nowadays computers are much more complicated - especially when you are using high-level language such as Java. Thing you need to take into account include:

  • Garbage collector pauses
  • JIT with various optimizations
  • Multiple levels of instruction and data caches.
  • Branch prediction.

Those mechanisms and interactions between them are not something you can easily predict. There is only one sane way to write fast programs I know:

  1. Write some part of the program.
  2. Identify that it is indeed too slow.
  3. Identify and fix bottle necks.
  4. Goto #1.

To identify bottle necks I usually start with JVisualVM and go for some more low-level tools if necessary:

In 99% of cases the issue is slow algorithm, wrong data structure, inefficient disk access or something stupid like left over debug logs. Less often micro-optimizations like avoiding unnecessary copy or memory allocations will help. In rare circumstances, if everything else fails and you need to squeeze a few cycles out of some tight loop, it might be worth to look at the generated assembly. PrintAssembly might be useful in that case. You want to start with tools that are most likely to help you.

Piotr Praszmo
  • 17,928
  • 1
  • 57
  • 65
2

To get JVM's assembly code you can use PrintAssembly parameter. It gives a readable code with comments, pointing to lines in java sources. So you can clearly understand how your Java code is compiled. But I think, looking at processor instructions is very hard to understand bottle necks. For this purpose I have used VisualVM and JProfiler.

Mikhail
  • 4,175
  • 15
  • 31