Pages

Monday, November 15, 2021

Java Flight Recorder: profiling Kotlin and Java apps with fun


Introduction

The goal of this article is to examine the possibilities of profiling Kotlin and a similar Java application with JMC/JFR to get a better understanding of their behavior compared to each other.
Nowadays the IT world often spells  terms like Site Reliability Engineering - SRE [5] or latencies, but how to measure this in an accurate way without relying on “random” samples ?  The answer to this question is out of the scope, but we can show what possibilities there are for understanding the behaviour of an application based on simple examples. 

Starting slowly: what is the JVM? The JVM stands for Java Virtual Machine. The JVM enables a computer to run Java programs, but not just only them. JVM supports all languages that are able to be compiled into the Java byte-code. All good so far, but what is the JFR ?

The letters JFR stand for the Java Flight Recorder, which is an event-based toolset build directly into the JVM.
Exciting, isn't it ? The JFR can provide a view to the JVM internals through emitted events and more…
The purpose of the article is to compare a Kotlin and a Java app and touch “hidden” compiled code compositions.  

Let’s briefly introduce Koltin as Java is known a bit longer. I bet a couple of million articles have already been written about Java, so it’s fair to have a short Kotlin introduction. 

Kotlin belongs to the JVM language family. It was introduced in 2011 as a new language for JVM and has been developed by JetBrains company.
 

The communicated goal was to become “better language” for the JVM. Kotlin has been successfully adopted by the Android community. In short, Kotlin is an object-oriented statistically typed language. It offers a set of quite handy features: data classes, concise, safety, smart casting, functional capabilities etc.  
Aside from the often spelled Kotlin "benefits",  it seems that nowadays more companies are thinking about or are already using a Kotlin stack for backend development. The reason for this may seem obvious but there are different perspectives. Such discussion may turn into the chicken-egg argumentation and it is out of the scope of this article. 

I have put the word "benefits" into the apostrophes intentionally as some nice concepts may look very neat in Kotlin but they may not be as optimized as Java’s counterpart (considering latest Java builds). The Java Ecosystem evolves pretty fast and Java stays the 1st JVM language and also the most optimized one. But nonetheless Kotlin has many nice constructs. Such constructs can help teams move faster without causing unwanted issues. An example of such an issue is the well known NPE  (Null Pointer Exception) .


Let’s profile  

The introduction is done. Let’s now compare the characteristics of a comparable Java & Kotlin apps using the JMC/JFR!

The setup goes first. For each measurement we use the current development state of the JMC/Java Flight Recorder - Early Access [1]. Each measurement is done in a 45 seconds time window. All examples  use OpenJDK 17 [4].


We consider the following 2 examples [2] to get some measurable data: 

  • Hot-Methods
  • Latencies

Each example uses similar JMC/JFR Events. Such events wrap equivalent sections of the application (Java/Kotlin) to obtain comparable results. The application Threads are also reduced in both cases in order to obtain comparable results. This means any detailed platform configuration is avoided as the goal is to compare basic platform configuration.  


1. Hot-Methods Example

The idea of this simple app is to have two “containers” held by the individual "worker". Those two containers each hold their own collection of numbers. The worker tries to find an intersection of those paired containers (see Img.1. in Kotlin, similar in Java)


Img.1.: example worker code - Kotlin

After running 1st not fixed code for 45 seconds we obtain for the Java app following results (see Img.2.)

Img.2.: Hot-Methods example: Java app - 431 400 events emitted

We repeat this process for the Kotlin version of the similar application for 45 seconds and obtain the following results (see, Img.3.)
Img.3.: Hot-Methods example: Kotlin app - 408 403 events emitted

Let's fix the code for both apps and observe the improvements in throughputs on both sides. We publish only the amount of JFR events that have been emitted. (Img.4.) as this is the identifier of the improvements that have been achieved.

Img.4.: Hot-Methods example Java, Kotlin comparison results


2. Latency Example

