[dev nexus 2024] a glance at the java performance toolbox

Speaker: Ana Maria Mihalceanu

@ammbra1508

For more, see the 2024 DevNexus Blog Table of Contents


What is performance

  • From user POV, how much work can do in a reasonable amount of time
  • From business, what is cost in computational resources needed to provide that user experience

Cloud

  • Practically unlmited resources
  • Reasonable cost

Container images

  • Tools to build container images – docker, jib, kaniko, buidah, etc
  • All started with a Dockerfile
  • Other tools arrived later to make easier

JLink

  • JRE stopped being included in Java 11
  • Can use jlink to include custom JRE with just modules need.
  • Can also omit man pages and header files.
  • Compress zip-9 offers the best compression.

Fine Tuning JVM Flags

  • Ergonomics docs – process for JVM/GC to tune performance measures
  • Tune min/max heap size with -Xms and -Xmx
  • Consider Java heap ratio

jcmd

  • Tracks native memory
  • Want available in container
  • Add jdk.jcmd module to application

Other commands/tools

  • Use jinfo to see what flags used in app
  • Helps when don’t know all flag names
  • Look for amount of memory reserved and amount used
  • Look for big values
  • JConsole – can see graph of memory use
  • jstat – garbage collection statistics
  • jmap – histogram of heap summary
  • Profiling with Java Flight Recorder – use when looking for something, not all the time. Need jdk.jfr module. Can specify how long to record.
  • Prometheus server – monitors/alerts on events
  • JFR Streaming – sends metrics to monitoring service

Sample app for testing at https://github.com/ammbra/performance-glance

My take

Good information and good demo. It was nice seeing the commands actually get used. Clear how to apply.

gson supports records

I like using records in Java and getting rid of the boilerplate on my immutable objects. I also like using gson (google’s serialization/deserialization library) for my lightweight JSON needs. All I need is an annotation to use a different field type. (For complex parsing I use Jackson)

Suppose I want parse this

var json = """
   {"first":"Mickey",
	"last":"Mouse",
	"birth_year":1928}
	""";

For example before records, I would write:

class Name {
	 private String first;
	 private String last;
     @SerializedName("birth_year") int birthYear;

     // boilerplate methods
}

I needed to use my IDE to generate a constructor, getters, and a toString(). And additionally, equals/hashCode if needed for that class.

In Java 17, I switched to records. I didn’t realize I could use them with gson annotations until recently. Turns out all I need to write is:

record Name(String first, 
   String last, 
   @SerializedName("birth_year") int birthYear) { }

The parsing code remains the same

var gson = new Gson();
var name = gson.fromJson(json, Name.class);
System.out.println(name);

[uberconf 2023] Structured Concurrency in Java

Speaker: Venkat Subramaniam

@venkat_s

For more, see the table of contents


Warning

  • Incubator phase feature
  • Anything can change.
  • Will be a year or more before release
  • use –enable-preview flag
  • Java prints out warning using incubator feature whenever run program

Executor Service

  • Since Java 5
  • Executors.newFixedThreadPool(x)
  • executorService.submit() -> logic()) – returns future. Call future.get() when done
  • executorService.shutdown()
  • executorService.awaitTermination(10, TImeout.SECONDS)

Structured Concurrency

  • Allow control of what happens on parallel
  • Parent handles/processes failures from children
  • Currently import jdk.incubator.concurrent – will move
  • StructuredTaskScopeShutdownOnFailure – invoke all
  • StructuredTaskScopeShutdownOnSuccess – invoke any
  • try (var scope = new StructuredTaskScope()) – want autoclose – or scope = StructuredTaskScopeShutdownOnSuccess() or scope = StructuredTaskScopeShutdownOnSuccess<String>()
  • scope.fork(() -> logic()) – makes child tasks, still returns a Future
  • scope.join() – don’t use – better to use a timeout so not unbounded waiting on children
  • scope.joinUntil(Instant.now().plusSeconds(50)) – better, uses timeout. waits for all children up to timeout Nice using Java date math
  • future.resultNow() – get result immediately. (vs get() which waits if not available)
  • scope.throwIfFailed(ex- > handle()) – deal with first failure

Scoped Values

  • ThreadLocal not useful in Spring because thread executing code not the same one that created the value
  • Scoped value, not scoped variable. Immutable
  • Hide the value instead of changing it
  • New value available in inner value. When get back out of that scope, see original value.
  • Doesn’t matter which thread runs the code because matters where you are in code.
  • Useful when calling a lambda which does a callback via third party code
  • Created ScopedValue field in the class that needs the data.
  • ScopedValue.newInstance() – placeholder, doesn’t have value yet
  • state.isBound() – whether has been set to a value
  • ScopedValue.where(state, “test”).run(lamba) – binds the value
  • state.get() – get value if bound. Blows up if not bound

My take

As an incubator feature, I knew nothing about this. It was great to learn about it from a Venkat talk. Different then the usual which is something I do know about and am learning deeper. I also enjoyed the airport code jokes: IAH (Houston – i am here), IAD (Dulles – i am delayed), and ORD (Chicago – ordeal). I’m always impressed Venkat can live code in front of so many people. I’d never seen incubator code in use. Nice it gets a temporary package name; can’t use it by accident. Venkat used IntelliJ to create a module. I don’t think I’ve ever seen him use IntelliJ :). Great audience questions on structured task scope. The scoped value thing made my head swim for a bit, but I get it now.