Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to measure efficiency (in particular: assembly code) for java programs?

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

like image 321
Joop Avatar asked Dec 19 '14 10:12

Joop


2 Answers

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:

  • perf
  • strace
  • -XX JVM diagnostics

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.

like image 53
Piotr Praszmo Avatar answered Sep 21 '22 12:09

Piotr Praszmo


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.

like image 25
Mikhail Avatar answered Sep 21 '22 12:09

Mikhail