The second example is based on getting insights into latency that can be caused by many things. It could be unnecessary garbage collection, network issues or improper synchronization inside the application. In the current example we consider a problematic logger (Img.5.) that has a corrupted method log that is synchronized. It means it forces each tread to wait for it. 

Img.5.: Problematic Logger method

The Kotlin application uses the concept of Mutex (Kotlin Interface, coroutines library) to enforce synchronization. Let's take a look at the measurements. We try to answer the question of how many events can be emitted from the corrupted code in a 45 seconds time window (Img.6.: Java, Img.7.: Kotlin)

Img.6.: Java Problematic logger results, 222 JFR events
When we run the Kotlin application we receive almost identical results (Img.7)

Img.7.: Kotlin Problematic logger result, 222 JFR events
After the fixing a problematic logger we obtain the following results (Img.8.: Java, Img.9.: Kotlin). 
The results show that the blocking issue has been removed.
Img.8.: Java fixed logger, 957 JFR events
How is Kotlin app doing? 
Img.9.: Kotlin fixed logger, 808 JFR events


Conclusion

Watching the results we can observe that the results are almost very comparable. Important to note: the time window for the examples was just 45 seconds and the examples were more set up from a research perspective to highlight a specific issue.  We have seen the possibilities that are provided to us by the Java Platform in order to create our application better and understand the behavior in more detail. Mainly, by demonstrating the possibilities the Java Flight Recorder brought to us. We have also discovered, in a bit more details, a composition of the Kotlin itselves and coroutine framework (asynchronous and non-blocking lib)

 

Stay Tuned 

and Happy JVM coding !  

Stay Tuned 
and Happy JVM coding !


References:

  1. Java Mission Control Project
  2. JMC-JVM-Lang tutorial: profiling examples for different languages 
  3. JMC-tutorial examples by Markus Hirt
  4. OpenJDK 17
  5. Site Reliability Engineering - SRE

Sunday, October 10, 2021

Power of tmux and cheatsheet 


Welcome to the post dedicated to the handy tool named Terminal MUltiplerXer, shortly tmuxtmux it the terminal tool and its big advantages is that it allows to keep eye on multiple opened programs (“command-lines”) within one terminal. This comes handy  during an interaction with multiple remote servers or cloud environments.

To install tmux on MacOs using brew use the following command:

$brew install tmux 

To confirm that all is properly installed just verify in command-line by typing:

$tmux -V

output:
tmux 3.2a 

Used terms:

Prefix, <prefix>: The key combination that must be entered before entering the shortcut key. 
The default prefix for MacOs or <Ctrl+b> for  linux.  
Session: this is entity managed by tmux. The session can be attached/detached. 
When session is detached the program continues to run (very handy)
Window: The window exist inside the session. tmux allows to have multiple 
windows inside the one session.
Pane: The pane is the unit that exist inside the window instance. It is possible to 
have multiple panes inside the window

Start tmux with the session name

#display shortcut keys
$tmux list-keys

# start only tmux
$ tmux 

# start tmux with named session
$tmux new -s <session_name>

# exit session 
$ exit

# attach session by name
$tmux attach -t <session_name>

# detach session
<prefix> + d 
$tmux kill-session -t <session_namne>

# list all sessions
<prefix> + : + ls
$tmux ls

# rename session
<prefix> + $

# reseting tmux
$tmux kill-server
The following sections are divided into target domains:

Sessions

# list available session:
$tmux ls

#start new session with name: 
$tmux new -s <session-name>
<prefix> :new - start a new session

#attach to named session: 
$tmux a -t <session-name>

#kill session:
$tmux kill-ses -t <sessio_name>
$tmux kill-session -t <session-name>
#kill/delete all session except current
$tmux kill-session -a  
#kill/delete all session except <session -name>
$tmux kill-session -a -t <session-name> 
<prefix> $  #rename session
<prefix> d  #detach session
<prefix> s  #show all session

#attach to the last session
$tmux a -t <session_name>
 
