Tips

  • list.removeIf(lambda)
  • map.computeIfPresent(lambda) // good for multi-threading with ConcurrentHashMap ??
  • Stream is not a data structure, it is an abstraction of functions.

JIT in the HotSpot

(java is best thought as dynamically compiled)

  • (Evans, 2013) Let’s look at some good basic facts about JIT compilation:
    • Virtually all modern JVMs will have a JIT compiler of some sort.
    • Purely interpreted VMs are very slow by comparison.
    • Compiled methods run much, much faster than interpreted code.
    • It makes sense to compile the most heavily used methods first.
    • When doing JIT compilation, it’s always important to take the low-hanging fruit first.
  • (Evans, 2013) Methods start off being interpreted from their bytecode representation, with the JVM keeping track of how many times a method has been called (and a few other statistics). When a threshold value is reached (10,000 times, by default), and if the method is eligible, a JVM thread will compile the bytecode to machine code in the background. If compilation succeeds, all further calls to the method will use the compiled form, unless something happens to invalidate it or otherwise cause deoptimization.
  • (Evans, 2013) Depending on the exact nature of the code in a method, a compiled method can be up to 100 times faster than the same method in interpreted mode. Understanding which methods are important in a program, and which important methods are being compiled, is very often the cornerstone of improving performance.
  • (Evans, 2013) client -server modes
    • client: tends to make more conservative decisions when compiling. This means that it can’t pause unexpectedly while it backs out an optimization decision that turned out to be incorrect or based on a faulty assumption.
    • server: By contrast, the server compiler (C2) will make aggressive assumptions when compiling. To ensure that the code that’s run is always correct, C2 will add a quick runtime check (usually called a guard condition) that the assumption it made is valid. If not, it will back out the aggressive compilation and will often try something else. This aggressive approach can yield far better performance than the rather risk-averse client compiler.
    • real-time java (a separate VM, not the HotSpot): Real-time programming is really about the guarantees that can be made. In statistical terms, a real-time system seeks to reduce the variance of the time taken to perform certain operations, and is prepared to sacrifice a certain amount of mean latency to do so. Overall performance may be slightly sacrificed in order to attain more consistent running.
  • (Evans, 2013) inlining - It works by eliminating the call to the inlined method, and instead placing the code of the called method inside the caller.
    • One of the advantages of the platform is that the compiler can make the decision to inline based on decent runtime statistics about how often the method is called and other factors (for example, will it make the caller method too large and potentially affect code caches). This means that HotSpot’s compiler can make much smarter decisions about inlining than ahead-of-time compilers.
    • HotSpot can and will ignore access control when compiling methods to machine code and will replace an accessor method with a direct access to the private field. This doesn’t compromise Java’s security model, because all of the access control was checked at class loading and linking time.
    • pp 198
  • (Evans, 2013) GC strategies - pp 182

Aspects

(Comparing Spring AOP and AspectJ, 2017)

Weaving

  • (ajc) Compile Time: AspectJ compiler takes as input both aspect and application sources and produces woven class files
  • (ajc) Post-Compile Time (a.k.a Binary): AspectJ compiler takes as input aspect sources and application class or jar files
  • (ajc) Load Time: same as Binary, but the weaving is postponed until a class loader loads the class files to the JVM.
  • (spring aop) Runtime weaving - With runtime weaving, the aspects are woven during the execution of the application using proxies of the targeted object – using either JDK dynamic proxy or CGLIB proxy
    • JDK dynamic proxy (interface based) – the preferred way for Spring AOP. Whenever the targeted object implements even one interface, then JDK dynamic proxy will be used.
    • CGLIB proxy (class based) – if the target object doesn’t implement an interface, then CGLIB proxy can be used.

Jointpoints

  • Spring AOP have limitations on final, static and private methods, due to the runtime weaving approach.
Jointpoints Spring AOP AspectJ
Method Execution Yes Yes
Constructor Call No Yes
Constructor Execution No Yes
Static initializer execution No Yes
Object initialization No Yes
Field assignment No Yes
Handler execution No Yes
Advice execution No Yes

additional java options (example with aspects)

set _JAVA_OPTIONS=-Daj.weaving.verbose=true -Dorg.aspectj.weaver.showWeaveInfo=true -Dorg.aspectj.osgi.verbose=true -Dorg.aspectj.tracing.factory=default -Dorg.aspectj.tracing.enabled=true -Dorg.aspectj.tracing.messages=true

Simple Performance Framework for Java (SPF4J)

java APIs

Matrix APIs

multiply by self 3000x3000 300x300
ATLAS, Pyhton, R 4 sec*
JAMA 50 sec*
COLT 150 sec*
JBLAS (ATLAS) 4 sec*
Breeze BASE 19,5 sec 500 ms
Breeze Native 17 sec 600 ms
Breeze MKL(blas) 1,5 sec 500 ms
  • Notes: * ‘s are from the net, Breeze’s are from my laptop

References

  • Comparing Spring AOP and AspectJ. (2017). https://www.baeldung.com/spring-aop-vs-aspectj/
  • Evans, B. (2013). The well-grounded Java developer. Manning.
  • Sundararaju, M. (2019). Introduction to SPF4J. https://www.baeldung.com/spf4j/