Java performance tips

前端 未结 14 1578
傲寒
傲寒 2021-02-01 20:04

I have a program I ported from C to Java. Both apps use quicksort to order some partitioned data (genomic coordinates).

The Java version runs fast, but I\'d like to get

相关标签:
14条回答
  • 2021-02-01 20:36

    jvisualvm ships with JDK 6 now - that's the reason the link cited above doesn't work. Just type "jvisualvm <pid>", where <pid> is the ID of the process you want to track. You'll get to see how the heap is being used, but you won't see what's filling it up.

    If it's a long-running process, you can turn on the -server option when you run. There are a lot of tuning options available to you; that's just one.

    0 讨论(0)
  • 2021-02-01 20:36

    Methodolically, you have to profile the application and then get an idea of what components of your program are time and memory-intensive: then take a closer look to that components, in order to improve their performances (see Amdahl's law).

    From a pure technological POV, you can use some java-to-nativecode compilers, like Excelsior's jet, but I've to note that recent JVM are really fast, so the VM should not impact in a significative manner.

    0 讨论(0)
  • 2021-02-01 20:37

    Is your sorting code executing only once, e.g. in a commandline utility that just sorts, or multiple times, e.g. a webapp that sorts in response to some user input?

    Chances are that performance would increase significantly after the code has been executed a few times because the HotSpot VM may optimize aggressively if it decides your code is a hotspot.

    This is a big advantage compared to C/C++.

    The VM, at runtime, optimizes code that is used often, and it does that quite well. Performance can actually rise beyond that of C/C++ because of this. Really. ;)

    Your custom Comparator could be a place for optimization, though.

    Try to check inexpensive stuff first (e.g. int comparison) before more expensive stuff (e.g. String comparison). I'm not sure if those tips apply because I don't know your Comparator.

    Use either Collections.sort(list, comparator) or Arrays.sort(array, comparator). The array variant will be a bit faster, see the respective documentation.

    As Andreas said before: don't try to outsmart the VM.

    0 讨论(0)
  • 2021-02-01 20:42

    First caveat - make sure you have done appropriate profiling or benchmarking before embarking on any optimisation work. The results will often enlighten you, and nearly always save you a lot of wasted effort in optimising something that doesn't matter.

    Assuming that you do need it, then you can get performance comparable to C in Java, but it takes some effort. You need to know where the JVM is doing "extra work" and avoid these.

    In particular:

    • Avoid unnecessary object creation. While the JVM heap and GC is extremely fast and efficient (probably the best in the world, and almost certainly better than anything you could roll yourself in C), it is still heap allocation and that will be beaten by avoiding the heap in the first place (stack or register allocation)
    • Avoid boxed primitives. You want to be using double and not Double.
    • Use primitive arrays for any big chunks of data. Java primitive arrays are basically as fast as C/C++ arrays (they do have an additional bounds check but that is usually insignificant)
    • Avoid anything synchronized - Java threading is pretty decent but it is still overhead that you may not need. Give each thread it's own data to work on.
    • Exploit concurrency - Java's concurrency support is very good. You might as well use all your cores! This is a big topic but there are plenty of good books / tutorials available.
    • Use specialised collection classes for certain types of data if you have some very specific requirements, e.g. supporting some specialised sorting/search algorithms. You may need to roll your own, but there are also some good libraries with high performance collection classes available that may fit your needs - see e.g. Javoltion
    • Avoid big class heirarchies - this is a design smell in performance code. Every layer of abstraction is costing you overhead. Very fast Java code will often end up looking rather like C....
    • Use static methods - the JIT can optimise these extremely well. It will usually inline them.
    • Use final concrete classes - again, the JIT can optimise these very well by avoiding virtual function calls.
    • Generate your own bytecode - if all else fails, this can be a viable option if you want the absolute maximum performance out of the JVM. Particularly useful if you need to compile your own DSL. Use something like ASM.
    0 讨论(0)
  • 2021-02-01 20:45

    do not try to outsmart the jvm.

    in particular:

    • don't try to avoid object creation for the sake of performance

    • use immutable objects where applicable.

    • use the scope of your objects correctly, so that the GC can do its job.

    • use primitives where you mean primitives (e.g. non-nullable int compared to nullable Integer)

    • use the built-in algorithms and data structures

    • when handing concurrency use java.util.concurrent package.

    • correctness over performance. first get it right, then measure, then measure with a profiler then optimize.

    0 讨论(0)
  • 2021-02-01 20:48

    Obviously, profile profile profile. For Eclipse there's TPTP. Here's an article on the TPTP plugin for Eclipse. Netbeans has its own profiler. jvisualvm is nice as a standalone tool. (The entire dev.java.net server seems to be down at the moment, but it is very much an active project.)

    The first thing to do is use the library sorting routine, Collections.sort; this will require your data objects to be Comparable. This might be fast enough and will definitely provide a good baseline.

    General tips:

    • Avoid locks you don't need (your JVM may have already optimized these away)
    • Use StringBuilder (not StringBuffer because of that lock thing I just mentioned) instead of concatenating String objects
    • Make anything you can final; if possible, make your classes completely immutable
    • If you aren't changing the value of a variable in a loop, try hoisting it out and see if it makes a difference (the JVM may have already done this for you)
    • Try to work on an ArrayList (or even an array) so the memory you're accessing is contiguous instead of potentially fragmented the way it might be with a LinkedList
    • Quicksort can be parallelized; consider doing that (see quicksort parallelization)
    • Reduce the visibility and live time of your data as much as possible (but don't contort your algorithm to do it unless profiling shows it is a big win)
    0 讨论(0)
提交回复
热议问题