Resizing panes
# command are written after pressing <prefilx>  followed by : (COLON CHARACTER)
<prefilx> + :resize-pane -U <empty or number of cels resize  up>
<prefilx> + :resize-pane -D <empty or number of cels resize down>
<prefilx> + :resize-pane -L <empty or number of cels resize left>
<prefilx> +:resize-pane -R <empty or number of cels resize right>
<prefilx> + :resize-pane -t 2 -D 10 <resize the pane 2 by number of cells down, D resp. U,L,P,R> 
Copy mode
<prefix> + :setw -g mode-keys vi    # use vi keys in buffer
<prefix> + [	        # enter copy mode
<prefix> + PgUp		    # enter copy mode and scroll one page up
<prefix> + q 		    # quit mode
<prefix> + g		    # go to top line
<prefix> + G		    # go to bottom line
<prefix> + h or l	    # move cursor left, right
<prefix> + j or k	    # move cursor up, down
<prefix> + w or b       # move cursor forward/backward one word at a time
<A-UP/DOWN/LEFT/RIGHT>	# scroll up/down
<prefix> + /			# search forward
<prefix> + ?			# search backward
<prefix> + n 			# next keyword occurrence
<prefix> + N			# previous keyword occurrence
<prefix> + <SPACEBAR>	# start selection
<prefix> + <ESC>		# clear selection
<prefix> + <ENTER>		# copy selection
<prefix> +	]		    # paste contents of buffer_0
<prefix> + :show-buffer	    # display buffer_0 contents
<prefix> + :capture-pane	# copy entire visible contents of pane to a buffer
<prefix> + :list-buffers	# show all buffers
<prefix> + :choose-buffer   # show all buffers and paste selected
<prefix> + :save-buffer buf.txt	 # save buffer contents to buf.txt
<prefix> + :delete-buffer -b 1	 # delete buffer_1 

Tabs(window)

<preix> + c  	# create tab
<preix> + w 	# list tab
<preix> + n 	# next tab
<preix> + p 	# previous tab
<preix> + f     # find tab
<preix> + , 	# name tab
<preix> + & 	# kill  tab
<preix> + .	    # move tab for a new, not occupied, number 
<preix> + t	    # display time clock in the active pane
<preix> + 0…9   # swich/select window by number
<preix> + : + swap-window -s 2 -t 1  # reorder window, swap window number 2 and 1
<preix> + : +swap-window -t -1 # move current window to the left by -1 
Panes
<prefix> + :setw synchronize-panes
<prefix> + <space>      # toggle between layouts
<prefix> + ;	        # toggle last active pane
<prefix> + %		    # vertical split
<prefix> + “            # horizontal split
<prefix> + o		    # swap panes
<prefix> + q		    # show pane numbers
<prefix> + q 0..9	    # select/switch pane by number
<prefix> + x		    # kill pane
<prefix> + z		    # toggle pane zoom
<prefix> + !		    # convert pane into a window
<prefix> + +		    # break pane into window  (investigate how)
<prefix> + -	        # restore pane from window (investigate how)
<prefix> + {	        # move current pane left
<prefix> + }	        # move current pane right
<prefix> + <ARROWS>     # switch to pane in the Arrow direction
<prefix> + <C-ARROWS>   # resize current pane with in direction 
Synchronize panes
# pretty useful when you plan to do similar action in all panes
<prefix> + :setw synchronize-panes on
<prefix> + :setw synchronize-panes off 
Misc
<prefix> +	:	            # enter command mode
<prefix> + :set -g OPTION 	# set OPTION for all sessions
<prefix> + :setw -g OPTION 	# set Option for all windows
<prefix> + :set mouse on	# enable mouse mode 
Help
$man tmux    #get man page
$ tmux list-keys
<prefix> + :list-keys
<prexi> ? 			    #list key bindings (shortcuts) 
Happy Tmuxing ! :) 
Link: wengneritsolutions - lab - tmux